1 //===-- CompactUnwindInfo.h -------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef liblldb_CompactUnwindInfo_h_ 11 #define liblldb_CompactUnwindInfo_h_ 12 13 #include <mutex> 14 #include <vector> 15 16 #include "lldb/Core/RangeMap.h" 17 #include "lldb/Symbol/ObjectFile.h" 18 #include "lldb/Symbol/UnwindPlan.h" 19 #include "lldb/Utility/DataExtractor.h" 20 #include "lldb/lldb-private.h" 21 22 namespace lldb_private { 23 24 // Compact Unwind info is an unwind format used on Darwin. The unwind 25 // instructions for typical compiler-generated functions can be expressed in a 26 // 32-bit encoding. The format includes a two-level index so the unwind 27 // information for a function can be found by two binary searches in the 28 // section. It can represent both stack frames that use a frame-pointer 29 // register and frameless functions, on i386/x86_64 for instance. When a 30 // function is too complex to be represented in the compact unwind format, it 31 // calls out to eh_frame unwind instructions. 32 33 // On Mac OS X / iOS, a function will have either a compact unwind 34 // representation or an eh_frame representation. If lldb is going to benefit 35 // from the compiler's description about saved register locations, it must be 36 // able to read both sources of information. 37 38 class CompactUnwindInfo { 39 public: 40 CompactUnwindInfo(ObjectFile &objfile, lldb::SectionSP §ion); 41 42 ~CompactUnwindInfo(); 43 44 bool GetUnwindPlan(Target &target, Address addr, UnwindPlan &unwind_plan); 45 46 bool IsValid(const lldb::ProcessSP &process_sp); 47 48 private: 49 // The top level index entries of the compact unwind info 50 // (internal representation of struct 51 // unwind_info_section_header_index_entry) 52 // There are relatively few of these (one per 500/1000 functions, depending 53 // on format) so creating them on first scan will not be too costly. 54 struct UnwindIndex { 55 uint32_t function_offset; // The offset of the first function covered by 56 // this index 57 uint32_t second_level; // The offset (inside unwind_info sect) to the second 58 // level page for this index 59 // (either UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED) 60 uint32_t lsda_array_start; // The offset (inside unwind_info sect) LSDA 61 // array for this index 62 uint32_t lsda_array_end; // The offset to the LSDA array for the NEXT index 63 bool sentinal_entry; // There is an empty index at the end which provides 64 // the upper bound of 65 // function addresses that are described 66 UnwindIndexUnwindIndex67 UnwindIndex() 68 : function_offset(0), second_level(0), lsda_array_start(0), 69 lsda_array_end(0), sentinal_entry(false) {} 70 71 bool operator<(const CompactUnwindInfo::UnwindIndex &rhs) const { 72 return function_offset < rhs.function_offset; 73 } 74 75 bool operator==(const CompactUnwindInfo::UnwindIndex &rhs) const { 76 return function_offset == rhs.function_offset; 77 } 78 }; 79 80 // An internal object used to store the information we retrieve about a 81 // function -- the encoding bits and possibly the LSDA/personality function. 82 struct FunctionInfo { 83 uint32_t encoding; // compact encoding 32-bit value for this function 84 Address lsda_address; // the address of the LSDA data for this function 85 Address personality_ptr_address; // the address where the personality 86 // routine addr can be found 87 88 uint32_t valid_range_offset_start; // first offset that this encoding is 89 // valid for (start of the function) 90 uint32_t 91 valid_range_offset_end; // the offset of the start of the next function FunctionInfoFunctionInfo92 FunctionInfo() 93 : encoding(0), lsda_address(), personality_ptr_address(), 94 valid_range_offset_start(0), valid_range_offset_end(0) {} 95 }; 96 97 struct UnwindHeader { 98 uint32_t version; 99 uint32_t common_encodings_array_offset; 100 uint32_t common_encodings_array_count; 101 uint32_t personality_array_offset; 102 uint32_t personality_array_count; 103 UnwindHeaderUnwindHeader104 UnwindHeader() 105 : common_encodings_array_offset(0), common_encodings_array_count(0), 106 personality_array_offset(0), personality_array_count(0) {} 107 }; 108 109 void ScanIndex(const lldb::ProcessSP &process_sp); 110 111 bool GetCompactUnwindInfoForFunction(Target &target, Address address, 112 FunctionInfo &unwind_info); 113 114 lldb::offset_t 115 BinarySearchRegularSecondPage(uint32_t entry_page_offset, 116 uint32_t entry_count, uint32_t function_offset, 117 uint32_t *entry_func_start_offset, 118 uint32_t *entry_func_end_offset); 119 120 uint32_t BinarySearchCompressedSecondPage(uint32_t entry_page_offset, 121 uint32_t entry_count, 122 uint32_t function_offset_to_find, 123 uint32_t function_offset_base, 124 uint32_t *entry_func_start_offset, 125 uint32_t *entry_func_end_offset); 126 127 uint32_t GetLSDAForFunctionOffset(uint32_t lsda_offset, uint32_t lsda_count, 128 uint32_t function_offset); 129 130 bool CreateUnwindPlan_x86_64(Target &target, FunctionInfo &function_info, 131 UnwindPlan &unwind_plan, 132 Address pc_or_function_start); 133 134 bool CreateUnwindPlan_i386(Target &target, FunctionInfo &function_info, 135 UnwindPlan &unwind_plan, 136 Address pc_or_function_start); 137 138 bool CreateUnwindPlan_arm64(Target &target, FunctionInfo &function_info, 139 UnwindPlan &unwind_plan, 140 Address pc_or_function_start); 141 142 bool CreateUnwindPlan_armv7(Target &target, FunctionInfo &function_info, 143 UnwindPlan &unwind_plan, 144 Address pc_or_function_start); 145 146 ObjectFile &m_objfile; 147 lldb::SectionSP m_section_sp; 148 lldb::DataBufferSP m_section_contents_if_encrypted; // if the binary is 149 // encrypted, read the 150 // sect contents 151 // out of live memory and cache them here 152 std::mutex m_mutex; 153 std::vector<UnwindIndex> m_indexes; 154 155 LazyBool m_indexes_computed; // eLazyBoolYes once we've tried to parse the 156 // unwind info 157 // eLazyBoolNo means we cannot parse the unwind info & should not retry 158 // eLazyBoolCalculate means we haven't tried to parse it yet 159 160 DataExtractor m_unwindinfo_data; 161 bool m_unwindinfo_data_computed; // true once we've mapped in the unwindinfo 162 // data 163 164 UnwindHeader m_unwind_header; 165 }; 166 167 } // namespace lldb_private 168 169 #endif // liblldb_CompactUnwindInfo_h_ 170