blob: cc4dcf24fc6d62fd4dce330a0688ae0956c4dca3 [file] [log] [blame]
Jason Molenda3a4ea242010-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 Claytoneea26402010-09-14 23:36:40 +000011#include "lldb/Target/Process.h"
Jason Molenda3a4ea242010-09-10 07:49:16 +000012#include "lldb/Target/RegisterContext.h"
Greg Claytoneea26402010-09-14 23:36:40 +000013#include "lldb/Target/Thread.h"
Jason Molenda3a4ea242010-09-10 07:49:16 +000014
15using namespace lldb;
16using namespace lldb_private;
17
18bool
19UnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const
20{
21 if (m_type != rhs.m_type)
22 return false;
23 if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
24 return m_location.offset == rhs.m_location.offset;
25 if (m_type == inOtherRegister)
26 return m_location.reg_num == rhs.m_location.reg_num;
27 if (m_type == atDWARFExpression || m_type == isDWARFExpression)
28 if (m_location.expr.length == rhs.m_location.expr.length)
29 return !memcmp (m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length);
30 return false;
31}
32
33// This function doesn't copy the dwarf expression bytes; they must remain in allocated
34// memory for the lifespan of this UnwindPlan object.
35void
36UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len)
37{
38 m_type = atDWARFExpression;
39 m_location.expr.opcodes = opcodes;
40 m_location.expr.length = len;
41}
42
43// This function doesn't copy the dwarf expression bytes; they must remain in allocated
44// memory for the lifespan of this UnwindPlan object.
45void
46UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len)
47{
48 m_type = isDWARFExpression;
49 m_location.expr.opcodes = opcodes;
50 m_location.expr.length = len;
51}
52
53void
54UnwindPlan::Row::RegisterLocation::SetUnspecified ()
55{
56 m_type = unspecified;
57}
58
59void
60UnwindPlan::Row::RegisterLocation::SetUndefined ()
61{
62 m_type = isUndefined;
63}
64
65void
66UnwindPlan::Row::RegisterLocation::SetSame ()
67{
68 m_type = isSame;
69}
70
71
72void
73UnwindPlan::Row::RegisterLocation::SetAtCFAPlusOffset (int32_t offset)
74{
75 m_type = atCFAPlusOffset;
76 m_location.offset = offset;
77}
78
79void
80UnwindPlan::Row::RegisterLocation::SetIsCFAPlusOffset (int32_t offset)
81{
82 m_type = isCFAPlusOffset;
83 m_location.offset = offset;
84}
85
86void
87UnwindPlan::Row::RegisterLocation::SetInRegister (uint32_t reg_num)
88{
89 m_type = inOtherRegister;
90 m_location.reg_num = reg_num;
91}
92
93void
94UnwindPlan::Row::RegisterLocation::Dump (Stream &s) const
95{
96 switch (m_type)
97 {
98 case unspecified:
99 s.Printf ("unspecified");
100 break;
101 case isUndefined:
102 s.Printf ("isUndefined");
103 break;
104 case isSame:
105 s.Printf ("isSame");
106 break;
107 case atCFAPlusOffset:
108 s.Printf ("atCFAPlusOffset %d", m_location.offset);
109 break;
110 case isCFAPlusOffset:
111 s.Printf ("isCFAPlusOffset %d", m_location.offset);
112 break;
113 case inOtherRegister:
114 s.Printf ("inOtherRegister %d", m_location.reg_num);
115 break;
116 case atDWARFExpression:
117 s.Printf ("atDWARFExpression");
118 break;
119 case isDWARFExpression:
120 s.Printf ("isDWARFExpression");
121 break;
122 }
123}
124
125void
126UnwindPlan::Row::Clear ()
127{
128 m_offset = 0;
129 m_cfa_reg_num = 0;
130 m_cfa_offset = 0;
131 m_register_locations.clear();
132}
133
134void
135UnwindPlan::Row::Dump (Stream& s, int register_kind, Thread* thread) const
136{
137 RegisterContext *rctx = NULL;
138 const RegisterInfo *rinfo = NULL;
139 int translated_regnum;
140 if (thread && thread->GetRegisterContext())
141 {
142 rctx = thread->GetRegisterContext();
143 }
144 s.Printf ("offset %ld, CFA reg ", (long) GetOffset());
145 if (rctx
146 && (translated_regnum = rctx->ConvertRegisterKindToRegisterNumber (register_kind, GetCFARegister())) != -1
147 && (rinfo = rctx->GetRegisterInfoAtIndex (translated_regnum)) != NULL
148 && 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;
162 if (thread && thread->GetRegisterContext())
163 {
164 rctx = thread->GetRegisterContext();
165 translated_regnum = rctx->ConvertRegisterKindToRegisterNumber (register_kind, idx->first);
166 rinfo = rctx->GetRegisterInfoAtIndex (translated_regnum);
167 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);
178 s.Printf ("]");
179 }
180 s.Printf ("\n");
181}
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{
222 const UnwindPlan::Row *rowp = NULL;
223 for (int i = 0; i < m_row_list.size(); ++i)
224 {
225 if (m_row_list[i].GetOffset() <= offset)
226 {
227 rowp = &m_row_list[i];
228 }
229 else
230 {
231 break;
232 }
233 }
234 return rowp;
235}
236
237bool
238UnwindPlan::IsValidRowIndex (uint32_t idx) const
239{
240 return idx < m_row_list.size();
241}
242
243const UnwindPlan::Row&
244UnwindPlan::GetRowAtIndex (uint32_t idx) const
245{
246 // You must call IsValidRowIndex(idx) first before calling this!!!
247 return m_row_list[idx];
248}
249
250int
251UnwindPlan::GetRowCount () const
252{
253 return m_row_list.size ();
254}
255
256void
257UnwindPlan::SetRegisterKind (uint32_t rk)
258{
259 m_register_kind = rk;
260}
261
262uint32_t
263UnwindPlan::GetRegisterKind (void) const
264{
265 return m_register_kind;
266}
267
268void
269UnwindPlan::SetPlanValidAddressRange (const AddressRange& range)
270{
271 m_plan_valid_address_range = range;
272// .GetBaseAddress() = addr;
273// m_plan_valid_address_range.SetByteSize (range.GetByteSize());
274}
275
276bool
277UnwindPlan::PlanValidAtAddress (Address addr)
278{
279 if (!m_plan_valid_address_range.GetBaseAddress().IsValid())
280 return true;
281
282 if (m_plan_valid_address_range.ContainsFileAddress (addr))
283 return true;
284
285 return false;
286}
287
288void
Greg Claytoneea26402010-09-14 23:36:40 +0000289UnwindPlan::Dump (Stream& s, Thread *thread) const
Jason Molenda3a4ea242010-09-10 07:49:16 +0000290{
291 s.Printf ("Address range of this UnwindPlan: ");
Greg Claytoneea26402010-09-14 23:36:40 +0000292 m_plan_valid_address_range.Dump (&s, &thread->GetProcess().GetTarget(), Address::DumpStyleSectionNameOffset);
Jason Molenda3a4ea242010-09-10 07:49:16 +0000293 s.Printf ("\n");
294 s.Printf ("UnwindPlan register kind %d", m_register_kind);
295 switch (m_register_kind)
296 {
297 case eRegisterKindGCC: s.Printf (" [eRegisterKindGCC]"); break;
298 case eRegisterKindDWARF: s.Printf (" [eRegisterKindDWARF]"); break;
299 case eRegisterKindGeneric: s.Printf (" [eRegisterKindGeneric]"); break;
300 case eRegisterKindGDB: s.Printf (" [eRegisterKindGDB]"); break;
301 case eRegisterKindLLDB: s.Printf (" [eRegisterKindLLDB]"); break;
302 default: break;
303 }
304 s.Printf ("\n");
305 for (int i = 0; IsValidRowIndex (i); i++)
306 {
307 s.Printf ("UnwindPlan row at index %d: ", i);
308 m_row_list[i].Dump(s, m_register_kind, thread);
309 }
310}