blob: 0e084cda98c94f81b6efb5220e32ad86a0c30f23 [file] [log] [blame]
Jason Molendafbcb7f22010-09-10 07:49:16 +00001//===-- UnwindPlan.cpp ----------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Jason Molendafbcb7f22010-09-10 07:49:16 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Symbol/UnwindPlan.h"
Greg Clayton79ea8782011-04-26 23:48:45 +000010
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"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000014#include "lldb/Utility/ConstString.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000015#include "lldb/Utility/Log.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000016
17using namespace lldb;
18using namespace lldb_private;
19
Kate Stoneb9c1b512016-09-06 20:57:50 +000020bool UnwindPlan::Row::RegisterLocation::
21operator==(const UnwindPlan::Row::RegisterLocation &rhs) const {
22 if (m_type == rhs.m_type) {
23 switch (m_type) {
24 case unspecified:
25 case undefined:
26 case same:
27 return true;
Greg Clayton31f1d2f2011-05-11 18:39:18 +000028
Kate Stoneb9c1b512016-09-06 20:57:50 +000029 case atCFAPlusOffset:
30 case isCFAPlusOffset:
Aleksandr Urakov4538ed32018-10-30 10:07:08 +000031 case atAFAPlusOffset:
32 case isAFAPlusOffset:
Kate Stoneb9c1b512016-09-06 20:57:50 +000033 return m_location.offset == rhs.m_location.offset;
Jason Molendafbcb7f22010-09-10 07:49:16 +000034
Kate Stoneb9c1b512016-09-06 20:57:50 +000035 case inOtherRegister:
36 return m_location.reg_num == rhs.m_location.reg_num;
Jason Molendafbcb7f22010-09-10 07:49:16 +000037
Kate Stoneb9c1b512016-09-06 20:57:50 +000038 case atDWARFExpression:
Pavel Labathab970f52015-02-23 10:19:16 +000039 case isDWARFExpression:
Kate Stoneb9c1b512016-09-06 20:57:50 +000040 if (m_location.expr.length == rhs.m_location.expr.length)
41 return !memcmp(m_location.expr.opcodes, rhs.m_location.expr.opcodes,
42 m_location.expr.length);
43 break;
Pavel Labathab970f52015-02-23 10:19:16 +000044 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000045 }
46 return false;
Pavel Labathab970f52015-02-23 10:19:16 +000047}
48
Kate Stoneb9c1b512016-09-06 20:57:50 +000049// This function doesn't copy the dwarf expression bytes; they must remain in
Adrian Prantl05097242018-04-30 16:49:04 +000050// allocated memory for the lifespan of this UnwindPlan object.
Kate Stoneb9c1b512016-09-06 20:57:50 +000051void UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression(
52 const uint8_t *opcodes, uint32_t len) {
53 m_type = atDWARFExpression;
54 m_location.expr.opcodes = opcodes;
55 m_location.expr.length = len;
Jason Molendafbcb7f22010-09-10 07:49:16 +000056}
57
Kate Stoneb9c1b512016-09-06 20:57:50 +000058// This function doesn't copy the dwarf expression bytes; they must remain in
Adrian Prantl05097242018-04-30 16:49:04 +000059// allocated memory for the lifespan of this UnwindPlan object.
Kate Stoneb9c1b512016-09-06 20:57:50 +000060void UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression(
61 const uint8_t *opcodes, uint32_t len) {
62 m_type = isDWARFExpression;
63 m_location.expr.opcodes = opcodes;
64 m_location.expr.length = len;
65}
66
67void UnwindPlan::Row::RegisterLocation::Dump(Stream &s,
68 const UnwindPlan *unwind_plan,
69 const UnwindPlan::Row *row,
70 Thread *thread,
71 bool verbose) const {
72 switch (m_type) {
73 case unspecified:
74 if (verbose)
75 s.PutCString("=<unspec>");
Jason Molendafbcb7f22010-09-10 07:49:16 +000076 else
Kate Stoneb9c1b512016-09-06 20:57:50 +000077 s.PutCString("=!");
78 break;
79 case undefined:
80 if (verbose)
81 s.PutCString("=<undef>");
82 else
83 s.PutCString("=?");
84 break;
85 case same:
86 s.PutCString("= <same>");
87 break;
88
89 case atCFAPlusOffset:
90 case isCFAPlusOffset: {
91 s.PutChar('=');
92 if (m_type == atCFAPlusOffset)
93 s.PutChar('[');
94 s.Printf("CFA%+d", m_location.offset);
95 if (m_type == atCFAPlusOffset)
96 s.PutChar(']');
97 } break;
98
Aleksandr Urakov4538ed32018-10-30 10:07:08 +000099 case atAFAPlusOffset:
100 case isAFAPlusOffset: {
101 s.PutChar('=');
102 if (m_type == atAFAPlusOffset)
103 s.PutChar('[');
104 s.Printf("AFA%+d", m_location.offset);
105 if (m_type == atAFAPlusOffset)
106 s.PutChar(']');
107 } break;
108
Kate Stoneb9c1b512016-09-06 20:57:50 +0000109 case inOtherRegister: {
110 const RegisterInfo *other_reg_info = nullptr;
111 if (unwind_plan)
112 other_reg_info = unwind_plan->GetRegisterInfo(thread, m_location.reg_num);
113 if (other_reg_info)
114 s.Printf("=%s", other_reg_info->name);
115 else
116 s.Printf("=reg(%u)", m_location.reg_num);
117 } break;
118
119 case atDWARFExpression:
120 case isDWARFExpression: {
121 s.PutChar('=');
122 if (m_type == atDWARFExpression)
123 s.PutCString("[dwarf-expr]");
124 else
125 s.PutCString("dwarf-expr");
126 } break;
127 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000128}
129
Kate Stoneb9c1b512016-09-06 20:57:50 +0000130static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan,
131 Thread *thread, uint32_t reg_num) {
132 const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo(thread, reg_num);
133 if (reg_info)
134 s.PutCString(reg_info->name);
135 else
136 s.Printf("reg(%u)", reg_num);
Jason Molendafbcb7f22010-09-10 07:49:16 +0000137}
138
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000139bool UnwindPlan::Row::FAValue::
140operator==(const UnwindPlan::Row::FAValue &rhs) const {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000141 if (m_type == rhs.m_type) {
142 switch (m_type) {
143 case unspecified:
144 return true;
145
146 case isRegisterPlusOffset:
147 return m_value.reg.offset == rhs.m_value.reg.offset;
148
149 case isRegisterDereferenced:
150 return m_value.reg.reg_num == rhs.m_value.reg.reg_num;
151
152 case isDWARFExpression:
153 if (m_value.expr.length == rhs.m_value.expr.length)
154 return !memcmp(m_value.expr.opcodes, rhs.m_value.expr.opcodes,
155 m_value.expr.length);
156 break;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000157 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158 }
159 return false;
160}
161
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000162void UnwindPlan::Row::FAValue::Dump(Stream &s, const UnwindPlan *unwind_plan,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000163 Thread *thread) const {
164 switch (m_type) {
165 case isRegisterPlusOffset:
166 DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
167 s.Printf("%+3d", m_value.reg.offset);
168 break;
169 case isRegisterDereferenced:
170 s.PutChar('[');
171 DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
172 s.PutChar(']');
173 break;
174 case isDWARFExpression:
175 s.PutCString("dwarf-expr");
176 break;
177 default:
178 s.PutCString("unspecified");
179 break;
180 }
181}
182
183void UnwindPlan::Row::Clear() {
184 m_cfa_value.SetUnspecified();
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000185 m_afa_value.SetUnspecified();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186 m_offset = 0;
187 m_register_locations.clear();
188}
189
190void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan,
191 Thread *thread, addr_t base_addr) const {
192 if (base_addr != LLDB_INVALID_ADDRESS)
193 s.Printf("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
194 else
195 s.Printf("%4" PRId64 ": CFA=", GetOffset());
196
197 m_cfa_value.Dump(s, unwind_plan, thread);
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000198
199 if (!m_afa_value.IsUnspecified()) {
200 s.Printf(" AFA=");
201 m_afa_value.Dump(s, unwind_plan, thread);
202 }
203
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204 s.Printf(" => ");
205 for (collection::const_iterator idx = m_register_locations.begin();
206 idx != m_register_locations.end(); ++idx) {
207 DumpRegisterName(s, unwind_plan, thread, idx->first);
208 const bool verbose = false;
209 idx->second.Dump(s, unwind_plan, this, thread, verbose);
210 s.PutChar(' ');
211 }
212 s.EOL();
213}
214
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000215UnwindPlan::Row::Row()
216 : m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations() {}
Kate Stoneb9c1b512016-09-06 20:57:50 +0000217
218bool UnwindPlan::Row::GetRegisterInfo(
219 uint32_t reg_num,
220 UnwindPlan::Row::RegisterLocation &register_location) const {
221 collection::const_iterator pos = m_register_locations.find(reg_num);
222 if (pos != m_register_locations.end()) {
223 register_location = pos->second;
224 return true;
225 }
226 return false;
227}
228
229void UnwindPlan::Row::RemoveRegisterInfo(uint32_t reg_num) {
230 collection::const_iterator pos = m_register_locations.find(reg_num);
231 if (pos != m_register_locations.end()) {
232 m_register_locations.erase(pos);
233 }
234}
235
236void UnwindPlan::Row::SetRegisterInfo(
237 uint32_t reg_num,
238 const UnwindPlan::Row::RegisterLocation register_location) {
239 m_register_locations[reg_num] = register_location;
240}
241
242bool UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num,
243 int32_t offset,
244 bool can_replace) {
245 if (!can_replace &&
246 m_register_locations.find(reg_num) != m_register_locations.end())
Jason Molendafbcb7f22010-09-10 07:49:16 +0000247 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000248 RegisterLocation reg_loc;
249 reg_loc.SetAtCFAPlusOffset(offset);
250 m_register_locations[reg_num] = reg_loc;
251 return true;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000252}
253
Kate Stoneb9c1b512016-09-06 20:57:50 +0000254bool UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num,
255 int32_t offset,
256 bool can_replace) {
257 if (!can_replace &&
258 m_register_locations.find(reg_num) != m_register_locations.end())
259 return false;
260 RegisterLocation reg_loc;
261 reg_loc.SetIsCFAPlusOffset(offset);
262 m_register_locations[reg_num] = reg_loc;
263 return true;
Jason Molenda34549b82015-01-13 06:04:04 +0000264}
265
Kate Stoneb9c1b512016-09-06 20:57:50 +0000266bool UnwindPlan::Row::SetRegisterLocationToUndefined(
267 uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) {
268 collection::iterator pos = m_register_locations.find(reg_num);
269 collection::iterator end = m_register_locations.end();
270
271 if (pos != end) {
272 if (!can_replace)
273 return false;
274 if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
275 return false;
276 }
277 RegisterLocation reg_loc;
278 reg_loc.SetUndefined();
279 m_register_locations[reg_num] = reg_loc;
280 return true;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000281}
282
Kate Stoneb9c1b512016-09-06 20:57:50 +0000283bool UnwindPlan::Row::SetRegisterLocationToUnspecified(uint32_t reg_num,
284 bool can_replace) {
285 if (!can_replace &&
286 m_register_locations.find(reg_num) != m_register_locations.end())
287 return false;
288 RegisterLocation reg_loc;
289 reg_loc.SetUnspecified();
290 m_register_locations[reg_num] = reg_loc;
291 return true;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000292}
293
Kate Stoneb9c1b512016-09-06 20:57:50 +0000294bool UnwindPlan::Row::SetRegisterLocationToRegister(uint32_t reg_num,
295 uint32_t other_reg_num,
296 bool can_replace) {
297 if (!can_replace &&
298 m_register_locations.find(reg_num) != m_register_locations.end())
299 return false;
300 RegisterLocation reg_loc;
301 reg_loc.SetInRegister(other_reg_num);
302 m_register_locations[reg_num] = reg_loc;
303 return true;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000304}
305
Kate Stoneb9c1b512016-09-06 20:57:50 +0000306bool UnwindPlan::Row::SetRegisterLocationToSame(uint32_t reg_num,
307 bool must_replace) {
308 if (must_replace &&
309 m_register_locations.find(reg_num) == m_register_locations.end())
310 return false;
311 RegisterLocation reg_loc;
312 reg_loc.SetSame();
313 m_register_locations[reg_num] = reg_loc;
314 return true;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000315}
316
Kate Stoneb9c1b512016-09-06 20:57:50 +0000317bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000318 return m_offset == rhs.m_offset &&
319 m_cfa_value == rhs.m_cfa_value &&
320 m_afa_value == rhs.m_afa_value &&
321 m_register_locations == rhs.m_register_locations;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000322}
323
Kate Stoneb9c1b512016-09-06 20:57:50 +0000324void UnwindPlan::AppendRow(const UnwindPlan::RowSP &row_sp) {
325 if (m_row_list.empty() ||
326 m_row_list.back()->GetOffset() != row_sp->GetOffset())
327 m_row_list.push_back(row_sp);
328 else
329 m_row_list.back() = row_sp;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000330}
331
Kate Stoneb9c1b512016-09-06 20:57:50 +0000332void UnwindPlan::InsertRow(const UnwindPlan::RowSP &row_sp,
333 bool replace_existing) {
334 collection::iterator it = m_row_list.begin();
335 while (it != m_row_list.end()) {
336 RowSP row = *it;
337 if (row->GetOffset() >= row_sp->GetOffset())
338 break;
339 it++;
340 }
341 if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset())
342 m_row_list.insert(it, row_sp);
343 else if (replace_existing)
344 *it = row_sp;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000345}
346
Kate Stoneb9c1b512016-09-06 20:57:50 +0000347UnwindPlan::RowSP UnwindPlan::GetRowForFunctionOffset(int offset) const {
348 RowSP row;
349 if (!m_row_list.empty()) {
350 if (offset == -1)
351 row = m_row_list.back();
352 else {
353 collection::const_iterator pos, end = m_row_list.end();
354 for (pos = m_row_list.begin(); pos != end; ++pos) {
355 if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset))
356 row = *pos;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000357 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000358 break;
359 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000360 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000361 }
362 return row;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000363}
364
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365bool UnwindPlan::IsValidRowIndex(uint32_t idx) const {
366 return idx < m_row_list.size();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000367}
368
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369const UnwindPlan::RowSP UnwindPlan::GetRowAtIndex(uint32_t idx) const {
370 if (idx < m_row_list.size())
371 return m_row_list[idx];
372 else {
373 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
374 if (log)
375 log->Printf("error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index "
376 "(number rows is %u)",
377 idx, (uint32_t)m_row_list.size());
378 return UnwindPlan::RowSP();
379 }
380}
381
382const UnwindPlan::RowSP UnwindPlan::GetLastRow() const {
383 if (m_row_list.empty()) {
384 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
385 if (log)
386 log->Printf("UnwindPlan::GetLastRow() when rows are empty");
387 return UnwindPlan::RowSP();
388 }
389 return m_row_list.back();
390}
391
392int UnwindPlan::GetRowCount() const { return m_row_list.size(); }
393
394void UnwindPlan::SetPlanValidAddressRange(const AddressRange &range) {
395 if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
396 m_plan_valid_address_range = range;
397}
398
399bool UnwindPlan::PlanValidAtAddress(Address addr) {
400 // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
401 if (GetRowCount() == 0) {
402 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
403 if (log) {
404 StreamString s;
405 if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
406 log->Printf("UnwindPlan is invalid -- no unwind rows for UnwindPlan "
407 "'%s' at address %s",
408 m_source_name.GetCString(), s.GetData());
409 } else {
410 log->Printf(
411 "UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
412 m_source_name.GetCString());
413 }
Greg Claytond28fae82016-07-12 23:07:50 +0000414 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000415 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000416 }
417
418 // If the 0th Row of unwind instructions is missing, or if it doesn't provide
419 // a register to use to find the Canonical Frame Address, this is not a valid
420 // UnwindPlan.
421 if (GetRowAtIndex(0).get() == nullptr ||
422 GetRowAtIndex(0)->GetCFAValue().GetValueType() ==
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000423 Row::FAValue::unspecified) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
425 if (log) {
426 StreamString s;
427 if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
428 log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 "
429 "for UnwindPlan '%s' at address %s",
430 m_source_name.GetCString(), s.GetData());
431 } else {
432 log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 "
433 "for UnwindPlan '%s'",
434 m_source_name.GetCString());
435 }
436 }
437 return false;
438 }
439
440 if (!m_plan_valid_address_range.GetBaseAddress().IsValid() ||
441 m_plan_valid_address_range.GetByteSize() == 0)
442 return true;
443
444 if (!addr.IsValid())
445 return true;
446
447 if (m_plan_valid_address_range.ContainsFileAddress(addr))
448 return true;
449
450 return false;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000451}
452
Kate Stoneb9c1b512016-09-06 20:57:50 +0000453void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const {
454 if (!m_source_name.IsEmpty()) {
455 s.Printf("This UnwindPlan originally sourced from %s\n",
456 m_source_name.GetCString());
457 }
458 if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) {
459 TargetSP target_sp(thread->CalculateTarget());
460 addr_t lsda_load_addr = m_lsda_address.GetLoadAddress(target_sp.get());
461 addr_t personality_func_load_addr =
462 m_personality_func_addr.GetLoadAddress(target_sp.get());
463
464 if (lsda_load_addr != LLDB_INVALID_ADDRESS &&
465 personality_func_load_addr != LLDB_INVALID_ADDRESS) {
466 s.Printf("LSDA address 0x%" PRIx64
467 ", personality routine is at address 0x%" PRIx64 "\n",
468 lsda_load_addr, personality_func_load_addr);
Jason Molendaab4f1922010-10-25 11:12:07 +0000469 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470 }
471 s.Printf("This UnwindPlan is sourced from the compiler: ");
472 switch (m_plan_is_sourced_from_compiler) {
473 case eLazyBoolYes:
474 s.Printf("yes.\n");
475 break;
476 case eLazyBoolNo:
477 s.Printf("no.\n");
478 break;
479 case eLazyBoolCalculate:
480 s.Printf("not specified.\n");
481 break;
482 }
483 s.Printf("This UnwindPlan is valid at all instruction locations: ");
484 switch (m_plan_is_valid_at_all_instruction_locations) {
485 case eLazyBoolYes:
486 s.Printf("yes.\n");
487 break;
488 case eLazyBoolNo:
489 s.Printf("no.\n");
490 break;
491 case eLazyBoolCalculate:
492 s.Printf("not specified.\n");
493 break;
494 }
495 if (m_plan_valid_address_range.GetBaseAddress().IsValid() &&
496 m_plan_valid_address_range.GetByteSize() > 0) {
497 s.PutCString("Address range of this UnwindPlan: ");
498 TargetSP target_sp(thread->CalculateTarget());
499 m_plan_valid_address_range.Dump(&s, target_sp.get(),
500 Address::DumpStyleSectionNameOffset);
501 s.EOL();
502 }
503 collection::const_iterator pos, begin = m_row_list.begin(),
504 end = m_row_list.end();
505 for (pos = begin; pos != end; ++pos) {
506 s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos));
507 (*pos)->Dump(s, this, thread, base_addr);
508 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000509}
Jason Molendaab4f1922010-10-25 11:12:07 +0000510
Kate Stoneb9c1b512016-09-06 20:57:50 +0000511void UnwindPlan::SetSourceName(const char *source) {
512 m_source_name = ConstString(source);
Jason Molendaab4f1922010-10-25 11:12:07 +0000513}
514
Kate Stoneb9c1b512016-09-06 20:57:50 +0000515ConstString UnwindPlan::GetSourceName() const { return m_source_name; }
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000516
Kate Stoneb9c1b512016-09-06 20:57:50 +0000517const RegisterInfo *UnwindPlan::GetRegisterInfo(Thread *thread,
518 uint32_t unwind_reg) const {
519 if (thread) {
520 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
521 if (reg_ctx) {
522 uint32_t reg;
523 if (m_register_kind == eRegisterKindLLDB)
524 reg = unwind_reg;
525 else
526 reg = reg_ctx->ConvertRegisterKindToRegisterNumber(m_register_kind,
527 unwind_reg);
528 if (reg != LLDB_INVALID_REGNUM)
529 return reg_ctx->GetRegisterInfoAtIndex(reg);
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000530 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000531 }
532 return nullptr;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000533}