18#include "llvm/DebugInfo/DIContext.h"
19#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
59 const uint8_t *opcodes, uint32_t len) {
60 m_type = atDWARFExpression;
61 m_location.expr.opcodes = opcodes;
62 m_location.expr.length = len;
68 const uint8_t *opcodes, uint32_t len) {
69 m_type = isDWARFExpression;
70 m_location.expr.opcodes = opcodes;
71 m_location.expr.length = len;
74static std::optional<std::pair<lldb::ByteOrder, uint32_t>>
81 ArchSpec arch = process_sp->GetTarget().GetArchitecture();
88 order_and_width->second);
89 llvm::DWARFExpression(data, order_and_width->second, llvm::dwarf::DWARF32)
90 .print(s.
AsRawOstream(), llvm::DIDumpOptions(),
nullptr);
97 Thread *thread,
bool verbose)
const {
115 case atCFAPlusOffset:
116 case isCFAPlusOffset: {
118 if (m_type == atCFAPlusOffset)
120 s.
Printf(
"CFA%+d", m_location.offset);
121 if (m_type == atCFAPlusOffset)
125 case atAFAPlusOffset:
126 case isAFAPlusOffset: {
128 if (m_type == atAFAPlusOffset)
130 s.
Printf(
"AFA%+d", m_location.offset);
131 if (m_type == atAFAPlusOffset)
135 case inOtherRegister: {
138 other_reg_info = unwind_plan->
GetRegisterInfo(thread, m_location.reg_num);
142 s.
Printf(
"=reg(%u)", m_location.reg_num);
145 case atDWARFExpression:
146 case isDWARFExpression: {
148 if (m_type == atDWARFExpression)
151 s, llvm::ArrayRef(m_location.expr.opcodes, m_location.expr.length),
153 if (m_type == atDWARFExpression)
157 s.
Printf(
"=0x%" PRIx64, m_location.constant_value);
163 Thread *thread, uint32_t reg_num) {
168 s.
Printf(
"reg(%u)", reg_num);
173 if (m_type == rhs.
m_type) {
179 case isRegisterPlusOffset:
182 case isRegisterDereferenced:
185 case isDWARFExpression:
188 m_value.expr.length);
200 case isRegisterPlusOffset:
202 s.
Printf(
"%+3d", m_value.reg.offset);
204 case isRegisterDereferenced:
209 case isDWARFExpression:
210 DumpDWARFExpr(s, llvm::ArrayRef(m_value.expr.opcodes, m_value.expr.length),
217 s.
Printf(
"RaSearch@SP%+d", m_value.ra_search_offset);
220 s.
Printf(
"0x%" PRIx64, m_value.constant);
250 const bool verbose =
false;
251 idx->second.Dump(s, unwind_plan,
this, thread, verbose);
261 collection::const_iterator pos = m_register_locations.find(reg_num);
262 if (pos != m_register_locations.end()) {
263 register_location = pos->second;
266 if (m_unspecified_registers_are_undefined) {
274 collection::const_iterator pos = m_register_locations.find(reg_num);
275 if (pos != m_register_locations.end()) {
276 m_register_locations.erase(pos);
283 m_register_locations[reg_num] = register_location;
290 m_register_locations.find(reg_num) != m_register_locations.end())
294 m_register_locations[reg_num] = reg_loc;
302 m_register_locations.find(reg_num) != m_register_locations.end())
306 m_register_locations[reg_num] = reg_loc;
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();
318 if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
323 m_register_locations[reg_num] = reg_loc;
330 m_register_locations.find(reg_num) != m_register_locations.end())
334 m_register_locations[reg_num] = reg_loc;
339 uint32_t other_reg_num,
342 m_register_locations.find(reg_num) != m_register_locations.end())
346 m_register_locations[reg_num] = reg_loc;
353 m_register_locations.find(reg_num) == m_register_locations.end())
357 m_register_locations[reg_num] = reg_loc;
362 uint32_t reg_num,
const uint8_t *opcodes, uint32_t len,
bool can_replace) {
364 m_register_locations.find(reg_num) != m_register_locations.end())
368 m_register_locations[reg_num] = reg_loc;
376 m_register_locations.find(reg_num) != m_register_locations.end())
380 m_register_locations[reg_num] = reg_loc;
387 m_unspecified_registers_are_undefined ==
394 m_row_list.back()->GetOffset() != row_sp->GetOffset())
401 bool replace_existing) {
405 if (row->GetOffset() >= row_sp->GetOffset())
409 if (it ==
m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset())
411 else if (replace_existing)
421 collection::const_iterator pos, end =
m_row_list.end();
422 for (pos =
m_row_list.begin(); pos != end; ++pos) {
443 "error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index "
444 "(number rows is %u)",
453 LLDB_LOGF(log,
"UnwindPlan::GetLastRow() when rows are empty");
474 "UnwindPlan is invalid -- no unwind rows for UnwindPlan "
475 "'%s' at address %s",
479 "UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
497 "UnwindPlan is invalid -- no CFA register defined in row 0 "
498 "for UnwindPlan '%s' at address %s",
502 "UnwindPlan is invalid -- no CFA register defined in row 0 "
503 "for UnwindPlan '%s'",
525 s.
Printf(
"This UnwindPlan originally sourced from %s\n",
531 addr_t personality_func_load_addr =
536 s.
Printf(
"LSDA address 0x%" PRIx64
537 ", personality routine is at address 0x%" PRIx64
"\n",
538 lsda_load_addr, personality_func_load_addr);
541 s.
Printf(
"This UnwindPlan is sourced from the compiler: ");
550 s.
Printf(
"not specified.\n");
553 s.
Printf(
"This UnwindPlan is valid at all instruction locations: ");
562 s.
Printf(
"not specified.\n");
565 s.
Printf(
"This UnwindPlan is for a trap handler function: ");
574 s.
Printf(
"not specified.\n");
579 s.
PutCString(
"Address range of this UnwindPlan: ");
585 collection::const_iterator pos, begin =
m_row_list.begin(),
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);
601 uint32_t unwind_reg)
const {
#define LLDB_LOGF(log,...)
static std::optional< std::pair< lldb::ByteOrder, uint32_t > > GetByteOrderAndAddrSize(Thread *thread)
static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, uint32_t reg_num)
static void DumpDWARFExpr(Stream &s, llvm::ArrayRef< uint8_t > expr, Thread *thread)
A section + offset based address range class.
Address & GetBaseAddress()
Get accessor for the base address of the range.
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.
A section + offset based address class.
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
@ DumpStyleSectionNameOffset
Display as the section name + offset.
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.
bool IsValid() const
Check if the object state is valid.
An architecture specification class.
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
A uniqued constant string class.
bool IsEmpty() const
Test for empty string.
const char * GetCString() const
Get the string value as a C string.
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
A stream class that can stream formatted output to a file.
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
size_t EOL()
Output and End of Line character to the stream.
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb::TargetSP CalculateTarget() override
lldb::ProcessSP GetProcess() const
struct lldb_private::UnwindPlan::Row::AbstractRegisterLocation::@24::@25 expr
void SetIsConstant(uint64_t value)
void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
void SetAtCFAPlusOffset(int32_t offset)
void Dump(Stream &s, const UnwindPlan *unwind_plan, const UnwindPlan::Row *row, Thread *thread, bool verbose) const
union lldb_private::UnwindPlan::Row::AbstractRegisterLocation::@24 m_location
void SetInRegister(uint32_t reg_num)
bool operator==(const AbstractRegisterLocation &rhs) const
void SetIsCFAPlusOffset(int32_t offset)
void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len)
void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread) const
union lldb_private::UnwindPlan::Row::FAValue::@26 m_value
bool IsUnspecified() const
bool operator==(const FAValue &rhs) const
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)
bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace)
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...
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
collection m_register_locations
bool m_unspecified_registers_are_undefined
bool GetRegisterInfo(uint32_t reg_num, AbstractRegisterLocation ®ister_location) const
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, lldb::addr_t base_addr) const
bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace)
void RemoveRegisterInfo(uint32_t reg_num)
lldb::addr_t GetOffset() const
bool operator==(const Row &rhs) const
bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified)
void SetRegisterInfo(uint32_t reg_num, const AbstractRegisterLocation register_location)
void InsertRow(const RowSP &row_sp, bool replace_existing=false)
const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const
Address m_personality_func_addr
lldb::RegisterKind m_register_kind
const RegisterInfo * GetRegisterInfo(Thread *thread, uint32_t reg_num) const
lldb_private::LazyBool m_plan_is_for_signal_trap
const UnwindPlan::RowSP GetLastRow() const
void SetPlanValidAddressRange(const AddressRange &range)
AddressRange m_plan_valid_address_range
bool IsValidRowIndex(uint32_t idx) const
void AppendRow(const RowSP &row_sp)
lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations
UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const
std::shared_ptr< Row > RowSP
lldb_private::ConstString m_source_name
bool PlanValidAtAddress(Address addr)
void SetSourceName(const char *)
void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const
lldb_private::ConstString GetSourceName() const
lldb_private::LazyBool m_plan_is_sourced_from_compiler
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_REGNUM
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.
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Target > TargetSP
@ 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.