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;
151 SectionSP §ion_sp,
Type type)
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) {
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))
429 bool clear_address_zeroth_bit =
false;
431 if (arch.GetTriple().getArch() == llvm::Triple::arm ||
432 arch.GetTriple().getArch() == llvm::Triple::thumb)
433 clear_address_zeroth_bit =
true;
447 next_entry = current_entry + len + 12;
448 cie_offset = current_entry + 12 - cie_id;
451 next_entry = current_entry + len + 4;
452 cie_offset = current_entry + 4 - cie_id;
457 "of {0:x} found in cie/fde at {1:x}",
458 next_entry, current_entry));
471 auto cie_sp =
ParseCIE(current_entry);
479 m_cie_map[current_entry] = std::move(cie_sp);
489 "found in cie/fde at {1:x}",
490 cie_offset, current_entry));
506 text_addr, data_addr);
507 if (clear_address_zeroth_bit)
512 pc_rel_addr, text_addr, data_addr);
517 "unable to find CIE at {0:x} for cie_id = {1:x} for entry at {2:x}.",
518 cie_offset, cie_id, current_entry));
556 cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset;
570 assert(cie !=
nullptr);
572 const dw_offset_t end_offset = current_entry + length + (is_64bit ? 12 : 4);
579 text_addr, data_addr);
582 pc_rel_addr, text_addr, data_addr);
593 lsda_data_file_address =
595 pc_rel_addr, text_addr, data_addr);
596 if (offset - saved_offset != aug_data_len) {
601 offset = saved_offset;
603 offset += aug_data_len;
609 Address personality_function_ptr;
616 personality_function_ptr);
635 std::vector<UnwindPlan::RowSP> stack;
640 uint8_t primary_opcode = inst & 0xC0;
641 uint8_t extended_opcode = inst & 0x3F;
645 if (primary_opcode) {
646 switch (primary_opcode) {
647 case DW_CFA_advance_loc:
656 *newrow = *row.get();
662 case DW_CFA_restore: {
676 row->SetRegisterInfo(reg_num, reg_location);
681 switch (extended_opcode) {
691 *newrow = *row.get();
698 case DW_CFA_advance_loc1:
705 *newrow = *row.get();
711 case DW_CFA_advance_loc2:
718 *newrow = *row.get();
724 case DW_CFA_advance_loc4:
731 *newrow = *row.get();
737 case DW_CFA_restore_extended:
746 row->SetRegisterInfo(reg_num, reg_location);
750 case DW_CFA_remember_state:
759 stack.push_back(row);
761 *newrow = *row.get();
766 case DW_CFA_restore_state:
777 "DWARFCallFrameInfo::{0}(dwarf_offset: "
778 "{1:x16}, startaddr: [{2:x16}] encountered "
779 "DW_CFA_restore_state but state stack "
780 "is empty. Corrupt unwind info?",
787 row->SetOffset(offset);
791 case DW_CFA_GNU_args_size:
803 case DW_CFA_val_offset:
804 case DW_CFA_val_offset_sf:
817 uint8_t extended_opcode,
823 if (primary_opcode) {
824 switch (primary_opcode) {
825 case DW_CFA_offset: {
832 uint8_t reg_num = extended_opcode;
840 switch (extended_opcode) {
844 case DW_CFA_offset_extended:
857 case DW_CFA_undefined:
869 case DW_CFA_same_value:
881 case DW_CFA_register:
905 case DW_CFA_def_cfa_register:
916 case DW_CFA_def_cfa_offset:
927 case DW_CFA_def_cfa_expression:
930 const uint8_t *block_data =
936 case DW_CFA_expression:
947 const uint8_t *block_data =
955 case DW_CFA_offset_extended_sf:
969 case DW_CFA_def_cfa_sf:
981 case DW_CFA_def_cfa_offset_sf:
992 case DW_CFA_val_expression:
1003 const uint8_t *block_data =
static uint64_t GetGNUEHPointer(const DataExtractor &DE, 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.
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