1 //===-- CompactUnwindInfo.h -------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef liblldb_CompactUnwindInfo_h_
10 #define liblldb_CompactUnwindInfo_h_
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"
20 namespace lldb_private {
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.
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.
36 class CompactUnwindInfo {
38 CompactUnwindInfo(ObjectFile &objfile, lldb::SectionSP §ion);
42 bool GetUnwindPlan(Target &target, Address addr, UnwindPlan &unwind_plan);
44 bool IsValid(const lldb::ProcessSP &process_sp);
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.
53 uint32_t function_offset; // The offset of the first function covered by
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
63 // function addresses that are described
66 : function_offset(0), second_level(0), lsda_array_start(0),
67 lsda_array_end(0), sentinal_entry(false) {}
69 bool operator<(const CompactUnwindInfo::UnwindIndex &rhs) const {
70 return function_offset < rhs.function_offset;
73 bool operator==(const CompactUnwindInfo::UnwindIndex &rhs) const {
74 return function_offset == rhs.function_offset;
78 // An internal object used to store the information we retrieve about a
79 // function -- the encoding bits and possibly the LSDA/personality function.
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
86 uint32_t valid_range_offset_start; // first offset that this encoding is
87 // valid for (start of the function)
89 valid_range_offset_end; // the offset of the start of the next function
91 : encoding(0), lsda_address(), personality_ptr_address(),
92 valid_range_offset_start(0), valid_range_offset_end(0) {}
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;
103 : common_encodings_array_offset(0), common_encodings_array_count(0),
104 personality_array_offset(0), personality_array_count(0) {}
107 void ScanIndex(const lldb::ProcessSP &process_sp);
109 bool GetCompactUnwindInfoForFunction(Target &target, Address address,
110 FunctionInfo &unwind_info);
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);
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);
125 uint32_t GetLSDAForFunctionOffset(uint32_t lsda_offset, uint32_t lsda_count,
126 uint32_t function_offset);
128 bool CreateUnwindPlan_x86_64(Target &target, FunctionInfo &function_info,
129 UnwindPlan &unwind_plan,
130 Address pc_or_function_start);
132 bool CreateUnwindPlan_i386(Target &target, FunctionInfo &function_info,
133 UnwindPlan &unwind_plan,
134 Address pc_or_function_start);
136 bool CreateUnwindPlan_arm64(Target &target, FunctionInfo &function_info,
137 UnwindPlan &unwind_plan,
138 Address pc_or_function_start);
140 bool CreateUnwindPlan_armv7(Target &target, FunctionInfo &function_info,
141 UnwindPlan &unwind_plan,
142 Address pc_or_function_start);
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
149 // out of live memory and cache them here
151 std::vector<UnwindIndex> m_indexes;
153 LazyBool m_indexes_computed; // eLazyBoolYes once we've tried to parse the
155 // eLazyBoolNo means we cannot parse the unwind info & should not retry
156 // eLazyBoolCalculate means we haven't tried to parse it yet
158 DataExtractor m_unwindinfo_data;
159 bool m_unwindinfo_data_computed; // true once we've mapped in the unwindinfo
162 UnwindHeader m_unwind_header;
165 } // namespace lldb_private
167 #endif // liblldb_CompactUnwindInfo_h_