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