blob: d24cabed14ce956465cd53a657f41cf55adacb13 [file] [log] [blame]
Raphael Isemann80814282020-01-24 08:23:27 +01001//===-- UnwindPlan.cpp ----------------------------------------------------===//
Jason Molendafbcb7f22010-09-10 07:49:16 +00002//
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
Pavel Labath7a784202019-04-23 09:16:51 +000011#include "lldb/Expression/DWARFExpression.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000012#include "lldb/Target/Process.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000013#include "lldb/Target/RegisterContext.h"
Pavel Labath7a784202019-04-23 09:16:51 +000014#include "lldb/Target/Target.h"
Greg Claytonf5e56de2010-09-14 23:36:40 +000015#include "lldb/Target/Thread.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000016#include "lldb/Utility/ConstString.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000017#include "lldb/Utility/Log.h"
Pavel Labathba03bcb2020-05-25 15:59:48 +020018#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000019
20using namespace lldb;
21using namespace lldb_private;
22
Kate Stoneb9c1b512016-09-06 20:57:50 +000023bool UnwindPlan::Row::RegisterLocation::
24operator==(const UnwindPlan::Row::RegisterLocation &rhs) const {
25 if (m_type == rhs.m_type) {
26 switch (m_type) {
27 case unspecified:
28 case undefined:
29 case same:
30 return true;
Greg Clayton31f1d2f2011-05-11 18:39:18 +000031
Kate Stoneb9c1b512016-09-06 20:57:50 +000032 case atCFAPlusOffset:
33 case isCFAPlusOffset:
Aleksandr Urakov4538ed32018-10-30 10:07:08 +000034 case atAFAPlusOffset:
35 case isAFAPlusOffset:
Kate Stoneb9c1b512016-09-06 20:57:50 +000036 return m_location.offset == rhs.m_location.offset;
Jason Molendafbcb7f22010-09-10 07:49:16 +000037
Kate Stoneb9c1b512016-09-06 20:57:50 +000038 case inOtherRegister:
39 return m_location.reg_num == rhs.m_location.reg_num;
Jason Molendafbcb7f22010-09-10 07:49:16 +000040
Kate Stoneb9c1b512016-09-06 20:57:50 +000041 case atDWARFExpression:
Pavel Labathab970f52015-02-23 10:19:16 +000042 case isDWARFExpression:
Kate Stoneb9c1b512016-09-06 20:57:50 +000043 if (m_location.expr.length == rhs.m_location.expr.length)
44 return !memcmp(m_location.expr.opcodes, rhs.m_location.expr.opcodes,
45 m_location.expr.length);
46 break;
Pavel Labathab970f52015-02-23 10:19:16 +000047 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000048 }
49 return false;
Pavel Labathab970f52015-02-23 10:19:16 +000050}
51
Kate Stoneb9c1b512016-09-06 20:57:50 +000052// This function doesn't copy the dwarf expression bytes; they must remain in
Adrian Prantl05097242018-04-30 16:49:04 +000053// allocated memory for the lifespan of this UnwindPlan object.
Kate Stoneb9c1b512016-09-06 20:57:50 +000054void UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression(
55 const uint8_t *opcodes, uint32_t len) {
56 m_type = atDWARFExpression;
57 m_location.expr.opcodes = opcodes;
58 m_location.expr.length = len;
Jason Molendafbcb7f22010-09-10 07:49:16 +000059}
60
Kate Stoneb9c1b512016-09-06 20:57:50 +000061// This function doesn't copy the dwarf expression bytes; they must remain in
Adrian Prantl05097242018-04-30 16:49:04 +000062// allocated memory for the lifespan of this UnwindPlan object.
Kate Stoneb9c1b512016-09-06 20:57:50 +000063void UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression(
64 const uint8_t *opcodes, uint32_t len) {
65 m_type = isDWARFExpression;
66 m_location.expr.opcodes = opcodes;
67 m_location.expr.length = len;
68}
69
Pavel Labath7a784202019-04-23 09:16:51 +000070static llvm::Optional<std::pair<lldb::ByteOrder, uint32_t>>
71GetByteOrderAndAddrSize(Thread *thread) {
72 if (!thread)
73 return llvm::None;
74 ProcessSP process_sp = thread->GetProcess();
75 if (!process_sp)
76 return llvm::None;
77 ArchSpec arch = process_sp->GetTarget().GetArchitecture();
78 return std::make_pair(arch.GetByteOrder(), arch.GetAddressByteSize());
79}
80
81static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *thread) {
82 if (auto order_and_width = GetByteOrderAndAddrSize(thread)) {
Pavel Labathba03bcb2020-05-25 15:59:48 +020083 llvm::DataExtractor data(expr, order_and_width->first == eByteOrderLittle,
84 order_and_width->second);
85 llvm::DWARFExpression(data, order_and_width->second, llvm::dwarf::DWARF32)
David Blaikie0b057322020-10-23 19:19:36 -070086 .print(s.AsRawOstream(), llvm::DIDumpOptions(), nullptr, nullptr);
Pavel Labath7a784202019-04-23 09:16:51 +000087 } else
88 s.PutCString("dwarf-expr");
89}
90
Kate Stoneb9c1b512016-09-06 20:57:50 +000091void UnwindPlan::Row::RegisterLocation::Dump(Stream &s,
92 const UnwindPlan *unwind_plan,
93 const UnwindPlan::Row *row,
94 Thread *thread,
95 bool verbose) const {
96 switch (m_type) {
97 case unspecified:
98 if (verbose)
99 s.PutCString("=<unspec>");
Jason Molendafbcb7f22010-09-10 07:49:16 +0000100 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101 s.PutCString("=!");
102 break;
103 case undefined:
104 if (verbose)
105 s.PutCString("=<undef>");
106 else
107 s.PutCString("=?");
108 break;
109 case same:
110 s.PutCString("= <same>");
111 break;
112
113 case atCFAPlusOffset:
114 case isCFAPlusOffset: {
115 s.PutChar('=');
116 if (m_type == atCFAPlusOffset)
117 s.PutChar('[');
118 s.Printf("CFA%+d", m_location.offset);
119 if (m_type == atCFAPlusOffset)
120 s.PutChar(']');
121 } break;
122
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000123 case atAFAPlusOffset:
124 case isAFAPlusOffset: {
125 s.PutChar('=');
126 if (m_type == atAFAPlusOffset)
127 s.PutChar('[');
128 s.Printf("AFA%+d", m_location.offset);
129 if (m_type == atAFAPlusOffset)
130 s.PutChar(']');
131 } break;
132
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133 case inOtherRegister: {
134 const RegisterInfo *other_reg_info = nullptr;
135 if (unwind_plan)
136 other_reg_info = unwind_plan->GetRegisterInfo(thread, m_location.reg_num);
137 if (other_reg_info)
138 s.Printf("=%s", other_reg_info->name);
139 else
140 s.Printf("=reg(%u)", m_location.reg_num);
141 } break;
142
143 case atDWARFExpression:
144 case isDWARFExpression: {
145 s.PutChar('=');
146 if (m_type == atDWARFExpression)
Pavel Labath7a784202019-04-23 09:16:51 +0000147 s.PutChar('[');
148 DumpDWARFExpr(
149 s, llvm::makeArrayRef(m_location.expr.opcodes, m_location.expr.length),
150 thread);
151 if (m_type == atDWARFExpression)
152 s.PutChar(']');
Kate Stoneb9c1b512016-09-06 20:57:50 +0000153 } break;
154 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000155}
156
Kate Stoneb9c1b512016-09-06 20:57:50 +0000157static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan,
158 Thread *thread, uint32_t reg_num) {
159 const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo(thread, reg_num);
160 if (reg_info)
161 s.PutCString(reg_info->name);
162 else
163 s.Printf("reg(%u)", reg_num);
Jason Molendafbcb7f22010-09-10 07:49:16 +0000164}
165
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000166bool UnwindPlan::Row::FAValue::
167operator==(const UnwindPlan::Row::FAValue &rhs) const {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168 if (m_type == rhs.m_type) {
169 switch (m_type) {
170 case unspecified:
Pavel Labatha8b284e2019-09-27 12:10:06 +0000171 case isRaSearch:
172 return m_value.ra_search_offset == rhs.m_value.ra_search_offset;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173
174 case isRegisterPlusOffset:
175 return m_value.reg.offset == rhs.m_value.reg.offset;
176
177 case isRegisterDereferenced:
178 return m_value.reg.reg_num == rhs.m_value.reg.reg_num;
179
180 case isDWARFExpression:
181 if (m_value.expr.length == rhs.m_value.expr.length)
182 return !memcmp(m_value.expr.opcodes, rhs.m_value.expr.opcodes,
183 m_value.expr.length);
184 break;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000185 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186 }
187 return false;
188}
189
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000190void UnwindPlan::Row::FAValue::Dump(Stream &s, const UnwindPlan *unwind_plan,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000191 Thread *thread) const {
192 switch (m_type) {
193 case isRegisterPlusOffset:
194 DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
195 s.Printf("%+3d", m_value.reg.offset);
196 break;
197 case isRegisterDereferenced:
198 s.PutChar('[');
199 DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
200 s.PutChar(']');
201 break;
202 case isDWARFExpression:
Pavel Labath7a784202019-04-23 09:16:51 +0000203 DumpDWARFExpr(s,
204 llvm::makeArrayRef(m_value.expr.opcodes, m_value.expr.length),
205 thread);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000206 break;
Pavel Labatha8b284e2019-09-27 12:10:06 +0000207 case unspecified:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000208 s.PutCString("unspecified");
209 break;
Pavel Labatha8b284e2019-09-27 12:10:06 +0000210 case isRaSearch:
211 s.Printf("RaSearch@SP%+d", m_value.ra_search_offset);
212 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000213 }
214}
215
216void UnwindPlan::Row::Clear() {
217 m_cfa_value.SetUnspecified();
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000218 m_afa_value.SetUnspecified();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000219 m_offset = 0;
220 m_register_locations.clear();
221}
222
223void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan,
224 Thread *thread, addr_t base_addr) const {
225 if (base_addr != LLDB_INVALID_ADDRESS)
226 s.Printf("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
227 else
228 s.Printf("%4" PRId64 ": CFA=", GetOffset());
229
230 m_cfa_value.Dump(s, unwind_plan, thread);
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000231
232 if (!m_afa_value.IsUnspecified()) {
233 s.Printf(" AFA=");
234 m_afa_value.Dump(s, unwind_plan, thread);
235 }
236
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237 s.Printf(" => ");
238 for (collection::const_iterator idx = m_register_locations.begin();
239 idx != m_register_locations.end(); ++idx) {
240 DumpRegisterName(s, unwind_plan, thread, idx->first);
241 const bool verbose = false;
242 idx->second.Dump(s, unwind_plan, this, thread, verbose);
243 s.PutChar(' ');
244 }
245 s.EOL();
246}
247
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000248UnwindPlan::Row::Row()
249 : m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations() {}
Kate Stoneb9c1b512016-09-06 20:57:50 +0000250
251bool UnwindPlan::Row::GetRegisterInfo(
252 uint32_t reg_num,
253 UnwindPlan::Row::RegisterLocation &register_location) const {
254 collection::const_iterator pos = m_register_locations.find(reg_num);
255 if (pos != m_register_locations.end()) {
256 register_location = pos->second;
257 return true;
258 }
259 return false;
260}
261
262void UnwindPlan::Row::RemoveRegisterInfo(uint32_t reg_num) {
263 collection::const_iterator pos = m_register_locations.find(reg_num);
264 if (pos != m_register_locations.end()) {
265 m_register_locations.erase(pos);
266 }
267}
268
269void UnwindPlan::Row::SetRegisterInfo(
270 uint32_t reg_num,
271 const UnwindPlan::Row::RegisterLocation register_location) {
272 m_register_locations[reg_num] = register_location;
273}
274
275bool UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num,
276 int32_t offset,
277 bool can_replace) {
278 if (!can_replace &&
279 m_register_locations.find(reg_num) != m_register_locations.end())
Jason Molendafbcb7f22010-09-10 07:49:16 +0000280 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000281 RegisterLocation reg_loc;
282 reg_loc.SetAtCFAPlusOffset(offset);
283 m_register_locations[reg_num] = reg_loc;
284 return true;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000285}
286
Kate Stoneb9c1b512016-09-06 20:57:50 +0000287bool UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num,
288 int32_t offset,
289 bool can_replace) {
290 if (!can_replace &&
291 m_register_locations.find(reg_num) != m_register_locations.end())
292 return false;
293 RegisterLocation reg_loc;
294 reg_loc.SetIsCFAPlusOffset(offset);
295 m_register_locations[reg_num] = reg_loc;
296 return true;
Jason Molenda34549b82015-01-13 06:04:04 +0000297}
298
Kate Stoneb9c1b512016-09-06 20:57:50 +0000299bool UnwindPlan::Row::SetRegisterLocationToUndefined(
300 uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) {
301 collection::iterator pos = m_register_locations.find(reg_num);
302 collection::iterator end = m_register_locations.end();
303
304 if (pos != end) {
305 if (!can_replace)
306 return false;
307 if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
308 return false;
309 }
310 RegisterLocation reg_loc;
311 reg_loc.SetUndefined();
312 m_register_locations[reg_num] = reg_loc;
313 return true;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000314}
315
Kate Stoneb9c1b512016-09-06 20:57:50 +0000316bool UnwindPlan::Row::SetRegisterLocationToUnspecified(uint32_t reg_num,
317 bool can_replace) {
318 if (!can_replace &&
319 m_register_locations.find(reg_num) != m_register_locations.end())
320 return false;
321 RegisterLocation reg_loc;
322 reg_loc.SetUnspecified();
323 m_register_locations[reg_num] = reg_loc;
324 return true;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000325}
326
Kate Stoneb9c1b512016-09-06 20:57:50 +0000327bool UnwindPlan::Row::SetRegisterLocationToRegister(uint32_t reg_num,
328 uint32_t other_reg_num,
329 bool can_replace) {
330 if (!can_replace &&
331 m_register_locations.find(reg_num) != m_register_locations.end())
332 return false;
333 RegisterLocation reg_loc;
334 reg_loc.SetInRegister(other_reg_num);
335 m_register_locations[reg_num] = reg_loc;
336 return true;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000337}
338
Kate Stoneb9c1b512016-09-06 20:57:50 +0000339bool UnwindPlan::Row::SetRegisterLocationToSame(uint32_t reg_num,
340 bool must_replace) {
341 if (must_replace &&
342 m_register_locations.find(reg_num) == m_register_locations.end())
343 return false;
344 RegisterLocation reg_loc;
345 reg_loc.SetSame();
346 m_register_locations[reg_num] = reg_loc;
347 return true;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000348}
349
Kate Stoneb9c1b512016-09-06 20:57:50 +0000350bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const {
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000351 return m_offset == rhs.m_offset &&
352 m_cfa_value == rhs.m_cfa_value &&
353 m_afa_value == rhs.m_afa_value &&
354 m_register_locations == rhs.m_register_locations;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000355}
356
Kate Stoneb9c1b512016-09-06 20:57:50 +0000357void UnwindPlan::AppendRow(const UnwindPlan::RowSP &row_sp) {
358 if (m_row_list.empty() ||
359 m_row_list.back()->GetOffset() != row_sp->GetOffset())
360 m_row_list.push_back(row_sp);
361 else
362 m_row_list.back() = row_sp;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000363}
364
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365void UnwindPlan::InsertRow(const UnwindPlan::RowSP &row_sp,
366 bool replace_existing) {
367 collection::iterator it = m_row_list.begin();
368 while (it != m_row_list.end()) {
369 RowSP row = *it;
370 if (row->GetOffset() >= row_sp->GetOffset())
371 break;
372 it++;
373 }
374 if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset())
375 m_row_list.insert(it, row_sp);
376 else if (replace_existing)
377 *it = row_sp;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000378}
379
Kate Stoneb9c1b512016-09-06 20:57:50 +0000380UnwindPlan::RowSP UnwindPlan::GetRowForFunctionOffset(int offset) const {
381 RowSP row;
382 if (!m_row_list.empty()) {
383 if (offset == -1)
384 row = m_row_list.back();
385 else {
386 collection::const_iterator pos, end = m_row_list.end();
387 for (pos = m_row_list.begin(); pos != end; ++pos) {
388 if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset))
389 row = *pos;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000390 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000391 break;
392 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000393 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000394 }
395 return row;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000396}
397
Kate Stoneb9c1b512016-09-06 20:57:50 +0000398bool UnwindPlan::IsValidRowIndex(uint32_t idx) const {
399 return idx < m_row_list.size();
Jason Molendafbcb7f22010-09-10 07:49:16 +0000400}
401
Kate Stoneb9c1b512016-09-06 20:57:50 +0000402const UnwindPlan::RowSP UnwindPlan::GetRowAtIndex(uint32_t idx) const {
403 if (idx < m_row_list.size())
404 return m_row_list[idx];
405 else {
406 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000407 LLDB_LOGF(log,
408 "error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index "
409 "(number rows is %u)",
410 idx, (uint32_t)m_row_list.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000411 return UnwindPlan::RowSP();
412 }
413}
414
415const UnwindPlan::RowSP UnwindPlan::GetLastRow() const {
416 if (m_row_list.empty()) {
417 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000418 LLDB_LOGF(log, "UnwindPlan::GetLastRow() when rows are empty");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000419 return UnwindPlan::RowSP();
420 }
421 return m_row_list.back();
422}
423
424int UnwindPlan::GetRowCount() const { return m_row_list.size(); }
425
426void UnwindPlan::SetPlanValidAddressRange(const AddressRange &range) {
427 if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
428 m_plan_valid_address_range = range;
429}
430
431bool UnwindPlan::PlanValidAtAddress(Address addr) {
432 // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
433 if (GetRowCount() == 0) {
434 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
435 if (log) {
436 StreamString s;
437 if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000438 LLDB_LOGF(log,
439 "UnwindPlan is invalid -- no unwind rows for UnwindPlan "
440 "'%s' at address %s",
441 m_source_name.GetCString(), s.GetData());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000442 } else {
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000443 LLDB_LOGF(log,
444 "UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
445 m_source_name.GetCString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000446 }
Greg Claytond28fae82016-07-12 23:07:50 +0000447 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000448 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000449 }
450
451 // If the 0th Row of unwind instructions is missing, or if it doesn't provide
452 // a register to use to find the Canonical Frame Address, this is not a valid
453 // UnwindPlan.
454 if (GetRowAtIndex(0).get() == nullptr ||
455 GetRowAtIndex(0)->GetCFAValue().GetValueType() ==
Aleksandr Urakov4538ed32018-10-30 10:07:08 +0000456 Row::FAValue::unspecified) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000457 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
458 if (log) {
459 StreamString s;
460 if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000461 LLDB_LOGF(log,
462 "UnwindPlan is invalid -- no CFA register defined in row 0 "
463 "for UnwindPlan '%s' at address %s",
464 m_source_name.GetCString(), s.GetData());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000465 } else {
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000466 LLDB_LOGF(log,
467 "UnwindPlan is invalid -- no CFA register defined in row 0 "
468 "for UnwindPlan '%s'",
469 m_source_name.GetCString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470 }
471 }
472 return false;
473 }
474
475 if (!m_plan_valid_address_range.GetBaseAddress().IsValid() ||
476 m_plan_valid_address_range.GetByteSize() == 0)
477 return true;
478
479 if (!addr.IsValid())
480 return true;
481
482 if (m_plan_valid_address_range.ContainsFileAddress(addr))
483 return true;
484
485 return false;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000486}
487
Kate Stoneb9c1b512016-09-06 20:57:50 +0000488void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const {
489 if (!m_source_name.IsEmpty()) {
490 s.Printf("This UnwindPlan originally sourced from %s\n",
491 m_source_name.GetCString());
492 }
493 if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) {
494 TargetSP target_sp(thread->CalculateTarget());
495 addr_t lsda_load_addr = m_lsda_address.GetLoadAddress(target_sp.get());
496 addr_t personality_func_load_addr =
497 m_personality_func_addr.GetLoadAddress(target_sp.get());
498
499 if (lsda_load_addr != LLDB_INVALID_ADDRESS &&
500 personality_func_load_addr != LLDB_INVALID_ADDRESS) {
501 s.Printf("LSDA address 0x%" PRIx64
502 ", personality routine is at address 0x%" PRIx64 "\n",
503 lsda_load_addr, personality_func_load_addr);
Jason Molendaab4f1922010-10-25 11:12:07 +0000504 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000505 }
506 s.Printf("This UnwindPlan is sourced from the compiler: ");
507 switch (m_plan_is_sourced_from_compiler) {
508 case eLazyBoolYes:
509 s.Printf("yes.\n");
510 break;
511 case eLazyBoolNo:
512 s.Printf("no.\n");
513 break;
514 case eLazyBoolCalculate:
515 s.Printf("not specified.\n");
516 break;
517 }
518 s.Printf("This UnwindPlan is valid at all instruction locations: ");
519 switch (m_plan_is_valid_at_all_instruction_locations) {
520 case eLazyBoolYes:
521 s.Printf("yes.\n");
522 break;
523 case eLazyBoolNo:
524 s.Printf("no.\n");
525 break;
526 case eLazyBoolCalculate:
527 s.Printf("not specified.\n");
528 break;
529 }
Jason Molenda99d187a2020-08-25 20:53:01 -0700530 s.Printf("This UnwindPlan is for a trap handler function: ");
531 switch (m_plan_is_for_signal_trap) {
532 case eLazyBoolYes:
533 s.Printf("yes.\n");
534 break;
535 case eLazyBoolNo:
536 s.Printf("no.\n");
537 break;
538 case eLazyBoolCalculate:
539 s.Printf("not specified.\n");
540 break;
541 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000542 if (m_plan_valid_address_range.GetBaseAddress().IsValid() &&
543 m_plan_valid_address_range.GetByteSize() > 0) {
544 s.PutCString("Address range of this UnwindPlan: ");
545 TargetSP target_sp(thread->CalculateTarget());
546 m_plan_valid_address_range.Dump(&s, target_sp.get(),
547 Address::DumpStyleSectionNameOffset);
548 s.EOL();
549 }
550 collection::const_iterator pos, begin = m_row_list.begin(),
551 end = m_row_list.end();
552 for (pos = begin; pos != end; ++pos) {
553 s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos));
554 (*pos)->Dump(s, this, thread, base_addr);
555 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000556}
Jason Molendaab4f1922010-10-25 11:12:07 +0000557
Kate Stoneb9c1b512016-09-06 20:57:50 +0000558void UnwindPlan::SetSourceName(const char *source) {
559 m_source_name = ConstString(source);
Jason Molendaab4f1922010-10-25 11:12:07 +0000560}
561
Kate Stoneb9c1b512016-09-06 20:57:50 +0000562ConstString UnwindPlan::GetSourceName() const { return m_source_name; }
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000563
Kate Stoneb9c1b512016-09-06 20:57:50 +0000564const RegisterInfo *UnwindPlan::GetRegisterInfo(Thread *thread,
565 uint32_t unwind_reg) const {
566 if (thread) {
567 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
568 if (reg_ctx) {
569 uint32_t reg;
570 if (m_register_kind == eRegisterKindLLDB)
571 reg = unwind_reg;
572 else
573 reg = reg_ctx->ConvertRegisterKindToRegisterNumber(m_register_kind,
574 unwind_reg);
575 if (reg != LLDB_INVALID_REGNUM)
576 return reg_ctx->GetRegisterInfoAtIndex(reg);
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000577 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000578 }
579 return nullptr;
Greg Clayton31f1d2f2011-05-11 18:39:18 +0000580}