blob: 31fba5b86e44a85d743392053735c0edb48aa8da [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 Claytonf5e56de2010-09-14 23:36:40 +000011#include "lldb/Target/Process.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000012#include "lldb/Target/RegisterContext.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000013#include "lldb/Target/Thread.h"
Jason Molendaab4f1922010-10-25 11:12:07 +000014#include "lldb/Core/ConstString.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000015
16using namespace lldb;
17using namespace lldb_private;
18
19bool
20UnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const
21{
22 if (m_type != rhs.m_type)
23 return false;
24 if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
25 return m_location.offset == rhs.m_location.offset;
26 if (m_type == inOtherRegister)
27 return m_location.reg_num == rhs.m_location.reg_num;
28 if (m_type == atDWARFExpression || m_type == isDWARFExpression)
29 if (m_location.expr.length == rhs.m_location.expr.length)
30 return !memcmp (m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length);
31 return false;
32}
33
34// This function doesn't copy the dwarf expression bytes; they must remain in allocated
35// memory for the lifespan of this UnwindPlan object.
36void
37UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len)
38{
39 m_type = atDWARFExpression;
40 m_location.expr.opcodes = opcodes;
41 m_location.expr.length = len;
42}
43
44// This function doesn't copy the dwarf expression bytes; they must remain in allocated
45// memory for the lifespan of this UnwindPlan object.
46void
47UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len)
48{
49 m_type = isDWARFExpression;
50 m_location.expr.opcodes = opcodes;
51 m_location.expr.length = len;
52}
53
54void
55UnwindPlan::Row::RegisterLocation::SetUnspecified ()
56{
57 m_type = unspecified;
58}
59
60void
61UnwindPlan::Row::RegisterLocation::SetUndefined ()
62{
63 m_type = isUndefined;
64}
65
66void
67UnwindPlan::Row::RegisterLocation::SetSame ()
68{
69 m_type = isSame;
70}
71
72
73void
74UnwindPlan::Row::RegisterLocation::SetAtCFAPlusOffset (int32_t offset)
75{
76 m_type = atCFAPlusOffset;
77 m_location.offset = offset;
78}
79
80void
81UnwindPlan::Row::RegisterLocation::SetIsCFAPlusOffset (int32_t offset)
82{
83 m_type = isCFAPlusOffset;
84 m_location.offset = offset;
85}
86
87void
88UnwindPlan::Row::RegisterLocation::SetInRegister (uint32_t reg_num)
89{
90 m_type = inOtherRegister;
91 m_location.reg_num = reg_num;
92}
93
94void
95UnwindPlan::Row::RegisterLocation::Dump (Stream &s) const
96{
97 switch (m_type)
98 {
99 case unspecified:
100 s.Printf ("unspecified");
101 break;
102 case isUndefined:
103 s.Printf ("isUndefined");
104 break;
105 case isSame:
106 s.Printf ("isSame");
107 break;
108 case atCFAPlusOffset:
109 s.Printf ("atCFAPlusOffset %d", m_location.offset);
110 break;
111 case isCFAPlusOffset:
112 s.Printf ("isCFAPlusOffset %d", m_location.offset);
113 break;
114 case inOtherRegister:
115 s.Printf ("inOtherRegister %d", m_location.reg_num);
116 break;
117 case atDWARFExpression:
118 s.Printf ("atDWARFExpression");
119 break;
120 case isDWARFExpression:
121 s.Printf ("isDWARFExpression");
122 break;
123 }
124}
125
126void
127UnwindPlan::Row::Clear ()
128{
129 m_offset = 0;
130 m_cfa_reg_num = 0;
131 m_cfa_offset = 0;
132 m_register_locations.clear();
133}
134
135void
136UnwindPlan::Row::Dump (Stream& s, int register_kind, Thread* thread) const
137{
Greg Clayton5ccbd292011-01-06 22:15:06 +0000138 RegisterContext *reg_ctx = NULL;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000139 const RegisterInfo *rinfo = NULL;
140 int translated_regnum;
141 if (thread && thread->GetRegisterContext())
Greg Clayton5ccbd292011-01-06 22:15:06 +0000142 reg_ctx = thread->GetRegisterContext().get();
143
Jason Molendafbcb7f22010-09-10 07:49:16 +0000144 s.Printf ("offset %ld, CFA reg ", (long) GetOffset());
Greg Clayton5ccbd292011-01-06 22:15:06 +0000145 if (reg_ctx
146 && (translated_regnum = reg_ctx->ConvertRegisterKindToRegisterNumber (register_kind, GetCFARegister())) != -1
147 && (rinfo = reg_ctx->GetRegisterInfoAtIndex (translated_regnum)) != NULL
Jason Molendafbcb7f22010-09-10 07:49:16 +0000148 && rinfo->name != NULL
149 && rinfo->name[0] != '\0')
150 {
151 s.Printf ("%s, ", rinfo->name);
152 }
153 else
154 {
155 s.Printf ("%d, ", (int)(int) GetCFARegister());
156 }
157 s.Printf ("CFA offset %d", (int) GetCFAOffset ());
158 for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx)
159 {
160 s.Printf (" [");
161 bool printed_name = false;
Greg Clayton5ccbd292011-01-06 22:15:06 +0000162 if (reg_ctx)
Jason Molendafbcb7f22010-09-10 07:49:16 +0000163 {
Greg Clayton5ccbd292011-01-06 22:15:06 +0000164 translated_regnum = reg_ctx->ConvertRegisterKindToRegisterNumber (register_kind, idx->first);
165 rinfo = reg_ctx->GetRegisterInfoAtIndex (translated_regnum);
Jason Molendafbcb7f22010-09-10 07:49:16 +0000166 if (rinfo && rinfo->name)
167 {
168 s.Printf ("%s ", rinfo->name);
169 printed_name = true;
170 }
171 }
172 if (!printed_name)
173 {
174 s.Printf ("reg %d ", idx->first);
175 }
176 idx->second.Dump(s);
177 s.Printf ("]");
178 }
179 s.Printf ("\n");
180}
181
182UnwindPlan::Row::Row() :
183 m_offset(0),
184 m_cfa_reg_num(0),
185 m_cfa_offset(0),
186 m_register_locations()
187{
188}
189
190bool
191UnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLocation& register_location) const
192{
193 collection::const_iterator pos = m_register_locations.find(reg_num);
194 if (pos != m_register_locations.end())
195 {
196 register_location = pos->second;
197 return true;
198 }
199 return false;
200}
201
202void
203UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location)
204{
205 m_register_locations[reg_num] = register_location;
206}
207
208
209void
210UnwindPlan::AppendRow (const UnwindPlan::Row &row)
211{
212 if (m_row_list.empty() || m_row_list.back().GetOffset() != row.GetOffset())
213 m_row_list.push_back(row);
214 else
215 m_row_list.back() = row;
216}
217
218const UnwindPlan::Row *
219UnwindPlan::GetRowForFunctionOffset (int offset) const
220{
221 const UnwindPlan::Row *rowp = NULL;
Jason Molendaab4f1922010-10-25 11:12:07 +0000222 if (offset == -1 && m_row_list.size() > 0)
223 {
224 return &m_row_list[m_row_list.size() - 1];
225 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000226 for (int i = 0; i < m_row_list.size(); ++i)
227 {
228 if (m_row_list[i].GetOffset() <= offset)
229 {
230 rowp = &m_row_list[i];
231 }
232 else
233 {
234 break;
235 }
236 }
237 return rowp;
238}
239
240bool
241UnwindPlan::IsValidRowIndex (uint32_t idx) const
242{
243 return idx < m_row_list.size();
244}
245
246const UnwindPlan::Row&
247UnwindPlan::GetRowAtIndex (uint32_t idx) const
248{
249 // You must call IsValidRowIndex(idx) first before calling this!!!
250 return m_row_list[idx];
251}
252
253int
254UnwindPlan::GetRowCount () const
255{
256 return m_row_list.size ();
257}
258
259void
260UnwindPlan::SetRegisterKind (uint32_t rk)
261{
262 m_register_kind = rk;
263}
264
265uint32_t
266UnwindPlan::GetRegisterKind (void) const
267{
268 return m_register_kind;
269}
270
271void
272UnwindPlan::SetPlanValidAddressRange (const AddressRange& range)
273{
Jason Molendaab4f1922010-10-25 11:12:07 +0000274 if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
275 {
276 m_plan_valid_address_range = range;
277 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000278// .GetBaseAddress() = addr;
279// m_plan_valid_address_range.SetByteSize (range.GetByteSize());
280}
281
282bool
283UnwindPlan::PlanValidAtAddress (Address addr)
284{
Jason Molendaab4f1922010-10-25 11:12:07 +0000285 if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0)
Jason Molendafbcb7f22010-09-10 07:49:16 +0000286 return true;
287
Jason Molenda59762002010-11-04 00:53:20 +0000288 if (!addr.IsValid())
289 return true;
290
Jason Molendafbcb7f22010-09-10 07:49:16 +0000291 if (m_plan_valid_address_range.ContainsFileAddress (addr))
292 return true;
293
294 return false;
295}
296
297void
Greg Claytonf5e56de2010-09-14 23:36:40 +0000298UnwindPlan::Dump (Stream& s, Thread *thread) const
Jason Molendafbcb7f22010-09-10 07:49:16 +0000299{
Jason Molendaab4f1922010-10-25 11:12:07 +0000300 if (!m_source_name.IsEmpty())
301 {
302 s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString());
303 }
304 if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0)
305 {
306 s.Printf ("Address range of this UnwindPlan: ");
307 m_plan_valid_address_range.Dump (&s, &thread->GetProcess().GetTarget(), Address::DumpStyleSectionNameOffset);
308 s.Printf ("\n");
309 }
310 else
311 {
312 s.Printf ("No valid address range recorded for this UnwindPlan.\n");
313 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000314 s.Printf ("UnwindPlan register kind %d", m_register_kind);
315 switch (m_register_kind)
316 {
317 case eRegisterKindGCC: s.Printf (" [eRegisterKindGCC]"); break;
318 case eRegisterKindDWARF: s.Printf (" [eRegisterKindDWARF]"); break;
319 case eRegisterKindGeneric: s.Printf (" [eRegisterKindGeneric]"); break;
320 case eRegisterKindGDB: s.Printf (" [eRegisterKindGDB]"); break;
321 case eRegisterKindLLDB: s.Printf (" [eRegisterKindLLDB]"); break;
322 default: break;
323 }
324 s.Printf ("\n");
325 for (int i = 0; IsValidRowIndex (i); i++)
326 {
327 s.Printf ("UnwindPlan row at index %d: ", i);
328 m_row_list[i].Dump(s, m_register_kind, thread);
329 }
330}
Jason Molendaab4f1922010-10-25 11:12:07 +0000331
332void
333UnwindPlan::SetSourceName (const char *source)
334{
335 m_source_name = ConstString (source);
336}
337
338ConstString
339UnwindPlan::GetSourceName () const
340{
341 return m_source_name;
342}