Coverage Report

Created: 2023-09-12 09:32

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