blob: ff0468e314d8b1f9f988d5b4e6a88c9c92c39f7d [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"
Jason Molenda61cd0722013-12-03 04:46:27 +000013#include "lldb/Core/Log.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000014#include "lldb/Target/Process.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000015#include "lldb/Target/RegisterContext.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000016#include "lldb/Target/Thread.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000017
18using namespace lldb;
19using namespace lldb_private;
20
21bool
22UnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const
23{
Greg Clayton31f1d2f2011-05-11 18:39:18 +000024 if (m_type == rhs.m_type)
25 {
26 switch (m_type)
27 {
28 case unspecified:
29 case undefined:
30 case same:
31 return true;
32
33 case atCFAPlusOffset:
34 case isCFAPlusOffset:
35 return m_location.offset == rhs.m_location.offset;
36
37 case inOtherRegister:
38 return m_location.reg_num == rhs.m_location.reg_num;
39
40 case atDWARFExpression:
41 case isDWARFExpression:
42 if (m_location.expr.length == rhs.m_location.expr.length)
43 return !memcmp (m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length);
44 break;
45 }
46 }
Jason Molendafbcb7f22010-09-10 07:49:16 +000047 return false;
48}
49
50// This function doesn't copy the dwarf expression bytes; they must remain in allocated
51// memory for the lifespan of this UnwindPlan object.
52void
53UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len)
54{
55 m_type = atDWARFExpression;
56 m_location.expr.opcodes = opcodes;
57 m_location.expr.length = len;
58}
59
60// This function doesn't copy the dwarf expression bytes; they must remain in allocated
61// memory for the lifespan of this UnwindPlan object.
62void
63UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len)
64{
65 m_type = isDWARFExpression;
66 m_location.expr.opcodes = opcodes;
67 m_location.expr.length = len;
68}
69
70void
Greg Clayton31f1d2f2011-05-11 18:39:18 +000071UnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_plan, const UnwindPlan::Row* row, Thread* thread, bool verbose) const
Jason Molendafbcb7f22010-09-10 07:49:16 +000072{
73 switch (m_type)
74 {
75 case unspecified:
Greg Clayton31f1d2f2011-05-11 18:39:18 +000076 if (verbose)
77 s.PutCString ("=<unspec>");
78 else
79 s.PutCString ("=!");
Jason Molendafbcb7f22010-09-10 07:49:16 +000080 break;
Greg Clayton31f1d2f2011-05-11 18:39:18 +000081 case undefined:
82 if (verbose)
83 s.PutCString ("=<undef>");
84 else
85 s.PutCString ("=?");
Jason Molendafbcb7f22010-09-10 07:49:16 +000086 break;
Greg Clayton31f1d2f2011-05-11 18:39:18 +000087 case same:
88 s.PutCString ("= <same>");
Jason Molendafbcb7f22010-09-10 07:49:16 +000089 break;
Greg Clayton31f1d2f2011-05-11 18:39:18 +000090
Jason Molendafbcb7f22010-09-10 07:49:16 +000091 case atCFAPlusOffset:
Jason Molendafbcb7f22010-09-10 07:49:16 +000092 case isCFAPlusOffset:
Greg Clayton31f1d2f2011-05-11 18:39:18 +000093 {
94 s.PutChar('=');
95 if (m_type == atCFAPlusOffset)
96 s.PutChar('[');
97 if (verbose)
98 s.Printf ("CFA%+d", m_location.offset);
99
100 if (unwind_plan && row)
101 {
102 const uint32_t cfa_reg = row->GetCFARegister();
103 const RegisterInfo *cfa_reg_info = unwind_plan->GetRegisterInfo (thread, cfa_reg);
104 const int32_t offset = row->GetCFAOffset() + m_location.offset;
105 if (verbose)
106 {
107 if (cfa_reg_info)
108 s.Printf (" (%s%+d)", cfa_reg_info->name, offset);
109 else
Johnny Chend397dc82011-08-12 00:02:24 +0000110 s.Printf (" (reg(%u)%+d)", cfa_reg, offset);
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000111 }
112 else
113 {
114 if (cfa_reg_info)
115 s.Printf ("%s", cfa_reg_info->name);
116 else
Johnny Chend397dc82011-08-12 00:02:24 +0000117 s.Printf ("reg(%u)", cfa_reg);
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000118 if (offset != 0)
119 s.Printf ("%+d", offset);
120 }
121 }
122 if (m_type == atCFAPlusOffset)
123 s.PutChar(']');
124 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000125 break;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000126
Jason Molendafbcb7f22010-09-10 07:49:16 +0000127 case inOtherRegister:
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000128 {
Ed Masted4612ad2014-04-20 13:17:36 +0000129 const RegisterInfo *other_reg_info = nullptr;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000130 if (unwind_plan)
131 other_reg_info = unwind_plan->GetRegisterInfo (thread, m_location.reg_num);
132 if (other_reg_info)
133 s.Printf ("=%s", other_reg_info->name);
134 else
135 s.Printf ("=reg(%u)", m_location.reg_num);
136 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000137 break;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000138
Jason Molendafbcb7f22010-09-10 07:49:16 +0000139 case atDWARFExpression:
Jason Molendafbcb7f22010-09-10 07:49:16 +0000140 case isDWARFExpression:
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000141 {
142 s.PutChar('=');
143 if (m_type == atDWARFExpression)
144 s.PutCString("[dwarf-expr]");
145 else
146 s.PutCString("dwarf-expr");
147 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000148 break;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000149
Jason Molendafbcb7f22010-09-10 07:49:16 +0000150 }
151}
152
153void
154UnwindPlan::Row::Clear ()
155{
156 m_offset = 0;
Jason Molenda60f0bd42012-10-26 06:08:58 +0000157 m_cfa_reg_num = LLDB_INVALID_REGNUM;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000158 m_cfa_offset = 0;
159 m_register_locations.clear();
160}
161
162void
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000163UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, addr_t base_addr) const
Jason Molendafbcb7f22010-09-10 07:49:16 +0000164{
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000165 const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo (thread, GetCFARegister());
Greg Clayton5ccbd292011-01-06 22:15:06 +0000166
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000167 if (base_addr != LLDB_INVALID_ADDRESS)
Daniel Malead01b2952012-11-29 21:49:15 +0000168 s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
Jason Molendafbcb7f22010-09-10 07:49:16 +0000169 else
Daniel Malead01b2952012-11-29 21:49:15 +0000170 s.Printf ("0x%8.8" PRIx64 ": CFA=", GetOffset());
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000171
172 if (reg_info)
173 s.Printf ("%s", reg_info->name);
174 else
175 s.Printf ("reg(%u)", GetCFARegister());
Jason Molenda42107132012-08-10 20:52:59 +0000176 s.Printf ("%+3d => ", GetCFAOffset ());
Jason Molendafbcb7f22010-09-10 07:49:16 +0000177 for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx)
178 {
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000179 reg_info = unwind_plan->GetRegisterInfo (thread, idx->first);
180 if (reg_info)
181 s.Printf ("%s", reg_info->name);
182 else
183 s.Printf ("reg(%u)", idx->first);
184 const bool verbose = false;
185 idx->second.Dump(s, unwind_plan, this, thread, verbose);
186 s.PutChar (' ');
Jason Molendafbcb7f22010-09-10 07:49:16 +0000187 }
Greg Clayton877aaa52011-01-08 21:19:00 +0000188 s.EOL();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000189}
190
191UnwindPlan::Row::Row() :
192 m_offset(0),
Jason Molenda60f0bd42012-10-26 06:08:58 +0000193 m_cfa_reg_num(LLDB_INVALID_REGNUM),
Jason Molendafbcb7f22010-09-10 07:49:16 +0000194 m_cfa_offset(0),
195 m_register_locations()
196{
197}
198
199bool
200UnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLocation& register_location) const
201{
202 collection::const_iterator pos = m_register_locations.find(reg_num);
203 if (pos != m_register_locations.end())
204 {
205 register_location = pos->second;
206 return true;
207 }
208 return false;
209}
210
211void
212UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location)
213{
214 m_register_locations[reg_num] = register_location;
215}
216
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000217bool
218UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace)
219{
220 if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
221 return false;
222 RegisterLocation reg_loc;
223 reg_loc.SetAtCFAPlusOffset(offset);
224 m_register_locations[reg_num] = reg_loc;
225 return true;
226}
227
228bool
229UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace)
230{
231 if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
232 return false;
233 RegisterLocation reg_loc;
234 reg_loc.SetIsCFAPlusOffset(offset);
235 m_register_locations[reg_num] = reg_loc;
236 return true;
237}
238
239bool
240UnwindPlan::Row::SetRegisterLocationToUndefined (uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified)
241{
242 collection::iterator pos = m_register_locations.find(reg_num);
243 collection::iterator end = m_register_locations.end();
244
245 if (pos != end)
246 {
247 if (!can_replace)
248 return false;
249 if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
250 return false;
251 }
252 RegisterLocation reg_loc;
253 reg_loc.SetUndefined();
254 m_register_locations[reg_num] = reg_loc;
255 return true;
256}
257
258bool
259UnwindPlan::Row::SetRegisterLocationToUnspecified (uint32_t reg_num, bool can_replace)
260{
261 if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
262 return false;
263 RegisterLocation reg_loc;
264 reg_loc.SetUnspecified();
265 m_register_locations[reg_num] = reg_loc;
266 return true;
267}
268
269bool
270UnwindPlan::Row::SetRegisterLocationToRegister (uint32_t reg_num,
271 uint32_t other_reg_num,
272 bool can_replace)
273{
274 if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
275 return false;
276 RegisterLocation reg_loc;
277 reg_loc.SetInRegister(other_reg_num);
278 m_register_locations[reg_num] = reg_loc;
279 return true;
280}
281
282bool
283UnwindPlan::Row::SetRegisterLocationToSame (uint32_t reg_num, bool must_replace)
284{
285 if (must_replace && m_register_locations.find(reg_num) == m_register_locations.end())
286 return false;
287 RegisterLocation reg_loc;
288 reg_loc.SetSame();
289 m_register_locations[reg_num] = reg_loc;
290 return true;
291}
292
293void
294UnwindPlan::Row::SetCFARegister (uint32_t reg_num)
295{
296 m_cfa_reg_num = reg_num;
297}
Jason Molendafbcb7f22010-09-10 07:49:16 +0000298
Jason Molenda24a83782012-07-17 01:57:24 +0000299bool
300UnwindPlan::Row::operator == (const UnwindPlan::Row& rhs) const
301{
302 if (m_offset != rhs.m_offset || m_cfa_reg_num != rhs.m_cfa_reg_num || m_cfa_offset != rhs.m_cfa_offset)
303 return false;
Greg Clayton358a7892012-07-18 20:37:53 +0000304 return m_register_locations == rhs.m_register_locations;
Jason Molenda24a83782012-07-17 01:57:24 +0000305}
306
Jason Molendafbcb7f22010-09-10 07:49:16 +0000307void
Greg Clayton358a7892012-07-18 20:37:53 +0000308UnwindPlan::AppendRow (const UnwindPlan::RowSP &row_sp)
Jason Molendafbcb7f22010-09-10 07:49:16 +0000309{
Greg Clayton358a7892012-07-18 20:37:53 +0000310 if (m_row_list.empty() || m_row_list.back()->GetOffset() != row_sp->GetOffset())
311 m_row_list.push_back(row_sp);
Jason Molendafbcb7f22010-09-10 07:49:16 +0000312 else
Greg Clayton358a7892012-07-18 20:37:53 +0000313 m_row_list.back() = row_sp;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000314}
315
Todd Fiala05625242014-08-25 20:29:09 +0000316void
317UnwindPlan::InsertRow (const UnwindPlan::RowSP &row_sp)
318{
319 collection::iterator it = m_row_list.begin();
320 while (it != m_row_list.end()) {
321 RowSP row = *it;
322 if (row->GetOffset() > row_sp->GetOffset())
323 break;
324 it++;
325 }
326 m_row_list.insert(it, row_sp);
327}
328
Jason Molenda1d42c7b2012-07-14 04:52:53 +0000329UnwindPlan::RowSP
Jason Molendafbcb7f22010-09-10 07:49:16 +0000330UnwindPlan::GetRowForFunctionOffset (int offset) const
331{
Jason Molenda1d42c7b2012-07-14 04:52:53 +0000332 RowSP row;
Greg Clayton877aaa52011-01-08 21:19:00 +0000333 if (!m_row_list.empty())
Jason Molendaab4f1922010-10-25 11:12:07 +0000334 {
Greg Clayton877aaa52011-01-08 21:19:00 +0000335 if (offset == -1)
Jason Molenda1d42c7b2012-07-14 04:52:53 +0000336 row = m_row_list.back();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000337 else
338 {
Greg Clayton877aaa52011-01-08 21:19:00 +0000339 collection::const_iterator pos, end = m_row_list.end();
340 for (pos = m_row_list.begin(); pos != end; ++pos)
341 {
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +0000342 if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset))
Jason Molenda1d42c7b2012-07-14 04:52:53 +0000343 row = *pos;
Greg Clayton877aaa52011-01-08 21:19:00 +0000344 else
345 break;
346 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000347 }
348 }
Jason Molenda1d42c7b2012-07-14 04:52:53 +0000349 return row;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000350}
351
352bool
353UnwindPlan::IsValidRowIndex (uint32_t idx) const
354{
355 return idx < m_row_list.size();
356}
357
Jason Molenda1d42c7b2012-07-14 04:52:53 +0000358const UnwindPlan::RowSP
Jason Molendafbcb7f22010-09-10 07:49:16 +0000359UnwindPlan::GetRowAtIndex (uint32_t idx) const
360{
361 // You must call IsValidRowIndex(idx) first before calling this!!!
Greg Clayton877aaa52011-01-08 21:19:00 +0000362 assert (idx < m_row_list.size());
Jason Molendafbcb7f22010-09-10 07:49:16 +0000363 return m_row_list[idx];
364}
365
Jason Molenda1d42c7b2012-07-14 04:52:53 +0000366const UnwindPlan::RowSP
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000367UnwindPlan::GetLastRow () const
368{
369 // You must call GetRowCount() first to make sure there is at least one row
370 assert (!m_row_list.empty());
371 return m_row_list.back();
372}
373
Jason Molendafbcb7f22010-09-10 07:49:16 +0000374int
375UnwindPlan::GetRowCount () const
376{
377 return m_row_list.size ();
378}
379
380void
Jason Molendafbcb7f22010-09-10 07:49:16 +0000381UnwindPlan::SetPlanValidAddressRange (const AddressRange& range)
382{
Jason Molendaab4f1922010-10-25 11:12:07 +0000383 if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
Jason Molendaab4f1922010-10-25 11:12:07 +0000384 m_plan_valid_address_range = range;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000385}
386
387bool
388UnwindPlan::PlanValidAtAddress (Address addr)
389{
Jason Molenda61cd0722013-12-03 04:46:27 +0000390 // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
391 if (GetRowCount() == 0)
392 {
393 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
394 if (log)
Jason Molenda135e55f2013-12-03 21:59:39 +0000395 {
396 StreamString s;
Ed Masted4612ad2014-04-20 13:17:36 +0000397 if (addr.Dump (&s, nullptr, Address::DumpStyleSectionNameOffset))
Jason Molenda135e55f2013-12-03 21:59:39 +0000398 {
399 log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s' at address %s",
400 m_source_name.GetCString(), s.GetData());
401 }
402 else
403 {
404 log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
405 m_source_name.GetCString());
406 }
407 }
Jason Molenda61cd0722013-12-03 04:46:27 +0000408 return false;
409 }
410
411 // If the 0th Row of unwind instructions is missing, or if it doesn't provide
412 // a register to use to find the Canonical Frame Address, this is not a valid UnwindPlan.
Ed Masted4612ad2014-04-20 13:17:36 +0000413 if (GetRowAtIndex(0).get() == nullptr || GetRowAtIndex(0)->GetCFARegister() == LLDB_INVALID_REGNUM)
Jason Molenda61cd0722013-12-03 04:46:27 +0000414 {
415 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
416 if (log)
Jason Molenda135e55f2013-12-03 21:59:39 +0000417 {
418 StreamString s;
Ed Masted4612ad2014-04-20 13:17:36 +0000419 if (addr.Dump (&s, nullptr, Address::DumpStyleSectionNameOffset))
Jason Molenda135e55f2013-12-03 21:59:39 +0000420 {
421 log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s' at address %s",
422 m_source_name.GetCString(), s.GetData());
423 }
424 else
425 {
426 log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s'",
427 m_source_name.GetCString());
428 }
429 }
Jason Molenda61cd0722013-12-03 04:46:27 +0000430 return false;
431 }
432
Jason Molendaab4f1922010-10-25 11:12:07 +0000433 if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0)
Jason Molendafbcb7f22010-09-10 07:49:16 +0000434 return true;
435
Jason Molenda59762002010-11-04 00:53:20 +0000436 if (!addr.IsValid())
437 return true;
438
Jason Molendafbcb7f22010-09-10 07:49:16 +0000439 if (m_plan_valid_address_range.ContainsFileAddress (addr))
440 return true;
441
442 return false;
443}
444
445void
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000446UnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const
Jason Molendafbcb7f22010-09-10 07:49:16 +0000447{
Jason Molendaab4f1922010-10-25 11:12:07 +0000448 if (!m_source_name.IsEmpty())
449 {
450 s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString());
451 }
452 if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0)
453 {
Greg Clayton877aaa52011-01-08 21:19:00 +0000454 s.PutCString ("Address range of this UnwindPlan: ");
Greg Clayton1ac04c32012-02-21 00:09:25 +0000455 TargetSP target_sp(thread->CalculateTarget());
456 m_plan_valid_address_range.Dump (&s, target_sp.get(), Address::DumpStyleSectionNameOffset);
Greg Clayton877aaa52011-01-08 21:19:00 +0000457 s.EOL();
Jason Molendaab4f1922010-10-25 11:12:07 +0000458 }
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000459 collection::const_iterator pos, begin = m_row_list.begin(), end = m_row_list.end();
460 for (pos = begin; pos != end; ++pos)
Jason Molendafbcb7f22010-09-10 07:49:16 +0000461 {
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000462 s.Printf ("row[%u]: ", (uint32_t)std::distance (begin, pos));
Jason Molenda1d42c7b2012-07-14 04:52:53 +0000463 (*pos)->Dump(s, this, thread, base_addr);
Jason Molendafbcb7f22010-09-10 07:49:16 +0000464 }
465}
Jason Molendaab4f1922010-10-25 11:12:07 +0000466
467void
468UnwindPlan::SetSourceName (const char *source)
469{
470 m_source_name = ConstString (source);
471}
472
473ConstString
474UnwindPlan::GetSourceName () const
475{
476 return m_source_name;
477}
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000478
479const RegisterInfo *
480UnwindPlan::GetRegisterInfo (Thread* thread, uint32_t unwind_reg) const
481{
482 if (thread)
483 {
484 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
485 if (reg_ctx)
486 {
487 uint32_t reg;
488 if (m_register_kind == eRegisterKindLLDB)
489 reg = unwind_reg;
490 else
491 reg = reg_ctx->ConvertRegisterKindToRegisterNumber (m_register_kind, unwind_reg);
492 if (reg != LLDB_INVALID_REGNUM)
493 return reg_ctx->GetRegisterInfoAtIndex (reg);
494 }
495 }
Ed Masted4612ad2014-04-20 13:17:36 +0000496 return nullptr;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000497}
498