LLDB  mainline
UnwindPlan.cpp
Go to the documentation of this file.
1 //===-- UnwindPlan.cpp ----------------------------------*- C++ -*-===//
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 
12 #include "lldb/Target/Process.h"
14 #include "lldb/Target/Target.h"
15 #include "lldb/Target/Thread.h"
17 #include "lldb/Utility/Log.h"
18 
19 using namespace lldb;
20 using namespace lldb_private;
21 
24  if (m_type == rhs.m_type) {
25  switch (m_type) {
26  case unspecified:
27  case undefined:
28  case same:
29  return true;
30 
31  case atCFAPlusOffset:
32  case isCFAPlusOffset:
33  case atAFAPlusOffset:
34  case isAFAPlusOffset:
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,
44  m_location.expr.length);
45  break;
46  }
47  }
48  return false;
49 }
50 
51 // This function doesn't copy the dwarf expression bytes; they must remain in
52 // allocated memory for the lifespan of this UnwindPlan object.
53 void UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression(
54  const uint8_t *opcodes, uint32_t len) {
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
61 // allocated memory for the lifespan of this UnwindPlan object.
62 void UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression(
63  const uint8_t *opcodes, uint32_t len) {
64  m_type = isDWARFExpression;
65  m_location.expr.opcodes = opcodes;
66  m_location.expr.length = len;
67 }
68 
69 static llvm::Optional<std::pair<lldb::ByteOrder, uint32_t>>
71  if (!thread)
72  return llvm::None;
73  ProcessSP process_sp = thread->GetProcess();
74  if (!process_sp)
75  return llvm::None;
76  ArchSpec arch = process_sp->GetTarget().GetArchitecture();
77  return std::make_pair(arch.GetByteOrder(), arch.GetAddressByteSize());
78 }
79 
80 static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *thread) {
81  if (auto order_and_width = GetByteOrderAndAddrSize(thread)) {
82  DataExtractor extractor(expr.data(), expr.size(), order_and_width->first,
83  order_and_width->second);
84  if (!DWARFExpression::PrintDWARFExpression(s, extractor,
85  order_and_width->second,
86  /*dwarf_ref_size*/ 4,
87  /*location_expression*/ false))
88  s.PutCString("invalid-dwarf-expr");
89  } else
90  s.PutCString("dwarf-expr");
91 }
92 
93 void UnwindPlan::Row::RegisterLocation::Dump(Stream &s,
94  const UnwindPlan *unwind_plan,
95  const UnwindPlan::Row *row,
96  Thread *thread,
97  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::makeArrayRef(m_location.expr.opcodes, m_location.expr.length),
152  thread);
153  if (m_type == atDWARFExpression)
154  s.PutChar(']');
155  } break;
156  }
157 }
158 
159 static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan,
160  Thread *thread, uint32_t reg_num) {
161  const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo(thread, reg_num);
162  if (reg_info)
163  s.PutCString(reg_info->name);
164  else
165  s.Printf("reg(%u)", reg_num);
166 }
167 
170  if (m_type == rhs.m_type) {
171  switch (m_type) {
172  case unspecified:
173  return true;
174 
175  case isRegisterPlusOffset:
176  return m_value.reg.offset == rhs.m_value.reg.offset;
177 
178  case isRegisterDereferenced:
179  return m_value.reg.reg_num == rhs.m_value.reg.reg_num;
180 
181  case isDWARFExpression:
182  if (m_value.expr.length == rhs.m_value.expr.length)
183  return !memcmp(m_value.expr.opcodes, rhs.m_value.expr.opcodes,
184  m_value.expr.length);
185  break;
186  }
187  }
188  return false;
189 }
190 
191 void UnwindPlan::Row::FAValue::Dump(Stream &s, const UnwindPlan *unwind_plan,
192  Thread *thread) const {
193  switch (m_type) {
194  case isRegisterPlusOffset:
195  DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
196  s.Printf("%+3d", m_value.reg.offset);
197  break;
198  case isRegisterDereferenced:
199  s.PutChar('[');
200  DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
201  s.PutChar(']');
202  break;
203  case isDWARFExpression:
204  DumpDWARFExpr(s,
205  llvm::makeArrayRef(m_value.expr.opcodes, m_value.expr.length),
206  thread);
207  break;
208  default:
209  s.PutCString("unspecified");
210  break;
211  }
212 }
213 
214 void UnwindPlan::Row::Clear() {
215  m_cfa_value.SetUnspecified();
216  m_afa_value.SetUnspecified();
217  m_offset = 0;
218  m_register_locations.clear();
219 }
220 
221 void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan,
222  Thread *thread, addr_t base_addr) const {
223  if (base_addr != LLDB_INVALID_ADDRESS)
224  s.Printf("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
225  else
226  s.Printf("%4" PRId64 ": CFA=", GetOffset());
227 
228  m_cfa_value.Dump(s, unwind_plan, thread);
229 
230  if (!m_afa_value.IsUnspecified()) {
231  s.Printf(" AFA=");
232  m_afa_value.Dump(s, unwind_plan, thread);
233  }
234 
235  s.Printf(" => ");
236  for (collection::const_iterator idx = m_register_locations.begin();
237  idx != m_register_locations.end(); ++idx) {
238  DumpRegisterName(s, unwind_plan, thread, idx->first);
239  const bool verbose = false;
240  idx->second.Dump(s, unwind_plan, this, thread, verbose);
241  s.PutChar(' ');
242  }
243  s.EOL();
244 }
245 
246 UnwindPlan::Row::Row()
247  : m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations() {}
248 
250  uint32_t reg_num,
251  UnwindPlan::Row::RegisterLocation &register_location) const {
252  collection::const_iterator pos = m_register_locations.find(reg_num);
253  if (pos != m_register_locations.end()) {
254  register_location = pos->second;
255  return true;
256  }
257  return false;
258 }
259 
261  collection::const_iterator pos = m_register_locations.find(reg_num);
262  if (pos != m_register_locations.end()) {
263  m_register_locations.erase(pos);
264  }
265 }
266 
268  uint32_t reg_num,
269  const UnwindPlan::Row::RegisterLocation register_location) {
270  m_register_locations[reg_num] = register_location;
271 }
272 
274  int32_t offset,
275  bool can_replace) {
276  if (!can_replace &&
277  m_register_locations.find(reg_num) != m_register_locations.end())
278  return false;
279  RegisterLocation reg_loc;
280  reg_loc.SetAtCFAPlusOffset(offset);
281  m_register_locations[reg_num] = reg_loc;
282  return true;
283 }
284 
286  int32_t offset,
287  bool can_replace) {
288  if (!can_replace &&
289  m_register_locations.find(reg_num) != m_register_locations.end())
290  return false;
291  RegisterLocation reg_loc;
292  reg_loc.SetIsCFAPlusOffset(offset);
293  m_register_locations[reg_num] = reg_loc;
294  return true;
295 }
296 
298  uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) {
299  collection::iterator pos = m_register_locations.find(reg_num);
300  collection::iterator end = m_register_locations.end();
301 
302  if (pos != end) {
303  if (!can_replace)
304  return false;
305  if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
306  return false;
307  }
308  RegisterLocation reg_loc;
309  reg_loc.SetUndefined();
310  m_register_locations[reg_num] = reg_loc;
311  return true;
312 }
313 
315  bool can_replace) {
316  if (!can_replace &&
317  m_register_locations.find(reg_num) != m_register_locations.end())
318  return false;
319  RegisterLocation reg_loc;
320  reg_loc.SetUnspecified();
321  m_register_locations[reg_num] = reg_loc;
322  return true;
323 }
324 
326  uint32_t other_reg_num,
327  bool can_replace) {
328  if (!can_replace &&
329  m_register_locations.find(reg_num) != m_register_locations.end())
330  return false;
331  RegisterLocation reg_loc;
332  reg_loc.SetInRegister(other_reg_num);
333  m_register_locations[reg_num] = reg_loc;
334  return true;
335 }
336 
338  bool must_replace) {
339  if (must_replace &&
340  m_register_locations.find(reg_num) == m_register_locations.end())
341  return false;
342  RegisterLocation reg_loc;
343  reg_loc.SetSame();
344  m_register_locations[reg_num] = reg_loc;
345  return true;
346 }
347 
349  return m_offset == rhs.m_offset &&
350  m_cfa_value == rhs.m_cfa_value &&
351  m_afa_value == rhs.m_afa_value &&
353 }
354 
356  if (m_row_list.empty() ||
357  m_row_list.back()->GetOffset() != row_sp->GetOffset())
358  m_row_list.push_back(row_sp);
359  else
360  m_row_list.back() = row_sp;
361 }
362 
364  bool replace_existing) {
365  collection::iterator it = m_row_list.begin();
366  while (it != m_row_list.end()) {
367  RowSP row = *it;
368  if (row->GetOffset() >= row_sp->GetOffset())
369  break;
370  it++;
371  }
372  if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset())
373  m_row_list.insert(it, row_sp);
374  else if (replace_existing)
375  *it = row_sp;
376 }
377 
379  RowSP row;
380  if (!m_row_list.empty()) {
381  if (offset == -1)
382  row = m_row_list.back();
383  else {
384  collection::const_iterator pos, end = m_row_list.end();
385  for (pos = m_row_list.begin(); pos != end; ++pos) {
386  if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset))
387  row = *pos;
388  else
389  break;
390  }
391  }
392  }
393  return row;
394 }
395 
397  return idx < m_row_list.size();
398 }
399 
401  if (idx < m_row_list.size())
402  return m_row_list[idx];
403  else {
405  if (log)
406  log->Printf("error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index "
407  "(number rows is %u)",
408  idx, (uint32_t)m_row_list.size());
409  return UnwindPlan::RowSP();
410  }
411 }
412 
414  if (m_row_list.empty()) {
416  if (log)
417  log->Printf("UnwindPlan::GetLastRow() when rows are empty");
418  return UnwindPlan::RowSP();
419  }
420  return m_row_list.back();
421 }
422 
423 int UnwindPlan::GetRowCount() const { return m_row_list.size(); }
424 
426  if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
427  m_plan_valid_address_range = range;
428 }
429 
431  // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
432  if (GetRowCount() == 0) {
434  if (log) {
435  StreamString s;
436  if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
437  log->Printf("UnwindPlan is invalid -- no unwind rows for UnwindPlan "
438  "'%s' at address %s",
439  m_source_name.GetCString(), s.GetData());
440  } else {
441  log->Printf(
442  "UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
443  m_source_name.GetCString());
444  }
445  }
446  return false;
447  }
448 
449  // If the 0th Row of unwind instructions is missing, or if it doesn't provide
450  // a register to use to find the Canonical Frame Address, this is not a valid
451  // UnwindPlan.
452  if (GetRowAtIndex(0).get() == nullptr ||
453  GetRowAtIndex(0)->GetCFAValue().GetValueType() ==
456  if (log) {
457  StreamString s;
458  if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
459  log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 "
460  "for UnwindPlan '%s' at address %s",
461  m_source_name.GetCString(), s.GetData());
462  } else {
463  log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 "
464  "for UnwindPlan '%s'",
465  m_source_name.GetCString());
466  }
467  }
468  return false;
469  }
470 
471  if (!m_plan_valid_address_range.GetBaseAddress().IsValid() ||
472  m_plan_valid_address_range.GetByteSize() == 0)
473  return true;
474 
475  if (!addr.IsValid())
476  return true;
477 
478  if (m_plan_valid_address_range.ContainsFileAddress(addr))
479  return true;
480 
481  return false;
482 }
483 
484 void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const {
485  if (!m_source_name.IsEmpty()) {
486  s.Printf("This UnwindPlan originally sourced from %s\n",
487  m_source_name.GetCString());
488  }
489  if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) {
490  TargetSP target_sp(thread->CalculateTarget());
491  addr_t lsda_load_addr = m_lsda_address.GetLoadAddress(target_sp.get());
492  addr_t personality_func_load_addr =
493  m_personality_func_addr.GetLoadAddress(target_sp.get());
494 
495  if (lsda_load_addr != LLDB_INVALID_ADDRESS &&
496  personality_func_load_addr != LLDB_INVALID_ADDRESS) {
497  s.Printf("LSDA address 0x%" PRIx64
498  ", personality routine is at address 0x%" PRIx64 "\n",
499  lsda_load_addr, personality_func_load_addr);
500  }
501  }
502  s.Printf("This UnwindPlan is sourced from the compiler: ");
503  switch (m_plan_is_sourced_from_compiler) {
504  case eLazyBoolYes:
505  s.Printf("yes.\n");
506  break;
507  case eLazyBoolNo:
508  s.Printf("no.\n");
509  break;
510  case eLazyBoolCalculate:
511  s.Printf("not specified.\n");
512  break;
513  }
514  s.Printf("This UnwindPlan is valid at all instruction locations: ");
515  switch (m_plan_is_valid_at_all_instruction_locations) {
516  case eLazyBoolYes:
517  s.Printf("yes.\n");
518  break;
519  case eLazyBoolNo:
520  s.Printf("no.\n");
521  break;
522  case eLazyBoolCalculate:
523  s.Printf("not specified.\n");
524  break;
525  }
526  if (m_plan_valid_address_range.GetBaseAddress().IsValid() &&
527  m_plan_valid_address_range.GetByteSize() > 0) {
528  s.PutCString("Address range of this UnwindPlan: ");
529  TargetSP target_sp(thread->CalculateTarget());
530  m_plan_valid_address_range.Dump(&s, target_sp.get(),
532  s.EOL();
533  }
534  collection::const_iterator pos, begin = m_row_list.begin(),
535  end = m_row_list.end();
536  for (pos = begin; pos != end; ++pos) {
537  s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos));
538  (*pos)->Dump(s, this, thread, base_addr);
539  }
540 }
541 
542 void UnwindPlan::SetSourceName(const char *source) {
543  m_source_name = ConstString(source);
544 }
545 
546 ConstString UnwindPlan::GetSourceName() const { return m_source_name; }
547 
548 const RegisterInfo *UnwindPlan::GetRegisterInfo(Thread *thread,
549  uint32_t unwind_reg) const {
550  if (thread) {
551  RegisterContext *reg_ctx = thread->GetRegisterContext().get();
552  if (reg_ctx) {
553  uint32_t reg;
554  if (m_register_kind == eRegisterKindLLDB)
555  reg = unwind_reg;
556  else
557  reg = reg_ctx->ConvertRegisterKindToRegisterNumber(m_register_kind,
558  unwind_reg);
559  if (reg != LLDB_INVALID_REGNUM)
560  return reg_ctx->GetRegisterInfoAtIndex(reg);
561  }
562  }
563  return nullptr;
564 }
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
An data extractor class.
Definition: DataExtractor.h:47
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:542
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
lldb::addr_t GetByteSize() const
Get accessor for the byte size of this range.
Definition: AddressRange.h:232
void InsertRow(const RowSP &row_sp, bool replace_existing=false)
Definition: UnwindPlan.cpp:363
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
struct lldb_private::UnwindPlan::Row::FAValue::@28::@30 expr
bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified)
Definition: UnwindPlan.cpp:297
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition: ArchSpec.cpp:742
bool LLDB_API operator==(const SBAddress &lhs, const SBAddress &rhs)
Definition: SBAddress.cpp:66
static void DumpDWARFExpr(Stream &s, llvm::ArrayRef< uint8_t > expr, Thread *thread)
Definition: UnwindPlan.cpp:80
bool operator==(const Row &rhs) const
Definition: UnwindPlan.cpp:348
bool Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style=DumpStyleInvalid, uint32_t addr_byte_size=UINT32_MAX) const
Dump a description of this object to a Stream.
Definition: Address.cpp:374
virtual uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num)=0
Convert from a given register numbering scheme to the lldb register numbering scheme.
An architecture specification class.
Definition: ArchSpec.h:32
const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const
Definition: UnwindPlan.cpp:400
const RegisterInfo * GetRegisterInfo(Thread *thread, uint32_t reg_num) const
Definition: UnwindPlan.cpp:548
void SetRegisterInfo(uint32_t reg_num, const RegisterLocation register_location)
Definition: UnwindPlan.cpp:267
bool IsValidRowIndex(uint32_t idx) const
Definition: UnwindPlan.cpp:396
#define LIBLLDB_LOG_UNWIND
Definition: Logging.h:29
const char * GetData() const
Definition: StreamString.h:43
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
Definition: UnwindPlan.cpp:325
void SetPlanValidAddressRange(const AddressRange &range)
Definition: UnwindPlan.cpp:425
bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
Definition: UnwindPlan.cpp:285
void RemoveRegisterInfo(uint32_t reg_num)
Definition: UnwindPlan.cpp:260
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
uint64_t offset_t
Definition: lldb-types.h:87
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:127
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:366
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:355
lldb::TargetSP CalculateTarget() override
Definition: Thread.cpp:1584
virtual lldb::RegisterContextSP GetRegisterContext()=0
virtual const RegisterInfo * GetRegisterInfoAtIndex(size_t reg)=0
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition: ArchSpec.cpp:788
Display as the section name + offset.
Definition: Address.h:86
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
struct lldb_private::UnwindPlan::Row::FAValue::@28::@29 reg
A section + offset based address class.
Definition: Address.h:80
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:343
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
Definition: UnwindPlan.cpp:273
lldb::ProcessSP GetProcess() const
Definition: Thread.h:154
void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const
Definition: UnwindPlan.cpp:484
lldb_private::ConstString GetSourceName() const
Definition: UnwindPlan.cpp:546
size_t PutChar(char ch)
Definition: Stream.cpp:103
const UnwindPlan::RowSP GetLastRow() const
Definition: UnwindPlan.cpp:413
uint64_t addr_t
Definition: lldb-types.h:83
bool GetRegisterInfo(uint32_t reg_num, RegisterLocation &register_location) const
Definition: UnwindPlan.cpp:249
bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace)
Definition: UnwindPlan.cpp:314
struct lldb_private::UnwindPlan::Row::RegisterLocation::@26::@27 expr
A uniqued constant string class.
Definition: ConstString.h:38
Definition: SBAddress.h:15
static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, uint32_t reg_num)
Definition: UnwindPlan.cpp:159
static llvm::Optional< std::pair< lldb::ByteOrder, uint32_t > > GetByteOrderAndAddrSize(Thread *thread)
Definition: UnwindPlan.cpp:70
Address & GetBaseAddress()
Get accessor for the base address of the range.
Definition: AddressRange.h:220
UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const
Definition: UnwindPlan.cpp:378
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
A section + offset based address range class.
Definition: AddressRange.h:32
bool PlanValidAtAddress(Address addr)
Definition: UnwindPlan.cpp:430
bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace)
Definition: UnwindPlan.cpp:337
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:90