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 liblldb_CompactUnwindInfo_h_ 10#define liblldb_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 20namespace 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 36class CompactUnwindInfo { 37public: 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 46private: 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; // The offset of the first function covered by 54 // this index 55 uint32_t second_level; // The offset (inside unwind_info sect) to the second 56 // level page for this index 57 // (either UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED) 58 uint32_t lsda_array_start; // The offset (inside unwind_info sect) LSDA 59 // array for this index 60 uint32_t lsda_array_end; // The offset to the LSDA array for the NEXT index 61 bool sentinal_entry; // There is an empty index at the end which provides 62 // the upper bound of 63 // function addresses that are described 64 65 UnwindIndex() 66 : function_offset(0), second_level(0), lsda_array_start(0), 67 lsda_array_end(0), sentinal_entry(false) {} 68 69 bool operator<(const CompactUnwindInfo::UnwindIndex &rhs) const { 70 return function_offset < rhs.function_offset; 71 } 72 73 bool operator==(const CompactUnwindInfo::UnwindIndex &rhs) const { 74 return function_offset == rhs.function_offset; 75 } 76 }; 77 78 // An internal object used to store the information we retrieve about a 79 // function -- the encoding bits and possibly the LSDA/personality function. 80 struct FunctionInfo { 81 uint32_t encoding; // compact encoding 32-bit value for this function 82 Address lsda_address; // the address of the LSDA data for this function 83 Address personality_ptr_address; // the address where the personality 84 // routine addr can be found 85 86 uint32_t valid_range_offset_start; // first offset that this encoding is 87 // valid for (start of the function) 88 uint32_t 89 valid_range_offset_end; // the offset of the start of the next function 90 FunctionInfo() 91 : encoding(0), lsda_address(), personality_ptr_address(), 92 valid_range_offset_start(0), valid_range_offset_end(0) {} 93 }; 94 95 struct UnwindHeader { 96 uint32_t version; 97 uint32_t common_encodings_array_offset; 98 uint32_t common_encodings_array_count; 99 uint32_t personality_array_offset; 100 uint32_t personality_array_count; 101 102 UnwindHeader() 103 : common_encodings_array_offset(0), common_encodings_array_count(0), 104 personality_array_offset(0), personality_array_count(0) {} 105 }; 106 107 void ScanIndex(const lldb::ProcessSP &process_sp); 108 109 bool GetCompactUnwindInfoForFunction(Target &target, Address address, 110 FunctionInfo &unwind_info); 111 112 lldb::offset_t 113 BinarySearchRegularSecondPage(uint32_t entry_page_offset, 114 uint32_t entry_count, uint32_t function_offset, 115 uint32_t *entry_func_start_offset, 116 uint32_t *entry_func_end_offset); 117 118 uint32_t BinarySearchCompressedSecondPage(uint32_t entry_page_offset, 119 uint32_t entry_count, 120 uint32_t function_offset_to_find, 121 uint32_t function_offset_base, 122 uint32_t *entry_func_start_offset, 123 uint32_t *entry_func_end_offset); 124 125 uint32_t GetLSDAForFunctionOffset(uint32_t lsda_offset, uint32_t lsda_count, 126 uint32_t function_offset); 127 128 bool CreateUnwindPlan_x86_64(Target &target, FunctionInfo &function_info, 129 UnwindPlan &unwind_plan, 130 Address pc_or_function_start); 131 132 bool CreateUnwindPlan_i386(Target &target, FunctionInfo &function_info, 133 UnwindPlan &unwind_plan, 134 Address pc_or_function_start); 135 136 bool CreateUnwindPlan_arm64(Target &target, FunctionInfo &function_info, 137 UnwindPlan &unwind_plan, 138 Address pc_or_function_start); 139 140 bool CreateUnwindPlan_armv7(Target &target, FunctionInfo &function_info, 141 UnwindPlan &unwind_plan, 142 Address pc_or_function_start); 143 144 ObjectFile &m_objfile; 145 lldb::SectionSP m_section_sp; 146 lldb::DataBufferSP m_section_contents_if_encrypted; // if the binary is 147 // encrypted, read the 148 // sect contents 149 // out of live memory and cache them here 150 std::mutex m_mutex; 151 std::vector<UnwindIndex> m_indexes; 152 153 LazyBool m_indexes_computed; // eLazyBoolYes once we've tried to parse the 154 // unwind info 155 // eLazyBoolNo means we cannot parse the unwind info & should not retry 156 // eLazyBoolCalculate means we haven't tried to parse it yet 157 158 DataExtractor m_unwindinfo_data; 159 bool m_unwindinfo_data_computed; // true once we've mapped in the unwindinfo 160 // data 161 162 UnwindHeader m_unwind_header; 163}; 164 165} // namespace lldb_private 166 167#endif // liblldb_CompactUnwindInfo_h_ 168