LLDB mainline
UnwindPlan.cpp
Go to the documentation of this file.
1//===-- UnwindPlan.cpp ----------------------------------------------------===//
2//
3// 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
6//
7//===----------------------------------------------------------------------===//
8
10
11#include "lldb/Target/Process.h"
13#include "lldb/Target/Target.h"
14#include "lldb/Target/Thread.h"
17#include "lldb/Utility/Log.h"
18#include "llvm/DebugInfo/DIContext.h"
19#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
20#include <optional>
21
22using namespace lldb;
23using namespace lldb_private;
24
27 if (m_type == rhs.m_type) {
28 switch (m_type) {
29 case unspecified:
30 case undefined:
31 case same:
32 return true;
33
34 case atCFAPlusOffset:
35 case isCFAPlusOffset:
36 case atAFAPlusOffset:
37 case isAFAPlusOffset:
38 return m_location.offset == rhs.m_location.offset;
39
40 case inOtherRegister:
41 return m_location.reg_num == rhs.m_location.reg_num;
42
45 if (m_location.expr.length == rhs.m_location.expr.length)
46 return !memcmp(m_location.expr.opcodes, rhs.m_location.expr.opcodes,
47 m_location.expr.length);
48 break;
49 case isConstant:
50 return m_location.constant_value == rhs.m_location.constant_value;
51 }
52 }
53 return false;
54}
55
56// This function doesn't copy the dwarf expression bytes; they must remain in
57// allocated memory for the lifespan of this UnwindPlan object.
59 const uint8_t *opcodes, uint32_t len) {
60 m_type = atDWARFExpression;
61 m_location.expr.opcodes = opcodes;
62 m_location.expr.length = len;
63}
64
65// This function doesn't copy the dwarf expression bytes; they must remain in
66// allocated memory for the lifespan of this UnwindPlan object.
68 const uint8_t *opcodes, uint32_t len) {
69 m_type = isDWARFExpression;
70 m_location.expr.opcodes = opcodes;
71 m_location.expr.length = len;
72}
73
74static std::optional<std::pair<lldb::ByteOrder, uint32_t>>
76 if (!thread)
77 return std::nullopt;
78 ProcessSP process_sp = thread->GetProcess();
79 if (!process_sp)
80 return std::nullopt;
81 ArchSpec arch = process_sp->GetTarget().GetArchitecture();
82 return std::make_pair(arch.GetByteOrder(), arch.GetAddressByteSize());
83}
84
85static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *thread) {
86 if (auto order_and_width = GetByteOrderAndAddrSize(thread)) {
87 llvm::DataExtractor data(expr, order_and_width->first == eByteOrderLittle,
88 order_and_width->second);
89 llvm::DWARFExpression(data, order_and_width->second, llvm::dwarf::DWARF32)
90 .print(s.AsRawOstream(), llvm::DIDumpOptions(), nullptr);
91 } else
92 s.PutCString("dwarf-expr");
93}
94
96 const UnwindPlan *unwind_plan,
97 const UnwindPlan::Row *row,
98 Thread *thread,
99 bool verbose) const {
100 switch (m_type) {
101 case unspecified:
102 if (verbose)
103 s.PutCString("=<unspec>");
104 else
105 s.PutCString("=!");
106 break;
107 case undefined:
108 if (verbose)
109 s.PutCString("=<undef>");
110 else
111 s.PutCString("=?");
112 break;
113 case same:
114 s.PutCString("= <same>");
115 break;
116
117 case atCFAPlusOffset:
118 case isCFAPlusOffset: {
119 s.PutChar('=');
120 if (m_type == atCFAPlusOffset)
121 s.PutChar('[');
122 s.Printf("CFA%+d", m_location.offset);
123 if (m_type == atCFAPlusOffset)
124 s.PutChar(']');
125 } break;
126
127 case atAFAPlusOffset:
128 case isAFAPlusOffset: {
129 s.PutChar('=');
130 if (m_type == atAFAPlusOffset)
131 s.PutChar('[');
132 s.Printf("AFA%+d", m_location.offset);
133 if (m_type == atAFAPlusOffset)
134 s.PutChar(']');
135 } break;
136
137 case inOtherRegister: {
138 const RegisterInfo *other_reg_info = nullptr;
139 if (unwind_plan)
140 other_reg_info = unwind_plan->GetRegisterInfo(thread, m_location.reg_num);
141 if (other_reg_info)
142 s.Printf("=%s", other_reg_info->name);
143 else
144 s.Printf("=reg(%u)", m_location.reg_num);
145 } break;
146
147 case atDWARFExpression:
148 case isDWARFExpression: {
149 s.PutChar('=');
150 if (m_type == atDWARFExpression)
151 s.PutChar('[');
153 s, llvm::ArrayRef(m_location.expr.opcodes, m_location.expr.length),
154 thread);
155 if (m_type == atDWARFExpression)
156 s.PutChar(']');
157 } break;
158 case isConstant:
159 s.Printf("=0x%" PRIx64, m_location.constant_value);
160 break;
161 }
162}
163
164static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan,
165 Thread *thread, uint32_t reg_num) {
166 const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo(thread, reg_num);
167 if (reg_info)
168 s.PutCString(reg_info->name);
169 else
170 s.Printf("reg(%u)", reg_num);
171}
172
174operator==(const UnwindPlan::Row::FAValue &rhs) const {
175 if (m_type == rhs.m_type) {
176 switch (m_type) {
177 case unspecified:
178 case isRaSearch:
179 return m_value.ra_search_offset == rhs.m_value.ra_search_offset;
180
181 case isRegisterPlusOffset:
182 return m_value.reg.offset == rhs.m_value.reg.offset;
183
184 case isRegisterDereferenced:
185 return m_value.reg.reg_num == rhs.m_value.reg.reg_num;
186
187 case isDWARFExpression:
188 if (m_value.expr.length == rhs.m_value.expr.length)
189 return !memcmp(m_value.expr.opcodes, rhs.m_value.expr.opcodes,
190 m_value.expr.length);
191 break;
192 }
193 }
194 return false;
195}
196
198 Thread *thread) const {
199 switch (m_type) {
200 case isRegisterPlusOffset:
201 DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
202 s.Printf("%+3d", m_value.reg.offset);
203 break;
204 case isRegisterDereferenced:
205 s.PutChar('[');
206 DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
207 s.PutChar(']');
208 break;
209 case isDWARFExpression:
210 DumpDWARFExpr(s, llvm::ArrayRef(m_value.expr.opcodes, m_value.expr.length),
211 thread);
212 break;
213 case unspecified:
214 s.PutCString("unspecified");
215 break;
216 case isRaSearch:
217 s.Printf("RaSearch@SP%+d", m_value.ra_search_offset);
218 break;
219 }
220}
221
225 m_offset = 0;
227 m_register_locations.clear();
228}
229
230void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan,
231 Thread *thread, addr_t base_addr) const {
232 if (base_addr != LLDB_INVALID_ADDRESS)
233 s.Printf("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
234 else
235 s.Printf("%4" PRId64 ": CFA=", GetOffset());
236
237 m_cfa_value.Dump(s, unwind_plan, thread);
238
239 if (!m_afa_value.IsUnspecified()) {
240 s.Printf(" AFA=");
241 m_afa_value.Dump(s, unwind_plan, thread);
242 }
243
244 s.Printf(" => ");
245 for (collection::const_iterator idx = m_register_locations.begin();
246 idx != m_register_locations.end(); ++idx) {
247 DumpRegisterName(s, unwind_plan, thread, idx->first);
248 const bool verbose = false;
249 idx->second.Dump(s, unwind_plan, this, thread, verbose);
250 s.PutChar(' ');
251 }
252}
253
255
257 uint32_t reg_num,
258 UnwindPlan::Row::RegisterLocation &register_location) const {
259 collection::const_iterator pos = m_register_locations.find(reg_num);
260 if (pos != m_register_locations.end()) {
261 register_location = pos->second;
262 return true;
263 }
264 if (m_unspecified_registers_are_undefined) {
265 register_location.SetUndefined();
266 return true;
267 }
268 return false;
269}
270
272 collection::const_iterator pos = m_register_locations.find(reg_num);
273 if (pos != m_register_locations.end()) {
274 m_register_locations.erase(pos);
275 }
276}
277
279 uint32_t reg_num,
280 const UnwindPlan::Row::RegisterLocation register_location) {
281 m_register_locations[reg_num] = register_location;
282}
283
285 int32_t offset,
286 bool can_replace) {
287 if (!can_replace &&
288 m_register_locations.find(reg_num) != m_register_locations.end())
289 return false;
290 RegisterLocation reg_loc;
291 reg_loc.SetAtCFAPlusOffset(offset);
292 m_register_locations[reg_num] = reg_loc;
293 return true;
294}
295
297 int32_t offset,
298 bool can_replace) {
299 if (!can_replace &&
300 m_register_locations.find(reg_num) != m_register_locations.end())
301 return false;
302 RegisterLocation reg_loc;
303 reg_loc.SetIsCFAPlusOffset(offset);
304 m_register_locations[reg_num] = reg_loc;
305 return true;
306}
307
309 uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) {
310 collection::iterator pos = m_register_locations.find(reg_num);
311 collection::iterator end = m_register_locations.end();
312
313 if (pos != end) {
314 if (!can_replace)
315 return false;
316 if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
317 return false;
318 }
319 RegisterLocation reg_loc;
320 reg_loc.SetUndefined();
321 m_register_locations[reg_num] = reg_loc;
322 return true;
323}
324
326 bool can_replace) {
327 if (!can_replace &&
328 m_register_locations.find(reg_num) != m_register_locations.end())
329 return false;
330 RegisterLocation reg_loc;
331 reg_loc.SetUnspecified();
332 m_register_locations[reg_num] = reg_loc;
333 return true;
334}
335
337 uint32_t other_reg_num,
338 bool can_replace) {
339 if (!can_replace &&
340 m_register_locations.find(reg_num) != m_register_locations.end())
341 return false;
342 RegisterLocation reg_loc;
343 reg_loc.SetInRegister(other_reg_num);
344 m_register_locations[reg_num] = reg_loc;
345 return true;
346}
347
349 bool must_replace) {
350 if (must_replace &&
351 m_register_locations.find(reg_num) == m_register_locations.end())
352 return false;
353 RegisterLocation reg_loc;
354 reg_loc.SetSame();
355 m_register_locations[reg_num] = reg_loc;
356 return true;
357}
358
360 uint64_t constant,
361 bool can_replace) {
362 if (!can_replace &&
363 m_register_locations.find(reg_num) != m_register_locations.end())
364 return false;
365 RegisterLocation reg_loc;
366 reg_loc.SetIsConstant(constant);
367 m_register_locations[reg_num] = reg_loc;
368 return true;
369}
370
372 return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value &&
373 m_afa_value == rhs.m_afa_value &&
374 m_unspecified_registers_are_undefined ==
376 m_register_locations == rhs.m_register_locations;
377}
378
380 if (m_row_list.empty() ||
381 m_row_list.back()->GetOffset() != row_sp->GetOffset())
382 m_row_list.push_back(row_sp);
383 else
384 m_row_list.back() = row_sp;
385}
386
388 bool replace_existing) {
389 collection::iterator it = m_row_list.begin();
390 while (it != m_row_list.end()) {
391 RowSP row = *it;
392 if (row->GetOffset() >= row_sp->GetOffset())
393 break;
394 it++;
395 }
396 if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset())
397 m_row_list.insert(it, row_sp);
398 else if (replace_existing)
399 *it = row_sp;
400}
401
403 RowSP row;
404 if (!m_row_list.empty()) {
405 if (offset == -1)
406 row = m_row_list.back();
407 else {
408 collection::const_iterator pos, end = m_row_list.end();
409 for (pos = m_row_list.begin(); pos != end; ++pos) {
410 if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset))
411 row = *pos;
412 else
413 break;
414 }
415 }
416 }
417 return row;
418}
419
420bool UnwindPlan::IsValidRowIndex(uint32_t idx) const {
421 return idx < m_row_list.size();
422}
423
425 if (idx < m_row_list.size())
426 return m_row_list[idx];
427 else {
428 Log *log = GetLog(LLDBLog::Unwind);
429 LLDB_LOGF(log,
430 "error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index "
431 "(number rows is %u)",
432 idx, (uint32_t)m_row_list.size());
433 return UnwindPlan::RowSP();
434 }
435}
436
438 if (m_row_list.empty()) {
439 Log *log = GetLog(LLDBLog::Unwind);
440 LLDB_LOGF(log, "UnwindPlan::GetLastRow() when rows are empty");
441 return UnwindPlan::RowSP();
442 }
443 return m_row_list.back();
444}
445
446int UnwindPlan::GetRowCount() const { return m_row_list.size(); }
447
449 if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
451}
452
454 // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
455 if (GetRowCount() == 0) {
456 Log *log = GetLog(LLDBLog::Unwind);
457 if (log) {
458 StreamString s;
459 if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
460 LLDB_LOGF(log,
461 "UnwindPlan is invalid -- no unwind rows for UnwindPlan "
462 "'%s' at address %s",
464 } else {
465 LLDB_LOGF(log,
466 "UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
468 }
469 }
470 return false;
471 }
472
473 // If the 0th Row of unwind instructions is missing, or if it doesn't provide
474 // a register to use to find the Canonical Frame Address, this is not a valid
475 // UnwindPlan.
476 if (GetRowAtIndex(0).get() == nullptr ||
477 GetRowAtIndex(0)->GetCFAValue().GetValueType() ==
479 Log *log = GetLog(LLDBLog::Unwind);
480 if (log) {
481 StreamString s;
482 if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
483 LLDB_LOGF(log,
484 "UnwindPlan is invalid -- no CFA register defined in row 0 "
485 "for UnwindPlan '%s' at address %s",
487 } else {
488 LLDB_LOGF(log,
489 "UnwindPlan is invalid -- no CFA register defined in row 0 "
490 "for UnwindPlan '%s'",
492 }
493 }
494 return false;
495 }
496
499 return true;
500
501 if (!addr.IsValid())
502 return true;
503
505 return true;
506
507 return false;
508}
509
510void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const {
511 if (!m_source_name.IsEmpty()) {
512 s.Printf("This UnwindPlan originally sourced from %s\n",
514 }
516 TargetSP target_sp(thread->CalculateTarget());
517 addr_t lsda_load_addr = m_lsda_address.GetLoadAddress(target_sp.get());
518 addr_t personality_func_load_addr =
520
521 if (lsda_load_addr != LLDB_INVALID_ADDRESS &&
522 personality_func_load_addr != LLDB_INVALID_ADDRESS) {
523 s.Printf("LSDA address 0x%" PRIx64
524 ", personality routine is at address 0x%" PRIx64 "\n",
525 lsda_load_addr, personality_func_load_addr);
526 }
527 }
528 s.Printf("This UnwindPlan is sourced from the compiler: ");
530 case eLazyBoolYes:
531 s.Printf("yes.\n");
532 break;
533 case eLazyBoolNo:
534 s.Printf("no.\n");
535 break;
537 s.Printf("not specified.\n");
538 break;
539 }
540 s.Printf("This UnwindPlan is valid at all instruction locations: ");
542 case eLazyBoolYes:
543 s.Printf("yes.\n");
544 break;
545 case eLazyBoolNo:
546 s.Printf("no.\n");
547 break;
549 s.Printf("not specified.\n");
550 break;
551 }
552 s.Printf("This UnwindPlan is for a trap handler function: ");
554 case eLazyBoolYes:
555 s.Printf("yes.\n");
556 break;
557 case eLazyBoolNo:
558 s.Printf("no.\n");
559 break;
561 s.Printf("not specified.\n");
562 break;
563 }
566 s.PutCString("Address range of this UnwindPlan: ");
567 TargetSP target_sp(thread->CalculateTarget());
568 m_plan_valid_address_range.Dump(&s, target_sp.get(),
570 s.EOL();
571 }
572 collection::const_iterator pos, begin = m_row_list.begin(),
573 end = m_row_list.end();
574 for (pos = begin; pos != end; ++pos) {
575 s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos));
576 (*pos)->Dump(s, this, thread, base_addr);
577 s.Printf("\n");
578 }
579}
580
581void UnwindPlan::SetSourceName(const char *source) {
582 m_source_name = ConstString(source);
583}
584
586
588 uint32_t unwind_reg) const {
589 if (thread) {
590 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
591 if (reg_ctx) {
592 uint32_t reg;
594 reg = unwind_reg;
595 else
597 unwind_reg);
598 if (reg != LLDB_INVALID_REGNUM)
599 return reg_ctx->GetRegisterInfoAtIndex(reg);
600 }
601 }
602 return nullptr;
603}
#define LLDB_LOGF(log,...)
Definition: Log.h:366
static std::optional< std::pair< lldb::ByteOrder, uint32_t > > GetByteOrderAndAddrSize(Thread *thread)
Definition: UnwindPlan.cpp:75
static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, uint32_t reg_num)
Definition: UnwindPlan.cpp:164
static void DumpDWARFExpr(Stream &s, llvm::ArrayRef< uint8_t > expr, Thread *thread)
Definition: UnwindPlan.cpp:85
A section + offset based address range class.
Definition: AddressRange.h:25
Address & GetBaseAddress()
Get accessor for the base address of the range.
Definition: AddressRange.h:211
bool ContainsFileAddress(const Address &so_addr) const
Check if a section offset address is contained in this range.
bool Dump(Stream *s, Target *target, Address::DumpStyle style, Address::DumpStyle fallback_style=Address::DumpStyleInvalid) const
Dump a description of this object to a Stream.
lldb::addr_t GetByteSize() const
Get accessor for the byte size of this range.
Definition: AddressRange.h:223
A section + offset based address class.
Definition: Address.h:62
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition: Address.cpp:313
@ DumpStyleSectionNameOffset
Display as the section name + offset.
Definition: Address.h:74
bool Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style=DumpStyleInvalid, uint32_t addr_byte_size=UINT32_MAX, bool all_ranges=false, std::optional< Stream::HighlightSettings > settings=std::nullopt) const
Dump a description of this object to a Stream.
Definition: Address.cpp:408
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:355
An architecture specification class.
Definition: ArchSpec.h:31
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition: ArchSpec.cpp:691
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition: ArchSpec.cpp:738
A uniqued constant string class.
Definition: ConstString.h:40
bool IsEmpty() const
Test for empty string.
Definition: ConstString.h:304
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:216
virtual uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num)
Convert from a given register numbering scheme to the lldb register numbering scheme.
virtual const RegisterInfo * GetRegisterInfoAtIndex(size_t reg)=0
const char * GetData() const
Definition: StreamString.h:45
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition: Stream.h:401
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:65
size_t PutChar(char ch)
Definition: Stream.cpp:131
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:155
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb::TargetSP CalculateTarget() override
Definition: Thread.cpp:1401
lldb::ProcessSP GetProcess() const
Definition: Thread.h:157
void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread) const
Definition: UnwindPlan.cpp:197
union lldb_private::UnwindPlan::Row::FAValue::@26 m_value
bool operator==(const FAValue &rhs) const
Definition: UnwindPlan.cpp:174
struct lldb_private::UnwindPlan::Row::FAValue::@26::@27 reg
struct lldb_private::UnwindPlan::Row::FAValue::@26::@28 expr
bool operator==(const RegisterLocation &rhs) const
Definition: UnwindPlan.cpp:26
union lldb_private::UnwindPlan::Row::RegisterLocation::@24 m_location
struct lldb_private::UnwindPlan::Row::RegisterLocation::@24::@25 expr
void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len)
Definition: UnwindPlan.cpp:58
void Dump(Stream &s, const UnwindPlan *unwind_plan, const UnwindPlan::Row *row, Thread *thread, bool verbose) const
Definition: UnwindPlan.cpp:95
void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
Definition: UnwindPlan.cpp:67
bool SetRegisterLocationToIsConstant(uint32_t reg_num, uint64_t constant, bool can_replace)
Definition: UnwindPlan.cpp:359
bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
Definition: UnwindPlan.cpp:296
bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace)
Definition: UnwindPlan.cpp:348
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
Definition: UnwindPlan.cpp:284
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
Definition: UnwindPlan.cpp:336
void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, lldb::addr_t base_addr) const
Definition: UnwindPlan.cpp:230
bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace)
Definition: UnwindPlan.cpp:325
void RemoveRegisterInfo(uint32_t reg_num)
Definition: UnwindPlan.cpp:271
lldb::addr_t GetOffset() const
Definition: UnwindPlan.h:347
bool operator==(const Row &rhs) const
Definition: UnwindPlan.cpp:371
bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified)
Definition: UnwindPlan.cpp:308
bool GetRegisterInfo(uint32_t reg_num, RegisterLocation &register_location) const
Definition: UnwindPlan.cpp:256
void SetRegisterInfo(uint32_t reg_num, const RegisterLocation register_location)
Definition: UnwindPlan.cpp:278
void InsertRow(const RowSP &row_sp, bool replace_existing=false)
Definition: UnwindPlan.cpp:387
const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const
Definition: UnwindPlan.cpp:424
lldb::RegisterKind m_register_kind
Definition: UnwindPlan.h:551
const RegisterInfo * GetRegisterInfo(Thread *thread, uint32_t reg_num) const
Definition: UnwindPlan.cpp:587
lldb_private::LazyBool m_plan_is_for_signal_trap
Definition: UnwindPlan.h:561
const UnwindPlan::RowSP GetLastRow() const
Definition: UnwindPlan.cpp:437
void SetPlanValidAddressRange(const AddressRange &range)
Definition: UnwindPlan.cpp:448
AddressRange m_plan_valid_address_range
Definition: UnwindPlan.h:550
bool IsValidRowIndex(uint32_t idx) const
Definition: UnwindPlan.cpp:420
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:379
lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations
Definition: UnwindPlan.h:560
UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const
Definition: UnwindPlan.cpp:402
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:410
lldb_private::ConstString m_source_name
Definition: UnwindPlan.h:558
bool PlanValidAtAddress(Address addr)
Definition: UnwindPlan.cpp:453
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:581
void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const
Definition: UnwindPlan.cpp:510
lldb_private::ConstString GetSourceName() const
Definition: UnwindPlan.cpp:585
lldb_private::LazyBool m_plan_is_sourced_from_compiler
Definition: UnwindPlan.h:559
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:87
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:331
Definition: SBAddress.h:15
uint64_t offset_t
Definition: lldb-types.h:85
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:387
@ eByteOrderLittle
uint64_t addr_t
Definition: lldb-types.h:80
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:444
@ eRegisterKindLLDB
lldb's internal register numbers
Every register is described in detail including its name, alternate name (optional),...
const char * name
Name of this register, can't be NULL.