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