CompactUnwindInfo.h revision 314564
1263712Sdes//===-- CompactUnwindInfo.h -------------------------------------*- C++ -*-===//
2224638Sbrooks//
360573Skris//                     The LLVM Compiler Infrastructure
492555Sdes//
560573Skris// This file is distributed under the University of Illinois Open Source
660573Skris// License. See LICENSE.TXT for details.
760573Skris//
860573Skris//===----------------------------------------------------------------------===//
960573Skris
1060573Skris#ifndef liblldb_CompactUnwindInfo_h_
1160573Skris#define liblldb_CompactUnwindInfo_h_
1260573Skris
1360573Skris#include <mutex>
1460573Skris#include <vector>
1560573Skris
1660573Skris#include "lldb/Core/DataExtractor.h"
1760573Skris#include "lldb/Core/RangeMap.h"
1860573Skris#include "lldb/Symbol/ObjectFile.h"
1960573Skris#include "lldb/Symbol/UnwindPlan.h"
2060573Skris#include "lldb/lldb-private.h"
2160573Skris
2260573Skrisnamespace lldb_private {
2360573Skris
2460573Skris// Compact Unwind info is an unwind format used on Darwin.  The unwind
2560573Skris// instructions
2660573Skris// for typical compiler-generated functions can be expressed in a 32-bit
2760573Skris// encoding.
28263691Sdes// The format includes a two-level index so the unwind information for a
2960573Skris// function
30162852Sdes// can be found by two binary searches in the section.  It can represent both
31162852Sdes// stack frames that use a frame-pointer register and frameless functions, on
32162852Sdes// i386/x86_64 for instance.  When a function is too complex to be represented
33162852Sdes// in
34162852Sdes// the compact unwind format, it calls out to eh_frame unwind instructions.
35162852Sdes
36162852Sdes// On Mac OS X / iOS, a function will have either a compact unwind
37162852Sdes// representation
3876259Sgreen// or an eh_frame representation.  If lldb is going to benefit  from the
3976259Sgreen// compiler's
40162852Sdes// description about saved register locations, it must be able to read both
4160573Skris// sources of information.
4260573Skris
4361209Skrisclass CompactUnwindInfo {
4460573Skrispublic:
4576259Sgreen  CompactUnwindInfo(ObjectFile &objfile, lldb::SectionSP &section);
46162852Sdes
4760573Skris  ~CompactUnwindInfo();
4876259Sgreen
4976259Sgreen  bool GetUnwindPlan(Target &target, Address addr, UnwindPlan &unwind_plan);
5076259Sgreen
5176259Sgreen  bool IsValid(const lldb::ProcessSP &process_sp);
5298675Sdes
53204917Sdesprivate:
54261320Sdes  // The top level index entries of the compact unwind info
5560573Skris  //   (internal representation of struct
56162852Sdes  //   unwind_info_section_header_index_entry)
57162852Sdes  // There are relatively few of these (one per 500/1000 functions, depending on
58162852Sdes  // format) so
59162852Sdes  // creating them on first scan will not be too costly.
60162852Sdes  struct UnwindIndex {
61162852Sdes    uint32_t function_offset; // The offset of the first function covered by
62162852Sdes                              // this index
63162852Sdes    uint32_t second_level; // The offset (inside unwind_info sect) to the second
6492555Sdes                           // level page for this index
6592555Sdes    // (either UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED)
6692555Sdes    uint32_t lsda_array_start; // The offset (inside unwind_info sect) LSDA
6776259Sgreen                               // array for this index
68255767Sdes    uint32_t lsda_array_end; // The offset to the LSDA array for the NEXT index
69255767Sdes    bool sentinal_entry; // There is an empty index at the end which provides
70255767Sdes                         // the upper bound of
71255767Sdes    // function addresses that are described
72261320Sdes
73255767Sdes    UnwindIndex()
74255767Sdes        : function_offset(0), second_level(0), lsda_array_start(0),
75261320Sdes          lsda_array_end(0), sentinal_entry(false) {}
76261320Sdes
77261320Sdes    bool operator<(const CompactUnwindInfo::UnwindIndex &rhs) const {
78255767Sdes      return function_offset < rhs.function_offset;
79261320Sdes    }
80255767Sdes
81255767Sdes    bool operator==(const CompactUnwindInfo::UnwindIndex &rhs) const {
82261320Sdes      return function_offset == rhs.function_offset;
83261320Sdes    }
84261320Sdes  };
85261320Sdes
86261320Sdes  // An internal object used to store the information we retrieve about a
87261320Sdes  // function --
88261320Sdes  // the encoding bits and possibly the LSDA/personality function.
89261320Sdes  struct FunctionInfo {
90255767Sdes    uint32_t encoding;    // compact encoding 32-bit value for this function
91261320Sdes    Address lsda_address; // the address of the LSDA data for this function
92261320Sdes    Address personality_ptr_address; // the address where the personality
93261320Sdes                                     // routine addr can be found
94261320Sdes
95261320Sdes    uint32_t valid_range_offset_start; // first offset that this encoding is
96255767Sdes                                       // valid for (start of the function)
97255767Sdes    uint32_t
98255767Sdes        valid_range_offset_end; // the offset of the start of the next function
99261320Sdes    FunctionInfo()
100255767Sdes        : encoding(0), lsda_address(), personality_ptr_address(),
101255767Sdes          valid_range_offset_start(0), valid_range_offset_end(0) {}
102255767Sdes  };
103255767Sdes
104255767Sdes  struct UnwindHeader {
105255767Sdes    uint32_t version;
106255767Sdes    uint32_t common_encodings_array_offset;
107261320Sdes    uint32_t common_encodings_array_count;
108255767Sdes    uint32_t personality_array_offset;
109255767Sdes    uint32_t personality_array_count;
110255767Sdes
111255767Sdes    UnwindHeader()
112255767Sdes        : common_encodings_array_offset(0), common_encodings_array_count(0),
113255767Sdes          personality_array_offset(0), personality_array_count(0) {}
114255767Sdes  };
115255767Sdes
116255767Sdes  void ScanIndex(const lldb::ProcessSP &process_sp);
117255767Sdes
118255767Sdes  bool GetCompactUnwindInfoForFunction(Target &target, Address address,
119255767Sdes                                       FunctionInfo &unwind_info);
120255767Sdes
121255767Sdes  lldb::offset_t
122255767Sdes  BinarySearchRegularSecondPage(uint32_t entry_page_offset,
123255767Sdes                                uint32_t entry_count, uint32_t function_offset,
124255767Sdes                                uint32_t *entry_func_start_offset,
125255767Sdes                                uint32_t *entry_func_end_offset);
126255767Sdes
127255767Sdes  uint32_t BinarySearchCompressedSecondPage(uint32_t entry_page_offset,
128221420Sdes                                            uint32_t entry_count,
129221420Sdes                                            uint32_t function_offset_to_find,
130221420Sdes                                            uint32_t function_offset_base,
131221420Sdes                                            uint32_t *entry_func_start_offset,
132221420Sdes                                            uint32_t *entry_func_end_offset);
133221420Sdes
134221420Sdes  uint32_t GetLSDAForFunctionOffset(uint32_t lsda_offset, uint32_t lsda_count,
135221420Sdes                                    uint32_t function_offset);
136221420Sdes
137221420Sdes  bool CreateUnwindPlan_x86_64(Target &target, FunctionInfo &function_info,
138221420Sdes                               UnwindPlan &unwind_plan,
139255767Sdes                               Address pc_or_function_start);
140221420Sdes
141255767Sdes  bool CreateUnwindPlan_i386(Target &target, FunctionInfo &function_info,
142221420Sdes                             UnwindPlan &unwind_plan,
143221420Sdes                             Address pc_or_function_start);
144221420Sdes
145221420Sdes  bool CreateUnwindPlan_arm64(Target &target, FunctionInfo &function_info,
146255767Sdes                              UnwindPlan &unwind_plan,
147221420Sdes                              Address pc_or_function_start);
148221420Sdes
149221420Sdes  bool CreateUnwindPlan_armv7(Target &target, FunctionInfo &function_info,
150240075Sdes                              UnwindPlan &unwind_plan,
151224638Sbrooks                              Address pc_or_function_start);
15292555Sdes
153224638Sbrooks  ObjectFile &m_objfile;
154224638Sbrooks  lldb::SectionSP m_section_sp;
155224638Sbrooks  lldb::DataBufferSP m_section_contents_if_encrypted; // if the binary is
156224638Sbrooks                                                      // encrypted, read the
15776259Sgreen                                                      // sect contents
15860573Skris  // out of live memory and cache them here
159149749Sdes  std::mutex m_mutex;
16076259Sgreen  std::vector<UnwindIndex> m_indexes;
16176259Sgreen
16298675Sdes  LazyBool m_indexes_computed; // eLazyBoolYes once we've tried to parse the
16398675Sdes                               // unwind info
16498675Sdes  // eLazyBoolNo means we cannot parse the unwind info & should not retry
16598675Sdes  // eLazyBoolCalculate means we haven't tried to parse it yet
16698675Sdes
16798675Sdes  DataExtractor m_unwindinfo_data;
16860573Skris  bool m_unwindinfo_data_computed; // true once we've mapped in the unwindinfo
16976259Sgreen                                   // data
17076259Sgreen
17176259Sgreen  UnwindHeader m_unwind_header;
17260573Skris};
17360573Skris
17476259Sgreen} // namespace lldb_private
17592555Sdes
176113908Sdes#endif // liblldb_CompactUnwindInfo_h_
17761209Skris