]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/include/lldb/Symbol/CompactUnwindInfo.h
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / include / lldb / Symbol / CompactUnwindInfo.h
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
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 &section);
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; // 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_