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