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 &section);
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