37 uint32_t eh_ptr_enc,
addr_t pc_rel_addr,
addr_t text_addr,
40 if (eh_ptr_enc == DW_EH_PE_omit)
43 uint64_t baseAddress = 0;
44 uint64_t addressValue = 0;
46 assert(addr_size == 4 || addr_size == 8);
48 bool signExtendValue =
false;
50 switch (eh_ptr_enc & 0x70) {
52 signExtendValue =
true;
53 baseAddress = *offset_ptr;
55 baseAddress += pc_rel_addr;
61 case DW_EH_PE_textrel:
62 signExtendValue =
true;
64 baseAddress = text_addr;
71 case DW_EH_PE_datarel:
72 signExtendValue =
true;
74 baseAddress = data_addr;
81 case DW_EH_PE_funcrel:
82 signExtendValue =
true;
85 case DW_EH_PE_aligned: {
88 assert(addr_size != 0);
91 uint32_t alignOffset = *offset_ptr % addr_size;
93 offset_ptr += addr_size - alignOffset;
103 case DW_EH_PE_absptr: {
109 case DW_EH_PE_uleb128:
112 case DW_EH_PE_udata2:
113 addressValue = DE.
GetU16(offset_ptr);
115 case DW_EH_PE_udata4:
116 addressValue = DE.
GetU32(offset_ptr);
118 case DW_EH_PE_udata8:
119 addressValue = DE.
GetU64(offset_ptr);
121 case DW_EH_PE_sleb128:
124 case DW_EH_PE_sdata2:
125 addressValue = (int16_t)DE.
GetU16(offset_ptr);
127 case DW_EH_PE_sdata4:
128 addressValue = (int32_t)DE.
GetU32(offset_ptr);
130 case DW_EH_PE_sdata8:
131 addressValue = (int64_t)DE.
GetU64(offset_ptr);
140 if (signExtendValue && addr_size <
sizeof(baseAddress)) {
141 uint64_t sign_bit = 1ull << ((addr_size * 8ull) - 1ull);
142 if (sign_bit & addressValue) {
143 uint64_t mask = ~sign_bit + 1;
144 addressValue |= mask;
147 return baseAddress + addressValue;
152 : m_objfile(objfile), m_section_sp(section_sp), m_type(type) {}
167 if (module_sp.get() ==
nullptr || module_sp->GetObjectFile() ==
nullptr ||
168 module_sp->GetObjectFile() != &
m_objfile)
181 if (module_sp.get() ==
nullptr || module_sp->GetObjectFile() ==
nullptr ||
182 module_sp->GetObjectFile() != &
m_objfile)
198std::optional<DWARFCallFrameInfo::FDEEntryMap::Entry>
219 function_info.
Clear();
222 for (
size_t i = 0; i < count; ++i) {
225 if (func_offset_data_entry) {
227 func_offset_data_entry->
base, func_offset_data_entry->
size);
228 function_info.
Append(function_offset_entry);
235 cie_map_t::iterator pos =
m_cie_map.find(cie_offset);
239 if (pos->second ==
nullptr)
242 return pos->second.get();
259 end_offset = cie_offset + length + 12;
262 end_offset = cie_offset + length + 4;
270 cie_sp->ptr_encoding = DW_EH_PE_absptr;
274 llvm::formatv(
"CIE parse error: CFI version {0} is not supported",
281 if (cie_sp->augmentation[i] ==
'\0') {
284 cie_sp->augmentation[j] =
'\0';
293 "CIE parse error: CIE augmentation string was too large "
294 "for the fixed sized buffer of {0} bytes.",
309 cie_sp->return_addr_reg_num =
314 if (cie_sp->augmentation[0]) {
318 const size_t aug_data_end = offset + aug_data_len;
319 const size_t aug_str_len = strlen(cie_sp->augmentation);
324 if (cie_sp->augmentation[0] ==
'z') {
326 size_t aug_str_idx = 0;
327 for (aug_str_idx = 1; aug_str_idx < aug_str_len; aug_str_idx++) {
328 char aug = cie_sp->augmentation[aug_str_idx];
357 m_cfi_data, &offset, arg_ptr_encoding, pc_rel_addr,
372 }
else if (strcmp(cie_sp->augmentation,
"eh") == 0) {
379 offset = (uint32_t)aug_data_end;
382 if (end_offset > offset) {
383 cie_sp->inst_offset = offset;
384 cie_sp->inst_length = end_offset - offset;
386 while (offset < end_offset) {
388 uint8_t primary_opcode = inst & 0xC0;
389 uint8_t extended_opcode = inst & 0x3F;
392 cie_sp->data_align, offset,
393 cie_sp->initial_row))
428 bool clear_address_zeroth_bit =
false;
430 if (arch.GetTriple().getArch() == llvm::Triple::arm ||
431 arch.GetTriple().getArch() == llvm::Triple::thumb)
432 clear_address_zeroth_bit =
true;
446 next_entry = current_entry + len + 12;
447 cie_offset = current_entry + 12 - cie_id;
450 next_entry = current_entry + len + 4;
451 cie_offset = current_entry + 4 - cie_id;
456 "of {0:x} found in cie/fde at {1:x}",
457 next_entry, current_entry));
470 auto cie_sp =
ParseCIE(current_entry);
478 m_cie_map[current_entry] = std::move(cie_sp);
488 "found in cie/fde at {1:x}",
489 cie_offset, current_entry));
505 text_addr, data_addr);
506 if (clear_address_zeroth_bit)
511 pc_rel_addr, text_addr, data_addr);
516 "unable to find CIE at {0:x} for cie_id = {1:x} for entry at {2:x}.",
517 cie_offset, cie_id, current_entry));
555 cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset;
569 assert(cie !=
nullptr);
571 const dw_offset_t end_offset = current_entry + length + (is_64bit ? 12 : 4);
578 text_addr, data_addr);
581 pc_rel_addr, text_addr, data_addr);
592 lsda_data_file_address =
594 pc_rel_addr, text_addr, data_addr);
595 if (offset - saved_offset != aug_data_len) {
600 offset = saved_offset;
602 offset += aug_data_len;
608 Address personality_function_ptr;
615 personality_function_ptr);
634 std::vector<UnwindPlan::RowSP> stack;
639 uint8_t primary_opcode = inst & 0xC0;
640 uint8_t extended_opcode = inst & 0x3F;
644 if (primary_opcode) {
645 switch (primary_opcode) {
646 case DW_CFA_advance_loc:
655 *newrow = *row.get();
661 case DW_CFA_restore: {
666 uint32_t reg_num = extended_opcode;
675 row->SetRegisterInfo(reg_num, reg_location);
679 row->RemoveRegisterInfo(reg_num);
685 switch (extended_opcode) {
695 *newrow = *row.get();
702 case DW_CFA_advance_loc1:
709 *newrow = *row.get();
715 case DW_CFA_advance_loc2:
722 *newrow = *row.get();
728 case DW_CFA_advance_loc4:
735 *newrow = *row.get();
741 case DW_CFA_restore_extended:
750 row->SetRegisterInfo(reg_num, reg_location);
754 case DW_CFA_remember_state:
763 stack.push_back(row);
765 *newrow = *row.get();
770 case DW_CFA_restore_state:
781 "DWARFCallFrameInfo::{0}(dwarf_offset: "
782 "{1:x16}, startaddr: [{2:x16}] encountered "
783 "DW_CFA_restore_state but state stack "
784 "is empty. Corrupt unwind info?",
791 row->SetOffset(offset);
795 case DW_CFA_GNU_args_size:
807 case DW_CFA_val_offset:
808 case DW_CFA_val_offset_sf:
821 uint8_t extended_opcode,
827 if (primary_opcode) {
828 switch (primary_opcode) {
829 case DW_CFA_offset: {
836 uint8_t reg_num = extended_opcode;
844 switch (extended_opcode) {
848 case DW_CFA_offset_extended:
861 case DW_CFA_undefined:
873 case DW_CFA_same_value:
885 case DW_CFA_register:
909 case DW_CFA_def_cfa_register:
920 case DW_CFA_def_cfa_offset:
931 case DW_CFA_def_cfa_expression:
934 const uint8_t *block_data =
940 case DW_CFA_expression:
951 const uint8_t *block_data =
959 case DW_CFA_offset_extended_sf:
973 case DW_CFA_def_cfa_sf:
985 case DW_CFA_def_cfa_offset_sf:
996 case DW_CFA_val_expression:
1007 const uint8_t *block_data =
static uint64_t GetGNUEHPointer(const DataExtractor &DE, lldb::offset_t *offset_ptr, uint32_t eh_ptr_enc, addr_t pc_rel_addr, addr_t text_addr, addr_t data_addr)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_SCOPED_TIMERF(...)
A section + offset based address range class.
Address & GetBaseAddress()
Get accessor for the base address of the range.
void SetByteSize(lldb::addr_t byte_size)
Set accessor for the byte size of this range.
lldb::addr_t GetByteSize() const
Get accessor for the byte size of this range.
A section + offset based address class.
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
lldb::addr_t GetFileAddress() const
Get the file address.
bool IsValid() const
Check if the object state is valid.
An architecture specification class.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
bool m_fde_index_initialized
lldb::RegisterKind GetRegisterKind() const
std::shared_ptr< CIE > CIESP
CIESP ParseCIE(const dw_offset_t cie_offset)
void GetFunctionAddressAndSizeVector(FunctionAddressAndSizeVector &function_info)
std::optional< FDEEntryMap::Entry > GetFirstFDEEntryInRange(const AddressRange &range)
lldb::SectionSP m_section_sp
void ForEachFDEEntries(const std::function< bool(lldb::addr_t, uint32_t, dw_offset_t)> &callback)
const CIE * GetCIE(dw_offset_t cie_offset)
std::mutex m_fde_index_mutex
bool GetAddressRange(Address addr, AddressRange &range)
bool FDEToUnwindPlan(dw_offset_t offset, Address startaddr, UnwindPlan &unwind_plan)
DWARFCallFrameInfo(ObjectFile &objfile, lldb::SectionSP §ion, Type type)
bool m_cfi_data_initialized
bool GetUnwindPlan(const Address &addr, UnwindPlan &unwind_plan)
Return an UnwindPlan based on the call frame information encoded in the FDE of this DWARFCallFrameInf...
bool HandleCommonDwarfOpcode(uint8_t primary_opcode, uint8_t extended_opcode, int32_t data_align, lldb::offset_t &offset, UnwindPlan::Row &row)
static void ReportError(std::string message, std::optional< lldb::user_id_t > debugger_id=std::nullopt, std::once_flag *once=nullptr)
Report error events.
const ConstString & GetFilename() const
Filename string const get accessor.
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
A plug-in interface definition class for object file parsers.
virtual FileSpec & GetFileSpec()
Get accessor to the object file specification.
virtual uint32_t GetAddressByteSize() const =0
Gets the address size in bytes for the current object file.
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
virtual size_t ReadSectionData(Section *section, lldb::offset_t section_offset, void *dst, size_t dst_len)
virtual ArchSpec GetArchitecture()=0
Get the ArchSpec for this object file.
Entry & GetEntryRef(size_t i)
const Entry * GetEntryAtIndex(size_t i) const
const Entry * FindEntryThatContainsOrFollows(B addr) const
void Append(const Entry &entry)
Entry * FindEntryThatContains(B addr)
void Append(const Entry &entry)
void Reserve(typename Collection::size_type size)
void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
int32_t GetOffset() const
void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset)
uint32_t GetRegisterNumber() const
void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len)
void SetInRegister(uint32_t reg_num)
void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
void SetAtCFAPlusOffset(int32_t offset)
void SlideOffset(lldb::addr_t offset)
void SetOffset(lldb::addr_t offset)
void SetRegisterInfo(uint32_t reg_num, const RegisterLocation register_location)
void SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap)
const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const
void SetRegisterKind(lldb::RegisterKind kind)
void SetPlanValidAddressRange(const AddressRange &range)
void SetReturnAddressRegister(uint32_t regnum)
bool IsValidRowIndex(uint32_t idx) const
void SetPersonalityFunctionPtr(Address presonality_func_ptr)
void AppendRow(const RowSP &row_sp)
std::shared_ptr< Row > RowSP
void SetLSDAAddress(Address lsda_addr)
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
void SetSourceName(const char *)
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
#define DW_EH_PE_MASK_ENCODING
#define LLDB_INVALID_ADDRESS
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::Section > SectionSP
std::shared_ptr< lldb_private::Module > ModuleSP
uint8_t lsda_addr_encoding
uint32_t return_addr_reg_num
lldb_private::UnwindPlan::Row initial_row
lldb::addr_t personality_loc
char augmentation[CFI_AUG_MAX_SIZE]
bool DoesIntersect(const Range &rhs) const