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 Stream &s, const UnwindPlan *unwind_plan, const UnwindPlan::Row *row,
97 Thread *thread, bool verbose) const {
98 switch (m_type) {
99 case unspecified:
100 if (verbose)
101 s.PutCString("=<unspec>");
102 else
103 s.PutCString("=!");
104 break;
105 case undefined:
106 if (verbose)
107 s.PutCString("=<undef>");
108 else
109 s.PutCString("=?");
110 break;
111 case same:
112 s.PutCString("= <same>");
113 break;
114
115 case atCFAPlusOffset:
116 case isCFAPlusOffset: {
117 s.PutChar('=');
118 if (m_type == atCFAPlusOffset)
119 s.PutChar('[');
120 s.Printf("CFA%+d", m_location.offset);
121 if (m_type == atCFAPlusOffset)
122 s.PutChar(']');
123 } break;
124
125 case atAFAPlusOffset:
126 case isAFAPlusOffset: {
127 s.PutChar('=');
128 if (m_type == atAFAPlusOffset)
129 s.PutChar('[');
130 s.Printf("AFA%+d", m_location.offset);
131 if (m_type == atAFAPlusOffset)
132 s.PutChar(']');
133 } break;
134
135 case inOtherRegister: {
136 const RegisterInfo *other_reg_info = nullptr;
137 if (unwind_plan)
138 other_reg_info = unwind_plan->GetRegisterInfo(thread, m_location.reg_num);
139 if (other_reg_info)
140 s.Printf("=%s", other_reg_info->name);
141 else
142 s.Printf("=reg(%u)", m_location.reg_num);
143 } break;
144
145 case atDWARFExpression:
146 case isDWARFExpression: {
147 s.PutChar('=');
148 if (m_type == atDWARFExpression)
149 s.PutChar('[');
151 s, llvm::ArrayRef(m_location.expr.opcodes, m_location.expr.length),
152 thread);
153 if (m_type == atDWARFExpression)
154 s.PutChar(']');
155 } break;
156 case isConstant:
157 s.Printf("=0x%" PRIx64, m_location.constant_value);
158 break;
159 }
160}
161
162static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan,
163 Thread *thread, uint32_t reg_num) {
164 const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo(thread, reg_num);
165 if (reg_info)
166 s.PutCString(reg_info->name);
167 else
168 s.Printf("reg(%u)", reg_num);
169}
170
172operator==(const UnwindPlan::Row::FAValue &rhs) const {
173 if (m_type == rhs.m_type) {
174 switch (m_type) {
175 case unspecified:
176 case isRaSearch:
177 return m_value.ra_search_offset == rhs.m_value.ra_search_offset;
178
179 case isRegisterPlusOffset:
180 return m_value.reg.offset == rhs.m_value.reg.offset;
181
182 case isRegisterDereferenced:
183 return m_value.reg.reg_num == rhs.m_value.reg.reg_num;
184
185 case isDWARFExpression:
186 if (m_value.expr.length == rhs.m_value.expr.length)
187 return !memcmp(m_value.expr.opcodes, rhs.m_value.expr.opcodes,
188 m_value.expr.length);
189 break;
190 case isConstant:
191 return m_value.constant == rhs.m_value.constant;
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 case isConstant:
220 s.Printf("0x%" PRIx64, m_value.constant);
221 }
222}
223
227 m_offset = 0;
229 m_register_locations.clear();
230}
231
232void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan,
233 Thread *thread, addr_t base_addr) const {
234 if (base_addr != LLDB_INVALID_ADDRESS)
235 s.Printf("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
236 else
237 s.Printf("%4" PRId64 ": CFA=", GetOffset());
238
239 m_cfa_value.Dump(s, unwind_plan, thread);
240
241 if (!m_afa_value.IsUnspecified()) {
242 s.Printf(" AFA=");
243 m_afa_value.Dump(s, unwind_plan, thread);
244 }
245
246 s.Printf(" => ");
247 for (collection::const_iterator idx = m_register_locations.begin();
248 idx != m_register_locations.end(); ++idx) {
249 DumpRegisterName(s, unwind_plan, thread, idx->first);
250 const bool verbose = false;
251 idx->second.Dump(s, unwind_plan, this, thread, verbose);
252 s.PutChar(' ');
253 }
254}
255
257
259 uint32_t reg_num,
260 UnwindPlan::Row::AbstractRegisterLocation &register_location) const {
261 collection::const_iterator pos = m_register_locations.find(reg_num);
262 if (pos != m_register_locations.end()) {
263 register_location = pos->second;
264 return true;
265 }
266 if (m_unspecified_registers_are_undefined) {
267 register_location.SetUndefined();
268 return true;
269 }
270 return false;
271}
272
274 collection::const_iterator pos = m_register_locations.find(reg_num);
275 if (pos != m_register_locations.end()) {
276 m_register_locations.erase(pos);
277 }
278}
279
281 uint32_t reg_num,
282 const UnwindPlan::Row::AbstractRegisterLocation register_location) {
283 m_register_locations[reg_num] = register_location;
284}
285
287 int32_t offset,
288 bool can_replace) {
289 if (!can_replace &&
290 m_register_locations.find(reg_num) != m_register_locations.end())
291 return false;
293 reg_loc.SetAtCFAPlusOffset(offset);
294 m_register_locations[reg_num] = reg_loc;
295 return true;
296}
297
299 int32_t offset,
300 bool can_replace) {
301 if (!can_replace &&
302 m_register_locations.find(reg_num) != m_register_locations.end())
303 return false;
305 reg_loc.SetIsCFAPlusOffset(offset);
306 m_register_locations[reg_num] = reg_loc;
307 return true;
308}
309
311 uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) {
312 collection::iterator pos = m_register_locations.find(reg_num);
313 collection::iterator end = m_register_locations.end();
314
315 if (pos != end) {
316 if (!can_replace)
317 return false;
318 if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
319 return false;
320 }
322 reg_loc.SetUndefined();
323 m_register_locations[reg_num] = reg_loc;
324 return true;
325}
326
328 bool can_replace) {
329 if (!can_replace &&
330 m_register_locations.find(reg_num) != m_register_locations.end())
331 return false;
333 reg_loc.SetUnspecified();
334 m_register_locations[reg_num] = reg_loc;
335 return true;
336}
337
339 uint32_t other_reg_num,
340 bool can_replace) {
341 if (!can_replace &&
342 m_register_locations.find(reg_num) != m_register_locations.end())
343 return false;
345 reg_loc.SetInRegister(other_reg_num);
346 m_register_locations[reg_num] = reg_loc;
347 return true;
348}
349
351 bool must_replace) {
352 if (must_replace &&
353 m_register_locations.find(reg_num) == m_register_locations.end())
354 return false;
356 reg_loc.SetSame();
357 m_register_locations[reg_num] = reg_loc;
358 return true;
359}
360
362 uint32_t reg_num, const uint8_t *opcodes, uint32_t len, bool can_replace) {
363 if (!can_replace &&
364 m_register_locations.find(reg_num) != m_register_locations.end())
365 return false;
367 reg_loc.SetIsDWARFExpression(opcodes, len);
368 m_register_locations[reg_num] = reg_loc;
369 return true;
370}
371
373 uint64_t constant,
374 bool can_replace) {
375 if (!can_replace &&
376 m_register_locations.find(reg_num) != m_register_locations.end())
377 return false;
379 reg_loc.SetIsConstant(constant);
380 m_register_locations[reg_num] = reg_loc;
381 return true;
382}
383
385 return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value &&
386 m_afa_value == rhs.m_afa_value &&
387 m_unspecified_registers_are_undefined ==
389 m_register_locations == rhs.m_register_locations;
390}
391
393 if (m_row_list.empty() ||
394 m_row_list.back()->GetOffset() != row_sp->GetOffset())
395 m_row_list.push_back(row_sp);
396 else
397 m_row_list.back() = row_sp;
398}
399
401 bool replace_existing) {
402 collection::iterator it = m_row_list.begin();
403 while (it != m_row_list.end()) {
404 RowSP row = *it;
405 if (row->GetOffset() >= row_sp->GetOffset())
406 break;
407 it++;
408 }
409 if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset())
410 m_row_list.insert(it, row_sp);
411 else if (replace_existing)
412 *it = row_sp;
413}
414
416 RowSP row;
417 if (!m_row_list.empty()) {
418 if (offset == -1)
419 row = m_row_list.back();
420 else {
421 collection::const_iterator pos, end = m_row_list.end();
422 for (pos = m_row_list.begin(); pos != end; ++pos) {
423 if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset))
424 row = *pos;
425 else
426 break;
427 }
428 }
429 }
430 return row;
431}
432
433bool UnwindPlan::IsValidRowIndex(uint32_t idx) const {
434 return idx < m_row_list.size();
435}
436
438 if (idx < m_row_list.size())
439 return m_row_list[idx];
440 else {
441 Log *log = GetLog(LLDBLog::Unwind);
442 LLDB_LOGF(log,
443 "error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index "
444 "(number rows is %u)",
445 idx, (uint32_t)m_row_list.size());
446 return UnwindPlan::RowSP();
447 }
448}
449
451 if (m_row_list.empty()) {
452 Log *log = GetLog(LLDBLog::Unwind);
453 LLDB_LOGF(log, "UnwindPlan::GetLastRow() when rows are empty");
454 return UnwindPlan::RowSP();
455 }
456 return m_row_list.back();
457}
458
459int UnwindPlan::GetRowCount() const { return m_row_list.size(); }
460
462 if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
464}
465
467 // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
468 if (GetRowCount() == 0) {
469 Log *log = GetLog(LLDBLog::Unwind);
470 if (log) {
471 StreamString s;
472 if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
473 LLDB_LOGF(log,
474 "UnwindPlan is invalid -- no unwind rows for UnwindPlan "
475 "'%s' at address %s",
477 } else {
478 LLDB_LOGF(log,
479 "UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
481 }
482 }
483 return false;
484 }
485
486 // If the 0th Row of unwind instructions is missing, or if it doesn't provide
487 // a register to use to find the Canonical Frame Address, this is not a valid
488 // UnwindPlan.
489 if (GetRowAtIndex(0).get() == nullptr ||
490 GetRowAtIndex(0)->GetCFAValue().GetValueType() ==
492 Log *log = GetLog(LLDBLog::Unwind);
493 if (log) {
494 StreamString s;
495 if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
496 LLDB_LOGF(log,
497 "UnwindPlan is invalid -- no CFA register defined in row 0 "
498 "for UnwindPlan '%s' at address %s",
500 } else {
501 LLDB_LOGF(log,
502 "UnwindPlan is invalid -- no CFA register defined in row 0 "
503 "for UnwindPlan '%s'",
505 }
506 }
507 return false;
508 }
509
512 return true;
513
514 if (!addr.IsValid())
515 return true;
516
518 return true;
519
520 return false;
521}
522
523void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const {
524 if (!m_source_name.IsEmpty()) {
525 s.Printf("This UnwindPlan originally sourced from %s\n",
527 }
529 TargetSP target_sp(thread->CalculateTarget());
530 addr_t lsda_load_addr = m_lsda_address.GetLoadAddress(target_sp.get());
531 addr_t personality_func_load_addr =
533
534 if (lsda_load_addr != LLDB_INVALID_ADDRESS &&
535 personality_func_load_addr != LLDB_INVALID_ADDRESS) {
536 s.Printf("LSDA address 0x%" PRIx64
537 ", personality routine is at address 0x%" PRIx64 "\n",
538 lsda_load_addr, personality_func_load_addr);
539 }
540 }
541 s.Printf("This UnwindPlan is sourced from the compiler: ");
543 case eLazyBoolYes:
544 s.Printf("yes.\n");
545 break;
546 case eLazyBoolNo:
547 s.Printf("no.\n");
548 break;
550 s.Printf("not specified.\n");
551 break;
552 }
553 s.Printf("This UnwindPlan is valid at all instruction locations: ");
555 case eLazyBoolYes:
556 s.Printf("yes.\n");
557 break;
558 case eLazyBoolNo:
559 s.Printf("no.\n");
560 break;
562 s.Printf("not specified.\n");
563 break;
564 }
565 s.Printf("This UnwindPlan is for a trap handler function: ");
567 case eLazyBoolYes:
568 s.Printf("yes.\n");
569 break;
570 case eLazyBoolNo:
571 s.Printf("no.\n");
572 break;
574 s.Printf("not specified.\n");
575 break;
576 }
579 s.PutCString("Address range of this UnwindPlan: ");
580 TargetSP target_sp(thread->CalculateTarget());
581 m_plan_valid_address_range.Dump(&s, target_sp.get(),
583 s.EOL();
584 }
585 collection::const_iterator pos, begin = m_row_list.begin(),
586 end = m_row_list.end();
587 for (pos = begin; pos != end; ++pos) {
588 s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos));
589 (*pos)->Dump(s, this, thread, base_addr);
590 s.Printf("\n");
591 }
592}
593
594void UnwindPlan::SetSourceName(const char *source) {
595 m_source_name = ConstString(source);
596}
597
599
601 uint32_t unwind_reg) const {
602 if (thread) {
603 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
604 if (reg_ctx) {
605 uint32_t reg;
607 reg = unwind_reg;
608 else
610 unwind_reg);
611 if (reg != LLDB_INVALID_REGNUM)
612 return reg_ctx->GetRegisterInfoAtIndex(reg);
613 }
614 }
615 return nullptr;
616}
#define LLDB_LOGF(log,...)
Definition: Log.h:376
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:162
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:709
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition: ArchSpec.cpp:756
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:1408
lldb::ProcessSP GetProcess() const
Definition: Thread.h:157
struct lldb_private::UnwindPlan::Row::AbstractRegisterLocation::@24::@25 expr
void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
Definition: UnwindPlan.cpp:67
void Dump(Stream &s, const UnwindPlan *unwind_plan, const UnwindPlan::Row *row, Thread *thread, bool verbose) const
Definition: UnwindPlan.cpp:95
union lldb_private::UnwindPlan::Row::AbstractRegisterLocation::@24 m_location
bool operator==(const AbstractRegisterLocation &rhs) const
Definition: UnwindPlan.cpp:25
void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len)
Definition: UnwindPlan.cpp:58
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:172
struct lldb_private::UnwindPlan::Row::FAValue::@26::@27 reg
struct lldb_private::UnwindPlan::Row::FAValue::@26::@28 expr
bool SetRegisterLocationToIsConstant(uint32_t reg_num, uint64_t constant, bool can_replace)
Definition: UnwindPlan.cpp:372
bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
Definition: UnwindPlan.cpp:298
bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace)
Definition: UnwindPlan.cpp:350
bool SetRegisterLocationToIsDWARFExpression(uint32_t reg_num, const uint8_t *opcodes, uint32_t len, bool can_replace)
This method does not make a copy of the opcodes memory, it is assumed to have the same lifetime as th...
Definition: UnwindPlan.cpp:361
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
Definition: UnwindPlan.cpp:286
bool GetRegisterInfo(uint32_t reg_num, AbstractRegisterLocation &register_location) const
Definition: UnwindPlan.cpp:258
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
Definition: UnwindPlan.cpp:338
void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, lldb::addr_t base_addr) const
Definition: UnwindPlan.cpp:232
bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace)
Definition: UnwindPlan.cpp:327
void RemoveRegisterInfo(uint32_t reg_num)
Definition: UnwindPlan.cpp:273
lldb::addr_t GetOffset() const
Definition: UnwindPlan.h:359
bool operator==(const Row &rhs) const
Definition: UnwindPlan.cpp:384
bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified)
Definition: UnwindPlan.cpp:310
void SetRegisterInfo(uint32_t reg_num, const AbstractRegisterLocation register_location)
Definition: UnwindPlan.cpp:280
void InsertRow(const RowSP &row_sp, bool replace_existing=false)
Definition: UnwindPlan.cpp:400
const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const
Definition: UnwindPlan.cpp:437
lldb::RegisterKind m_register_kind
Definition: UnwindPlan.h:570
const RegisterInfo * GetRegisterInfo(Thread *thread, uint32_t reg_num) const
Definition: UnwindPlan.cpp:600
lldb_private::LazyBool m_plan_is_for_signal_trap
Definition: UnwindPlan.h:580
const UnwindPlan::RowSP GetLastRow() const
Definition: UnwindPlan.cpp:450
void SetPlanValidAddressRange(const AddressRange &range)
Definition: UnwindPlan.cpp:461
AddressRange m_plan_valid_address_range
Definition: UnwindPlan.h:569
bool IsValidRowIndex(uint32_t idx) const
Definition: UnwindPlan.cpp:433
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:392
lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations
Definition: UnwindPlan.h:579
UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const
Definition: UnwindPlan.cpp:415
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:429
lldb_private::ConstString m_source_name
Definition: UnwindPlan.h:577
bool PlanValidAtAddress(Address addr)
Definition: UnwindPlan.cpp:466
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:594
void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const
Definition: UnwindPlan.cpp:523
lldb_private::ConstString GetSourceName() const
Definition: UnwindPlan.cpp:598
lldb_private::LazyBool m_plan_is_sourced_from_compiler
Definition: UnwindPlan.h:578
#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:332
Definition: SBAddress.h:15
uint64_t offset_t
Definition: lldb-types.h:85
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:389
@ eByteOrderLittle
uint64_t addr_t
Definition: lldb-types.h:80
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:448
@ 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.