/src/perfetto/buildtools/android-unwinding/libunwindstack/DwarfSection.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2017 The Android Open Source Project |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #include <stdint.h> |
18 | | |
19 | | #include <algorithm> |
20 | | #include <optional> |
21 | | #include <tuple> |
22 | | #include <utility> |
23 | | #include <vector> |
24 | | |
25 | | #include <unwindstack/DwarfError.h> |
26 | | #include <unwindstack/DwarfLocation.h> |
27 | | #include <unwindstack/DwarfMemory.h> |
28 | | #include <unwindstack/DwarfSection.h> |
29 | | #include <unwindstack/DwarfStructs.h> |
30 | | #include <unwindstack/Elf.h> |
31 | | #include <unwindstack/Log.h> |
32 | | #include <unwindstack/Memory.h> |
33 | | #include <unwindstack/Regs.h> |
34 | | |
35 | | #include "DwarfCfa.h" |
36 | | #include "DwarfDebugFrame.h" |
37 | | #include "DwarfEhFrame.h" |
38 | | #include "DwarfEncoding.h" |
39 | | #include "DwarfOp.h" |
40 | | #include "RegsInfo.h" |
41 | | |
42 | | namespace unwindstack { |
43 | | |
44 | 2.06k | DwarfSection::DwarfSection(std::shared_ptr<Memory>& memory) : memory_(memory) {} |
45 | | |
46 | | bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, |
47 | 2.27k | bool* is_signal_frame) { |
48 | | // Lookup the pc in the cache. |
49 | 2.27k | auto it = loc_regs_.upper_bound(pc); |
50 | 2.27k | if (it == loc_regs_.end() || pc < it->second.pc_start) { |
51 | 1.48k | last_error_.code = DWARF_ERROR_NONE; |
52 | 1.48k | const DwarfFde* fde = GetFdeFromPc(pc); |
53 | 1.48k | if (fde == nullptr || fde->cie == nullptr) { |
54 | 729 | last_error_.code = DWARF_ERROR_ILLEGAL_STATE; |
55 | 729 | return false; |
56 | 729 | } |
57 | | |
58 | | // Now get the location information for this pc. |
59 | 758 | DwarfLocations loc_regs; |
60 | 758 | if (!GetCfaLocationInfo(pc, fde, &loc_regs, regs->Arch())) { |
61 | 361 | return false; |
62 | 361 | } |
63 | 397 | loc_regs.cie = fde->cie; |
64 | | |
65 | | // Store it in the cache. |
66 | 397 | it = loc_regs_.emplace(loc_regs.pc_end, std::move(loc_regs)).first; |
67 | 397 | } |
68 | | |
69 | 1.18k | *is_signal_frame = it->second.cie->is_signal_frame; |
70 | | |
71 | | // Now eval the actual registers. |
72 | 1.18k | return Eval(it->second.cie, process_memory, it->second, regs, finished); |
73 | 2.27k | } |
74 | | |
75 | | template <typename AddressType> |
76 | 4.40k | const DwarfCie* DwarfSectionImpl<AddressType>::GetCieFromOffset(uint64_t offset) { |
77 | 4.40k | auto cie_entry = cie_entries_.find(offset); |
78 | 4.40k | if (cie_entry != cie_entries_.end()) { |
79 | 907 | return &cie_entry->second; |
80 | 907 | } |
81 | 3.49k | DwarfCie* cie = &cie_entries_[offset]; |
82 | 3.49k | memory_.set_data_offset(entries_offset_); |
83 | 3.49k | memory_.set_cur_offset(offset); |
84 | 3.49k | if (!FillInCieHeader(cie) || !FillInCie(cie)) { |
85 | | // Erase the cached entry. |
86 | 572 | cie_entries_.erase(offset); |
87 | 572 | return nullptr; |
88 | 572 | } |
89 | 2.92k | return cie; |
90 | 3.49k | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::GetCieFromOffset(unsigned long) unwindstack::DwarfSectionImpl<unsigned long>::GetCieFromOffset(unsigned long) Line | Count | Source | 76 | 4.40k | const DwarfCie* DwarfSectionImpl<AddressType>::GetCieFromOffset(uint64_t offset) { | 77 | 4.40k | auto cie_entry = cie_entries_.find(offset); | 78 | 4.40k | if (cie_entry != cie_entries_.end()) { | 79 | 907 | return &cie_entry->second; | 80 | 907 | } | 81 | 3.49k | DwarfCie* cie = &cie_entries_[offset]; | 82 | 3.49k | memory_.set_data_offset(entries_offset_); | 83 | 3.49k | memory_.set_cur_offset(offset); | 84 | 3.49k | if (!FillInCieHeader(cie) || !FillInCie(cie)) { | 85 | | // Erase the cached entry. | 86 | 572 | cie_entries_.erase(offset); | 87 | 572 | return nullptr; | 88 | 572 | } | 89 | 2.92k | return cie; | 90 | 3.49k | } |
|
91 | | |
92 | | template <typename AddressType> |
93 | 3.49k | bool DwarfSectionImpl<AddressType>::FillInCieHeader(DwarfCie* cie) { |
94 | 3.49k | cie->lsda_encoding = DW_EH_PE_omit; |
95 | 3.49k | uint32_t length32; |
96 | 3.49k | if (!memory_.ReadBytes(&length32, sizeof(length32))) { |
97 | 414 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
98 | 414 | last_error_.address = memory_.cur_offset(); |
99 | 414 | return false; |
100 | 414 | } |
101 | 3.08k | if (length32 == static_cast<uint32_t>(-1)) { |
102 | | // 64 bit Cie |
103 | 55 | uint64_t length64; |
104 | 55 | if (!memory_.ReadBytes(&length64, sizeof(length64))) { |
105 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
106 | 1 | last_error_.address = memory_.cur_offset(); |
107 | 1 | return false; |
108 | 1 | } |
109 | | |
110 | 54 | cie->cfa_instructions_end = memory_.cur_offset() + length64; |
111 | | // TODO(b/192012848): This is wrong. We need to propagate pointer size here. |
112 | 54 | cie->fde_address_encoding = DW_EH_PE_udata8; |
113 | | |
114 | 54 | uint64_t cie_id; |
115 | 54 | if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) { |
116 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
117 | 1 | last_error_.address = memory_.cur_offset(); |
118 | 1 | return false; |
119 | 1 | } |
120 | 53 | if (cie_id != cie64_value_) { |
121 | | // This is not a Cie, something has gone horribly wrong. |
122 | 49 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; |
123 | 49 | return false; |
124 | 49 | } |
125 | 3.02k | } else { |
126 | | // 32 bit Cie |
127 | 3.02k | cie->cfa_instructions_end = memory_.cur_offset() + length32; |
128 | | // TODO(b/192012848): This is wrong. We need to propagate pointer size here. |
129 | 3.02k | cie->fde_address_encoding = DW_EH_PE_udata4; |
130 | | |
131 | 3.02k | uint32_t cie_id; |
132 | 3.02k | if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) { |
133 | 6 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
134 | 6 | last_error_.address = memory_.cur_offset(); |
135 | 6 | return false; |
136 | 6 | } |
137 | 3.02k | if (cie_id != cie32_value_) { |
138 | | // This is not a Cie, something has gone horribly wrong. |
139 | 85 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; |
140 | 85 | return false; |
141 | 85 | } |
142 | 3.02k | } |
143 | 2.94k | return true; |
144 | 3.08k | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::FillInCieHeader(unwindstack::DwarfCie*) unwindstack::DwarfSectionImpl<unsigned long>::FillInCieHeader(unwindstack::DwarfCie*) Line | Count | Source | 93 | 3.49k | bool DwarfSectionImpl<AddressType>::FillInCieHeader(DwarfCie* cie) { | 94 | 3.49k | cie->lsda_encoding = DW_EH_PE_omit; | 95 | 3.49k | uint32_t length32; | 96 | 3.49k | if (!memory_.ReadBytes(&length32, sizeof(length32))) { | 97 | 414 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 98 | 414 | last_error_.address = memory_.cur_offset(); | 99 | 414 | return false; | 100 | 414 | } | 101 | 3.08k | if (length32 == static_cast<uint32_t>(-1)) { | 102 | | // 64 bit Cie | 103 | 55 | uint64_t length64; | 104 | 55 | if (!memory_.ReadBytes(&length64, sizeof(length64))) { | 105 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 106 | 1 | last_error_.address = memory_.cur_offset(); | 107 | 1 | return false; | 108 | 1 | } | 109 | | | 110 | 54 | cie->cfa_instructions_end = memory_.cur_offset() + length64; | 111 | | // TODO(b/192012848): This is wrong. We need to propagate pointer size here. | 112 | 54 | cie->fde_address_encoding = DW_EH_PE_udata8; | 113 | | | 114 | 54 | uint64_t cie_id; | 115 | 54 | if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) { | 116 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 117 | 1 | last_error_.address = memory_.cur_offset(); | 118 | 1 | return false; | 119 | 1 | } | 120 | 53 | if (cie_id != cie64_value_) { | 121 | | // This is not a Cie, something has gone horribly wrong. | 122 | 49 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; | 123 | 49 | return false; | 124 | 49 | } | 125 | 3.02k | } else { | 126 | | // 32 bit Cie | 127 | 3.02k | cie->cfa_instructions_end = memory_.cur_offset() + length32; | 128 | | // TODO(b/192012848): This is wrong. We need to propagate pointer size here. | 129 | 3.02k | cie->fde_address_encoding = DW_EH_PE_udata4; | 130 | | | 131 | 3.02k | uint32_t cie_id; | 132 | 3.02k | if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) { | 133 | 6 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 134 | 6 | last_error_.address = memory_.cur_offset(); | 135 | 6 | return false; | 136 | 6 | } | 137 | 3.02k | if (cie_id != cie32_value_) { | 138 | | // This is not a Cie, something has gone horribly wrong. | 139 | 85 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; | 140 | 85 | return false; | 141 | 85 | } | 142 | 3.02k | } | 143 | 2.94k | return true; | 144 | 3.08k | } |
|
145 | | |
146 | | template <typename AddressType> |
147 | 2.99k | bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) { |
148 | 2.99k | if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) { |
149 | 3 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
150 | 3 | last_error_.address = memory_.cur_offset(); |
151 | 3 | return false; |
152 | 3 | } |
153 | | |
154 | 2.99k | if (cie->version != 1 && cie->version != 3 && cie->version != 4 && cie->version != 5) { |
155 | | // Unrecognized version. |
156 | 43 | last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION; |
157 | 43 | return false; |
158 | 43 | } |
159 | | |
160 | | // Read the augmentation string. |
161 | 2.94k | char aug_value; |
162 | 7.10k | do { |
163 | 7.10k | if (!memory_.ReadBytes(&aug_value, 1)) { |
164 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
165 | 0 | last_error_.address = memory_.cur_offset(); |
166 | 0 | return false; |
167 | 0 | } |
168 | 7.10k | cie->augmentation_string.push_back(aug_value); |
169 | 7.10k | } while (aug_value != '\0'); |
170 | | |
171 | 2.94k | if (cie->version == 4 || cie->version == 5) { |
172 | 521 | char address_size; |
173 | 521 | if (!memory_.ReadBytes(&address_size, 1)) { |
174 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
175 | 0 | last_error_.address = memory_.cur_offset(); |
176 | 0 | return false; |
177 | 0 | } |
178 | 521 | cie->fde_address_encoding = address_size == 8 ? DW_EH_PE_udata8 : DW_EH_PE_udata4; |
179 | | |
180 | | // Segment Size |
181 | 521 | if (!memory_.ReadBytes(&cie->segment_size, 1)) { |
182 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
183 | 0 | last_error_.address = memory_.cur_offset(); |
184 | 0 | return false; |
185 | 0 | } |
186 | 521 | } |
187 | | |
188 | | // Code Alignment Factor |
189 | 2.94k | if (!memory_.ReadULEB128(&cie->code_alignment_factor)) { |
190 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
191 | 0 | last_error_.address = memory_.cur_offset(); |
192 | 0 | return false; |
193 | 0 | } |
194 | | |
195 | | // Data Alignment Factor |
196 | 2.94k | if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) { |
197 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
198 | 0 | last_error_.address = memory_.cur_offset(); |
199 | 0 | return false; |
200 | 0 | } |
201 | | |
202 | 2.94k | if (cie->version == 1) { |
203 | | // Return Address is a single byte. |
204 | 1.75k | uint8_t return_address_register; |
205 | 1.75k | if (!memory_.ReadBytes(&return_address_register, 1)) { |
206 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
207 | 1 | last_error_.address = memory_.cur_offset(); |
208 | 1 | return false; |
209 | 1 | } |
210 | 1.75k | cie->return_address_register = return_address_register; |
211 | 1.75k | } else if (!memory_.ReadULEB128(&cie->return_address_register)) { |
212 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
213 | 1 | last_error_.address = memory_.cur_offset(); |
214 | 1 | return false; |
215 | 1 | } |
216 | | |
217 | 2.94k | if (cie->augmentation_string[0] != 'z') { |
218 | 2.93k | cie->cfa_instructions_offset = memory_.cur_offset(); |
219 | 2.93k | return true; |
220 | 2.93k | } |
221 | | |
222 | 9 | uint64_t aug_length; |
223 | 9 | if (!memory_.ReadULEB128(&aug_length)) { |
224 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
225 | 0 | last_error_.address = memory_.cur_offset(); |
226 | 0 | return false; |
227 | 0 | } |
228 | 9 | cie->cfa_instructions_offset = memory_.cur_offset() + aug_length; |
229 | | |
230 | 102 | for (size_t i = 1; i < cie->augmentation_string.size(); i++) { |
231 | 94 | switch (cie->augmentation_string[i]) { |
232 | 4 | case 'L': |
233 | 4 | if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) { |
234 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
235 | 0 | last_error_.address = memory_.cur_offset(); |
236 | 0 | return false; |
237 | 0 | } |
238 | 4 | break; |
239 | 4 | case 'P': { |
240 | 1 | uint8_t encoding; |
241 | 1 | if (!memory_.ReadBytes(&encoding, 1)) { |
242 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
243 | 0 | last_error_.address = memory_.cur_offset(); |
244 | 0 | return false; |
245 | 0 | } |
246 | 1 | memory_.set_pc_offset(pc_offset_); |
247 | 1 | if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) { |
248 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
249 | 1 | last_error_.address = memory_.cur_offset(); |
250 | 1 | return false; |
251 | 1 | } |
252 | 1 | } break; |
253 | 0 | case 'R': |
254 | 0 | if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) { |
255 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
256 | 0 | last_error_.address = memory_.cur_offset(); |
257 | 0 | return false; |
258 | 0 | } |
259 | 0 | break; |
260 | 0 | case 'S': |
261 | 0 | cie->is_signal_frame = true; |
262 | 0 | break; |
263 | 94 | } |
264 | 94 | } |
265 | 8 | return true; |
266 | 9 | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::FillInCie(unwindstack::DwarfCie*) unwindstack::DwarfSectionImpl<unsigned long>::FillInCie(unwindstack::DwarfCie*) Line | Count | Source | 147 | 2.99k | bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) { | 148 | 2.99k | if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) { | 149 | 3 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 150 | 3 | last_error_.address = memory_.cur_offset(); | 151 | 3 | return false; | 152 | 3 | } | 153 | | | 154 | 2.99k | if (cie->version != 1 && cie->version != 3 && cie->version != 4 && cie->version != 5) { | 155 | | // Unrecognized version. | 156 | 43 | last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION; | 157 | 43 | return false; | 158 | 43 | } | 159 | | | 160 | | // Read the augmentation string. | 161 | 2.94k | char aug_value; | 162 | 7.10k | do { | 163 | 7.10k | if (!memory_.ReadBytes(&aug_value, 1)) { | 164 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 165 | 0 | last_error_.address = memory_.cur_offset(); | 166 | 0 | return false; | 167 | 0 | } | 168 | 7.10k | cie->augmentation_string.push_back(aug_value); | 169 | 7.10k | } while (aug_value != '\0'); | 170 | | | 171 | 2.94k | if (cie->version == 4 || cie->version == 5) { | 172 | 521 | char address_size; | 173 | 521 | if (!memory_.ReadBytes(&address_size, 1)) { | 174 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 175 | 0 | last_error_.address = memory_.cur_offset(); | 176 | 0 | return false; | 177 | 0 | } | 178 | 521 | cie->fde_address_encoding = address_size == 8 ? DW_EH_PE_udata8 : DW_EH_PE_udata4; | 179 | | | 180 | | // Segment Size | 181 | 521 | if (!memory_.ReadBytes(&cie->segment_size, 1)) { | 182 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 183 | 0 | last_error_.address = memory_.cur_offset(); | 184 | 0 | return false; | 185 | 0 | } | 186 | 521 | } | 187 | | | 188 | | // Code Alignment Factor | 189 | 2.94k | if (!memory_.ReadULEB128(&cie->code_alignment_factor)) { | 190 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 191 | 0 | last_error_.address = memory_.cur_offset(); | 192 | 0 | return false; | 193 | 0 | } | 194 | | | 195 | | // Data Alignment Factor | 196 | 2.94k | if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) { | 197 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 198 | 0 | last_error_.address = memory_.cur_offset(); | 199 | 0 | return false; | 200 | 0 | } | 201 | | | 202 | 2.94k | if (cie->version == 1) { | 203 | | // Return Address is a single byte. | 204 | 1.75k | uint8_t return_address_register; | 205 | 1.75k | if (!memory_.ReadBytes(&return_address_register, 1)) { | 206 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 207 | 1 | last_error_.address = memory_.cur_offset(); | 208 | 1 | return false; | 209 | 1 | } | 210 | 1.75k | cie->return_address_register = return_address_register; | 211 | 1.75k | } else if (!memory_.ReadULEB128(&cie->return_address_register)) { | 212 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 213 | 1 | last_error_.address = memory_.cur_offset(); | 214 | 1 | return false; | 215 | 1 | } | 216 | | | 217 | 2.94k | if (cie->augmentation_string[0] != 'z') { | 218 | 2.93k | cie->cfa_instructions_offset = memory_.cur_offset(); | 219 | 2.93k | return true; | 220 | 2.93k | } | 221 | | | 222 | 9 | uint64_t aug_length; | 223 | 9 | if (!memory_.ReadULEB128(&aug_length)) { | 224 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 225 | 0 | last_error_.address = memory_.cur_offset(); | 226 | 0 | return false; | 227 | 0 | } | 228 | 9 | cie->cfa_instructions_offset = memory_.cur_offset() + aug_length; | 229 | | | 230 | 102 | for (size_t i = 1; i < cie->augmentation_string.size(); i++) { | 231 | 94 | switch (cie->augmentation_string[i]) { | 232 | 4 | case 'L': | 233 | 4 | if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) { | 234 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 235 | 0 | last_error_.address = memory_.cur_offset(); | 236 | 0 | return false; | 237 | 0 | } | 238 | 4 | break; | 239 | 4 | case 'P': { | 240 | 1 | uint8_t encoding; | 241 | 1 | if (!memory_.ReadBytes(&encoding, 1)) { | 242 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 243 | 0 | last_error_.address = memory_.cur_offset(); | 244 | 0 | return false; | 245 | 0 | } | 246 | 1 | memory_.set_pc_offset(pc_offset_); | 247 | 1 | if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) { | 248 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 249 | 1 | last_error_.address = memory_.cur_offset(); | 250 | 1 | return false; | 251 | 1 | } | 252 | 1 | } break; | 253 | 0 | case 'R': | 254 | 0 | if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) { | 255 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 256 | 0 | last_error_.address = memory_.cur_offset(); | 257 | 0 | return false; | 258 | 0 | } | 259 | 0 | break; | 260 | 0 | case 'S': | 261 | 0 | cie->is_signal_frame = true; | 262 | 0 | break; | 263 | 94 | } | 264 | 94 | } | 265 | 8 | return true; | 266 | 9 | } |
|
267 | | |
268 | | template <typename AddressType> |
269 | 1.05k | const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) { |
270 | 1.05k | auto fde_entry = fde_entries_.find(offset); |
271 | 1.05k | if (fde_entry != fde_entries_.end()) { |
272 | 69 | return &fde_entry->second; |
273 | 69 | } |
274 | 987 | DwarfFde* fde = &fde_entries_[offset]; |
275 | 987 | memory_.set_data_offset(entries_offset_); |
276 | 987 | memory_.set_cur_offset(offset); |
277 | 987 | if (!FillInFdeHeader(fde) || !FillInFde(fde)) { |
278 | 169 | fde_entries_.erase(offset); |
279 | 169 | return nullptr; |
280 | 169 | } |
281 | 818 | return fde; |
282 | 987 | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::GetFdeFromOffset(unsigned long) unwindstack::DwarfSectionImpl<unsigned long>::GetFdeFromOffset(unsigned long) Line | Count | Source | 269 | 1.05k | const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) { | 270 | 1.05k | auto fde_entry = fde_entries_.find(offset); | 271 | 1.05k | if (fde_entry != fde_entries_.end()) { | 272 | 69 | return &fde_entry->second; | 273 | 69 | } | 274 | 987 | DwarfFde* fde = &fde_entries_[offset]; | 275 | 987 | memory_.set_data_offset(entries_offset_); | 276 | 987 | memory_.set_cur_offset(offset); | 277 | 987 | if (!FillInFdeHeader(fde) || !FillInFde(fde)) { | 278 | 169 | fde_entries_.erase(offset); | 279 | 169 | return nullptr; | 280 | 169 | } | 281 | 818 | return fde; | 282 | 987 | } |
|
283 | | |
284 | | template <typename AddressType> |
285 | 987 | bool DwarfSectionImpl<AddressType>::FillInFdeHeader(DwarfFde* fde) { |
286 | 987 | uint32_t length32; |
287 | 987 | if (!memory_.ReadBytes(&length32, sizeof(length32))) { |
288 | 19 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
289 | 19 | last_error_.address = memory_.cur_offset(); |
290 | 19 | return false; |
291 | 19 | } |
292 | | |
293 | 968 | if (length32 == static_cast<uint32_t>(-1)) { |
294 | | // 64 bit Fde. |
295 | 572 | uint64_t length64; |
296 | 572 | if (!memory_.ReadBytes(&length64, sizeof(length64))) { |
297 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
298 | 1 | last_error_.address = memory_.cur_offset(); |
299 | 1 | return false; |
300 | 1 | } |
301 | 571 | fde->cfa_instructions_end = memory_.cur_offset() + length64; |
302 | | |
303 | 571 | uint64_t value64; |
304 | 571 | if (!memory_.ReadBytes(&value64, sizeof(value64))) { |
305 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
306 | 0 | last_error_.address = memory_.cur_offset(); |
307 | 0 | return false; |
308 | 0 | } |
309 | 571 | if (value64 == cie64_value_) { |
310 | | // This is a Cie, this means something has gone wrong. |
311 | 3 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; |
312 | 3 | return false; |
313 | 3 | } |
314 | | |
315 | | // Get the Cie pointer, which is necessary to properly read the rest of |
316 | | // of the Fde information. |
317 | 568 | fde->cie_offset = GetCieOffsetFromFde64(value64); |
318 | 568 | } else { |
319 | | // 32 bit Fde. |
320 | 396 | fde->cfa_instructions_end = memory_.cur_offset() + length32; |
321 | | |
322 | 396 | uint32_t value32; |
323 | 396 | if (!memory_.ReadBytes(&value32, sizeof(value32))) { |
324 | 3 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
325 | 3 | last_error_.address = memory_.cur_offset(); |
326 | 3 | return false; |
327 | 3 | } |
328 | 393 | if (value32 == cie32_value_) { |
329 | | // This is a Cie, this means something has gone wrong. |
330 | 2 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; |
331 | 2 | return false; |
332 | 2 | } |
333 | | |
334 | | // Get the Cie pointer, which is necessary to properly read the rest of |
335 | | // of the Fde information. |
336 | 391 | fde->cie_offset = GetCieOffsetFromFde32(value32); |
337 | 391 | } |
338 | 959 | return true; |
339 | 968 | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::FillInFdeHeader(unwindstack::DwarfFde*) unwindstack::DwarfSectionImpl<unsigned long>::FillInFdeHeader(unwindstack::DwarfFde*) Line | Count | Source | 285 | 987 | bool DwarfSectionImpl<AddressType>::FillInFdeHeader(DwarfFde* fde) { | 286 | 987 | uint32_t length32; | 287 | 987 | if (!memory_.ReadBytes(&length32, sizeof(length32))) { | 288 | 19 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 289 | 19 | last_error_.address = memory_.cur_offset(); | 290 | 19 | return false; | 291 | 19 | } | 292 | | | 293 | 968 | if (length32 == static_cast<uint32_t>(-1)) { | 294 | | // 64 bit Fde. | 295 | 572 | uint64_t length64; | 296 | 572 | if (!memory_.ReadBytes(&length64, sizeof(length64))) { | 297 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 298 | 1 | last_error_.address = memory_.cur_offset(); | 299 | 1 | return false; | 300 | 1 | } | 301 | 571 | fde->cfa_instructions_end = memory_.cur_offset() + length64; | 302 | | | 303 | 571 | uint64_t value64; | 304 | 571 | if (!memory_.ReadBytes(&value64, sizeof(value64))) { | 305 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 306 | 0 | last_error_.address = memory_.cur_offset(); | 307 | 0 | return false; | 308 | 0 | } | 309 | 571 | if (value64 == cie64_value_) { | 310 | | // This is a Cie, this means something has gone wrong. | 311 | 3 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; | 312 | 3 | return false; | 313 | 3 | } | 314 | | | 315 | | // Get the Cie pointer, which is necessary to properly read the rest of | 316 | | // of the Fde information. | 317 | 568 | fde->cie_offset = GetCieOffsetFromFde64(value64); | 318 | 568 | } else { | 319 | | // 32 bit Fde. | 320 | 396 | fde->cfa_instructions_end = memory_.cur_offset() + length32; | 321 | | | 322 | 396 | uint32_t value32; | 323 | 396 | if (!memory_.ReadBytes(&value32, sizeof(value32))) { | 324 | 3 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 325 | 3 | last_error_.address = memory_.cur_offset(); | 326 | 3 | return false; | 327 | 3 | } | 328 | 393 | if (value32 == cie32_value_) { | 329 | | // This is a Cie, this means something has gone wrong. | 330 | 2 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; | 331 | 2 | return false; | 332 | 2 | } | 333 | | | 334 | | // Get the Cie pointer, which is necessary to properly read the rest of | 335 | | // of the Fde information. | 336 | 391 | fde->cie_offset = GetCieOffsetFromFde32(value32); | 337 | 391 | } | 338 | 959 | return true; | 339 | 968 | } |
|
340 | | |
341 | | template <typename AddressType> |
342 | 4.40k | bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) { |
343 | 4.40k | uint64_t cur_offset = memory_.cur_offset(); |
344 | | |
345 | 4.40k | const DwarfCie* cie = GetCieFromOffset(fde->cie_offset); |
346 | 4.40k | if (cie == nullptr) { |
347 | 572 | return false; |
348 | 572 | } |
349 | 3.83k | fde->cie = cie; |
350 | | |
351 | 3.83k | if (cie->segment_size != 0) { |
352 | | // Skip over the segment selector for now. |
353 | 62 | cur_offset += cie->segment_size; |
354 | 62 | } |
355 | 3.83k | memory_.set_cur_offset(cur_offset); |
356 | | |
357 | | // The load bias only applies to the start. |
358 | 3.83k | memory_.set_pc_offset(section_bias_); |
359 | 3.83k | bool valid = memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_start); |
360 | 3.83k | fde->pc_start = AdjustPcFromFde(fde->pc_start); |
361 | | |
362 | 3.83k | memory_.set_pc_offset(0); |
363 | 3.83k | if (!valid || !memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_end)) { |
364 | 6 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
365 | 6 | last_error_.address = memory_.cur_offset(); |
366 | 6 | return false; |
367 | 6 | } |
368 | 3.82k | fde->pc_end += fde->pc_start; |
369 | | |
370 | 3.82k | if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') { |
371 | | // Augmentation Size |
372 | 10 | uint64_t aug_length; |
373 | 10 | if (!memory_.ReadULEB128(&aug_length)) { |
374 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
375 | 0 | last_error_.address = memory_.cur_offset(); |
376 | 0 | return false; |
377 | 0 | } |
378 | 10 | uint64_t cur_offset = memory_.cur_offset(); |
379 | | |
380 | 10 | memory_.set_pc_offset(pc_offset_); |
381 | 10 | if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) { |
382 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
383 | 1 | last_error_.address = memory_.cur_offset(); |
384 | 1 | return false; |
385 | 1 | } |
386 | | |
387 | | // Set our position to after all of the augmentation data. |
388 | 9 | memory_.set_cur_offset(cur_offset + aug_length); |
389 | 9 | } |
390 | 3.82k | fde->cfa_instructions_offset = memory_.cur_offset(); |
391 | | |
392 | 3.82k | return true; |
393 | 3.82k | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::FillInFde(unwindstack::DwarfFde*) unwindstack::DwarfSectionImpl<unsigned long>::FillInFde(unwindstack::DwarfFde*) Line | Count | Source | 342 | 4.40k | bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) { | 343 | 4.40k | uint64_t cur_offset = memory_.cur_offset(); | 344 | | | 345 | 4.40k | const DwarfCie* cie = GetCieFromOffset(fde->cie_offset); | 346 | 4.40k | if (cie == nullptr) { | 347 | 572 | return false; | 348 | 572 | } | 349 | 3.83k | fde->cie = cie; | 350 | | | 351 | 3.83k | if (cie->segment_size != 0) { | 352 | | // Skip over the segment selector for now. | 353 | 62 | cur_offset += cie->segment_size; | 354 | 62 | } | 355 | 3.83k | memory_.set_cur_offset(cur_offset); | 356 | | | 357 | | // The load bias only applies to the start. | 358 | 3.83k | memory_.set_pc_offset(section_bias_); | 359 | 3.83k | bool valid = memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_start); | 360 | 3.83k | fde->pc_start = AdjustPcFromFde(fde->pc_start); | 361 | | | 362 | 3.83k | memory_.set_pc_offset(0); | 363 | 3.83k | if (!valid || !memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_end)) { | 364 | 6 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 365 | 6 | last_error_.address = memory_.cur_offset(); | 366 | 6 | return false; | 367 | 6 | } | 368 | 3.82k | fde->pc_end += fde->pc_start; | 369 | | | 370 | 3.82k | if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') { | 371 | | // Augmentation Size | 372 | 10 | uint64_t aug_length; | 373 | 10 | if (!memory_.ReadULEB128(&aug_length)) { | 374 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 375 | 0 | last_error_.address = memory_.cur_offset(); | 376 | 0 | return false; | 377 | 0 | } | 378 | 10 | uint64_t cur_offset = memory_.cur_offset(); | 379 | | | 380 | 10 | memory_.set_pc_offset(pc_offset_); | 381 | 10 | if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) { | 382 | 1 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 383 | 1 | last_error_.address = memory_.cur_offset(); | 384 | 1 | return false; | 385 | 1 | } | 386 | | | 387 | | // Set our position to after all of the augmentation data. | 388 | 9 | memory_.set_cur_offset(cur_offset + aug_length); | 389 | 9 | } | 390 | 3.82k | fde->cfa_instructions_offset = memory_.cur_offset(); | 391 | | | 392 | 3.82k | return true; | 393 | 3.82k | } |
|
394 | | |
395 | | template <typename AddressType> |
396 | | bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, Memory* regular_memory, |
397 | | AddressType* value, |
398 | | RegsInfo<AddressType>* regs_info, |
399 | 215 | bool* is_dex_pc) { |
400 | 215 | DwarfOp<AddressType> op(&memory_, regular_memory); |
401 | 215 | op.set_regs_info(regs_info); |
402 | | |
403 | | // Need to evaluate the op data. |
404 | 215 | uint64_t end = loc.values[1]; |
405 | 215 | uint64_t start = end - loc.values[0]; |
406 | 215 | if (!op.Eval(start, end)) { |
407 | 174 | last_error_ = op.last_error(); |
408 | 174 | return false; |
409 | 174 | } |
410 | 41 | if (op.StackSize() == 0) { |
411 | 4 | last_error_.code = DWARF_ERROR_ILLEGAL_STATE; |
412 | 4 | return false; |
413 | 4 | } |
414 | | // We don't support an expression that evaluates to a register number. |
415 | 37 | if (op.is_register()) { |
416 | 1 | last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED; |
417 | 1 | return false; |
418 | 1 | } |
419 | 36 | *value = op.StackAt(0); |
420 | 36 | if (is_dex_pc != nullptr && op.dex_pc_set()) { |
421 | 0 | *is_dex_pc = true; |
422 | 0 | } |
423 | 36 | return true; |
424 | 37 | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::EvalExpression(unwindstack::DwarfLocation const&, unwindstack::Memory*, unsigned int*, unwindstack::RegsInfo<unsigned int>*, bool*) unwindstack::DwarfSectionImpl<unsigned long>::EvalExpression(unwindstack::DwarfLocation const&, unwindstack::Memory*, unsigned long*, unwindstack::RegsInfo<unsigned long>*, bool*) Line | Count | Source | 399 | 215 | bool* is_dex_pc) { | 400 | 215 | DwarfOp<AddressType> op(&memory_, regular_memory); | 401 | 215 | op.set_regs_info(regs_info); | 402 | | | 403 | | // Need to evaluate the op data. | 404 | 215 | uint64_t end = loc.values[1]; | 405 | 215 | uint64_t start = end - loc.values[0]; | 406 | 215 | if (!op.Eval(start, end)) { | 407 | 174 | last_error_ = op.last_error(); | 408 | 174 | return false; | 409 | 174 | } | 410 | 41 | if (op.StackSize() == 0) { | 411 | 4 | last_error_.code = DWARF_ERROR_ILLEGAL_STATE; | 412 | 4 | return false; | 413 | 4 | } | 414 | | // We don't support an expression that evaluates to a register number. | 415 | 37 | if (op.is_register()) { | 416 | 1 | last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED; | 417 | 1 | return false; | 418 | 1 | } | 419 | 36 | *value = op.StackAt(0); | 420 | 36 | if (is_dex_pc != nullptr && op.dex_pc_set()) { | 421 | 0 | *is_dex_pc = true; | 422 | 0 | } | 423 | 36 | return true; | 424 | 37 | } |
|
425 | | |
426 | | template <typename AddressType> |
427 | | struct EvalInfo { |
428 | | const DwarfLocations* loc_regs; |
429 | | const DwarfCie* cie; |
430 | | Memory* regular_memory; |
431 | | AddressType cfa; |
432 | | bool return_address_undefined = false; |
433 | | RegsInfo<AddressType> regs_info; |
434 | | }; |
435 | | |
436 | | template <typename AddressType> |
437 | | bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg, |
438 | 223 | AddressType* reg_ptr, void* info) { |
439 | 223 | EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info); |
440 | 223 | Memory* regular_memory = eval_info->regular_memory; |
441 | 223 | switch (loc->type) { |
442 | 49 | case DWARF_LOCATION_OFFSET: |
443 | 49 | if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) { |
444 | 49 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
445 | 49 | last_error_.address = eval_info->cfa + loc->values[0]; |
446 | 49 | return false; |
447 | 49 | } |
448 | 0 | break; |
449 | 10 | case DWARF_LOCATION_VAL_OFFSET: |
450 | 10 | *reg_ptr = eval_info->cfa + loc->values[0]; |
451 | 10 | break; |
452 | 44 | case DWARF_LOCATION_REGISTER: { |
453 | 44 | uint16_t cur_reg = eval_info->regs_info.regs->Convert(loc->values[0]); |
454 | 44 | if (cur_reg >= eval_info->regs_info.Total()) { |
455 | 6 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; |
456 | 6 | return false; |
457 | 6 | } |
458 | 38 | *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1]; |
459 | 38 | break; |
460 | 44 | } |
461 | 55 | case DWARF_LOCATION_EXPRESSION: |
462 | 66 | case DWARF_LOCATION_VAL_EXPRESSION: { |
463 | 66 | AddressType value; |
464 | 66 | bool is_dex_pc = false; |
465 | 66 | if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) { |
466 | 59 | return false; |
467 | 59 | } |
468 | 7 | if (loc->type == DWARF_LOCATION_EXPRESSION) { |
469 | 5 | if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) { |
470 | 5 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
471 | 5 | last_error_.address = value; |
472 | 5 | return false; |
473 | 5 | } |
474 | 5 | } else { |
475 | 2 | *reg_ptr = value; |
476 | 2 | if (is_dex_pc) { |
477 | 0 | eval_info->regs_info.regs->set_dex_pc(value); |
478 | 0 | } |
479 | 2 | } |
480 | 2 | break; |
481 | 7 | } |
482 | 54 | case DWARF_LOCATION_UNDEFINED: |
483 | 54 | if (reg == eval_info->cie->return_address_register) { |
484 | 6 | eval_info->return_address_undefined = true; |
485 | 6 | } |
486 | 54 | break; |
487 | 0 | case DWARF_LOCATION_PSEUDO_REGISTER: |
488 | 0 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; |
489 | 0 | return false; |
490 | 0 | default: |
491 | 0 | break; |
492 | 223 | } |
493 | | |
494 | 104 | return true; |
495 | 223 | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::EvalRegister(unwindstack::DwarfLocation const*, unsigned int, unsigned int*, void*) unwindstack::DwarfSectionImpl<unsigned long>::EvalRegister(unwindstack::DwarfLocation const*, unsigned int, unsigned long*, void*) Line | Count | Source | 438 | 223 | AddressType* reg_ptr, void* info) { | 439 | 223 | EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info); | 440 | 223 | Memory* regular_memory = eval_info->regular_memory; | 441 | 223 | switch (loc->type) { | 442 | 49 | case DWARF_LOCATION_OFFSET: | 443 | 49 | if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) { | 444 | 49 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 445 | 49 | last_error_.address = eval_info->cfa + loc->values[0]; | 446 | 49 | return false; | 447 | 49 | } | 448 | 0 | break; | 449 | 10 | case DWARF_LOCATION_VAL_OFFSET: | 450 | 10 | *reg_ptr = eval_info->cfa + loc->values[0]; | 451 | 10 | break; | 452 | 44 | case DWARF_LOCATION_REGISTER: { | 453 | 44 | uint16_t cur_reg = eval_info->regs_info.regs->Convert(loc->values[0]); | 454 | 44 | if (cur_reg >= eval_info->regs_info.Total()) { | 455 | 6 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; | 456 | 6 | return false; | 457 | 6 | } | 458 | 38 | *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1]; | 459 | 38 | break; | 460 | 44 | } | 461 | 55 | case DWARF_LOCATION_EXPRESSION: | 462 | 66 | case DWARF_LOCATION_VAL_EXPRESSION: { | 463 | 66 | AddressType value; | 464 | 66 | bool is_dex_pc = false; | 465 | 66 | if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) { | 466 | 59 | return false; | 467 | 59 | } | 468 | 7 | if (loc->type == DWARF_LOCATION_EXPRESSION) { | 469 | 5 | if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) { | 470 | 5 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 471 | 5 | last_error_.address = value; | 472 | 5 | return false; | 473 | 5 | } | 474 | 5 | } else { | 475 | 2 | *reg_ptr = value; | 476 | 2 | if (is_dex_pc) { | 477 | 0 | eval_info->regs_info.regs->set_dex_pc(value); | 478 | 0 | } | 479 | 2 | } | 480 | 2 | break; | 481 | 7 | } | 482 | 54 | case DWARF_LOCATION_UNDEFINED: | 483 | 54 | if (reg == eval_info->cie->return_address_register) { | 484 | 6 | eval_info->return_address_undefined = true; | 485 | 6 | } | 486 | 54 | break; | 487 | 0 | case DWARF_LOCATION_PSEUDO_REGISTER: | 488 | 0 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; | 489 | 0 | return false; | 490 | 0 | default: | 491 | 0 | break; | 492 | 223 | } | 493 | | | 494 | 104 | return true; | 495 | 223 | } |
|
496 | | |
497 | | template <typename AddressType> |
498 | | bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory, |
499 | | const DwarfLocations& loc_regs, Regs* regs, |
500 | 1.18k | bool* finished) { |
501 | 1.18k | RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs); |
502 | 1.18k | if (cie->return_address_register >= cur_regs->total_regs()) { |
503 | 7 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; |
504 | 7 | return false; |
505 | 7 | } |
506 | | |
507 | | // Get the cfa value; |
508 | 1.17k | auto cfa_entry = loc_regs.find(CFA_REG); |
509 | 1.17k | if (cfa_entry == loc_regs.end()) { |
510 | 63 | last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED; |
511 | 63 | return false; |
512 | 63 | } |
513 | | |
514 | | // Always set the dex pc to zero when evaluating. |
515 | 1.11k | cur_regs->set_dex_pc(0); |
516 | | |
517 | | // Reset necessary pseudo registers before evaluation. |
518 | | // This is needed for ARM64, for example. |
519 | 1.11k | regs->ResetPseudoRegisters(); |
520 | | |
521 | 1.11k | EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs, |
522 | 1.11k | .cie = cie, |
523 | 1.11k | .regular_memory = regular_memory, |
524 | 1.11k | .regs_info = RegsInfo<AddressType>(cur_regs)}; |
525 | 1.11k | const DwarfLocation* loc = &cfa_entry->second; |
526 | | // Only a few location types are valid for the cfa. |
527 | 1.11k | switch (loc->type) { |
528 | 965 | case DWARF_LOCATION_REGISTER: |
529 | 965 | if (loc->values[0] >= cur_regs->total_regs()) { |
530 | 14 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; |
531 | 14 | return false; |
532 | 14 | } |
533 | 951 | eval_info.cfa = (*cur_regs)[loc->values[0]]; |
534 | 951 | eval_info.cfa += loc->values[1]; |
535 | 951 | break; |
536 | 149 | case DWARF_LOCATION_VAL_EXPRESSION: { |
537 | 149 | AddressType value; |
538 | 149 | if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) { |
539 | 120 | return false; |
540 | 120 | } |
541 | | // There is only one type of valid expression for CFA evaluation. |
542 | 29 | eval_info.cfa = value; |
543 | 29 | break; |
544 | 149 | } |
545 | 0 | default: |
546 | 0 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; |
547 | 0 | return false; |
548 | 1.11k | } |
549 | | |
550 | 3.56k | for (const auto& entry : loc_regs) { |
551 | 3.56k | uint32_t reg = entry.first; |
552 | | // Already handled the CFA register. |
553 | 3.56k | if (reg == CFA_REG) continue; |
554 | | |
555 | 2.68k | AddressType* reg_ptr; |
556 | 2.68k | if (reg >= cur_regs->total_regs()) { |
557 | 2.46k | if (entry.second.type != DWARF_LOCATION_PSEUDO_REGISTER) { |
558 | | // Skip this unknown register. |
559 | 1.93k | continue; |
560 | 1.93k | } |
561 | 532 | if (!eval_info.regs_info.regs->SetPseudoRegister(reg, entry.second.values[0])) { |
562 | 0 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; |
563 | 0 | return false; |
564 | 0 | } |
565 | 532 | } else { |
566 | 223 | reg_ptr = eval_info.regs_info.Save(reg); |
567 | 223 | if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) { |
568 | 119 | return false; |
569 | 119 | } |
570 | 223 | } |
571 | 2.68k | } |
572 | | |
573 | | // Find the return address location. |
574 | 861 | if (eval_info.return_address_undefined) { |
575 | 1 | cur_regs->set_pc(0); |
576 | 860 | } else { |
577 | 860 | cur_regs->set_pc((*cur_regs)[cie->return_address_register]); |
578 | 860 | } |
579 | | |
580 | | // If the pc was set to zero, consider this the final frame. Exception: if |
581 | | // this is the sigreturn frame, then we want to try to recover the real PC |
582 | | // using the return address (from LR or the stack), so keep going. |
583 | 861 | *finished = (cur_regs->pc() == 0 && !cie->is_signal_frame) ? true : false; |
584 | | |
585 | 861 | cur_regs->set_sp(eval_info.cfa); |
586 | | |
587 | 861 | return true; |
588 | 980 | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::Eval(unwindstack::DwarfCie const*, unwindstack::Memory*, unwindstack::DwarfLocations const&, unwindstack::Regs*, bool*) unwindstack::DwarfSectionImpl<unsigned long>::Eval(unwindstack::DwarfCie const*, unwindstack::Memory*, unwindstack::DwarfLocations const&, unwindstack::Regs*, bool*) Line | Count | Source | 500 | 1.18k | bool* finished) { | 501 | 1.18k | RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs); | 502 | 1.18k | if (cie->return_address_register >= cur_regs->total_regs()) { | 503 | 7 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; | 504 | 7 | return false; | 505 | 7 | } | 506 | | | 507 | | // Get the cfa value; | 508 | 1.17k | auto cfa_entry = loc_regs.find(CFA_REG); | 509 | 1.17k | if (cfa_entry == loc_regs.end()) { | 510 | 63 | last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED; | 511 | 63 | return false; | 512 | 63 | } | 513 | | | 514 | | // Always set the dex pc to zero when evaluating. | 515 | 1.11k | cur_regs->set_dex_pc(0); | 516 | | | 517 | | // Reset necessary pseudo registers before evaluation. | 518 | | // This is needed for ARM64, for example. | 519 | 1.11k | regs->ResetPseudoRegisters(); | 520 | | | 521 | 1.11k | EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs, | 522 | 1.11k | .cie = cie, | 523 | 1.11k | .regular_memory = regular_memory, | 524 | 1.11k | .regs_info = RegsInfo<AddressType>(cur_regs)}; | 525 | 1.11k | const DwarfLocation* loc = &cfa_entry->second; | 526 | | // Only a few location types are valid for the cfa. | 527 | 1.11k | switch (loc->type) { | 528 | 965 | case DWARF_LOCATION_REGISTER: | 529 | 965 | if (loc->values[0] >= cur_regs->total_regs()) { | 530 | 14 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; | 531 | 14 | return false; | 532 | 14 | } | 533 | 951 | eval_info.cfa = (*cur_regs)[loc->values[0]]; | 534 | 951 | eval_info.cfa += loc->values[1]; | 535 | 951 | break; | 536 | 149 | case DWARF_LOCATION_VAL_EXPRESSION: { | 537 | 149 | AddressType value; | 538 | 149 | if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) { | 539 | 120 | return false; | 540 | 120 | } | 541 | | // There is only one type of valid expression for CFA evaluation. | 542 | 29 | eval_info.cfa = value; | 543 | 29 | break; | 544 | 149 | } | 545 | 0 | default: | 546 | 0 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; | 547 | 0 | return false; | 548 | 1.11k | } | 549 | | | 550 | 3.56k | for (const auto& entry : loc_regs) { | 551 | 3.56k | uint32_t reg = entry.first; | 552 | | // Already handled the CFA register. | 553 | 3.56k | if (reg == CFA_REG) continue; | 554 | | | 555 | 2.68k | AddressType* reg_ptr; | 556 | 2.68k | if (reg >= cur_regs->total_regs()) { | 557 | 2.46k | if (entry.second.type != DWARF_LOCATION_PSEUDO_REGISTER) { | 558 | | // Skip this unknown register. | 559 | 1.93k | continue; | 560 | 1.93k | } | 561 | 532 | if (!eval_info.regs_info.regs->SetPseudoRegister(reg, entry.second.values[0])) { | 562 | 0 | last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; | 563 | 0 | return false; | 564 | 0 | } | 565 | 532 | } else { | 566 | 223 | reg_ptr = eval_info.regs_info.Save(reg); | 567 | 223 | if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) { | 568 | 119 | return false; | 569 | 119 | } | 570 | 223 | } | 571 | 2.68k | } | 572 | | | 573 | | // Find the return address location. | 574 | 861 | if (eval_info.return_address_undefined) { | 575 | 1 | cur_regs->set_pc(0); | 576 | 860 | } else { | 577 | 860 | cur_regs->set_pc((*cur_regs)[cie->return_address_register]); | 578 | 860 | } | 579 | | | 580 | | // If the pc was set to zero, consider this the final frame. Exception: if | 581 | | // this is the sigreturn frame, then we want to try to recover the real PC | 582 | | // using the return address (from LR or the stack), so keep going. | 583 | 861 | *finished = (cur_regs->pc() == 0 && !cie->is_signal_frame) ? true : false; | 584 | | | 585 | 861 | cur_regs->set_sp(eval_info.cfa); | 586 | | | 587 | 861 | return true; | 588 | 980 | } |
|
589 | | |
590 | | template <typename AddressType> |
591 | | bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, |
592 | 758 | DwarfLocations* loc_regs, ArchEnum arch) { |
593 | 758 | DwarfCfa<AddressType> cfa(&memory_, fde, arch); |
594 | | |
595 | | // Look for the cached copy of the cie data. |
596 | 758 | auto reg_entry = cie_loc_regs_.find(fde->cie_offset); |
597 | 758 | if (reg_entry == cie_loc_regs_.end()) { |
598 | 699 | if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end, |
599 | 699 | loc_regs)) { |
600 | 127 | last_error_ = cfa.last_error(); |
601 | 127 | return false; |
602 | 127 | } |
603 | 572 | cie_loc_regs_[fde->cie_offset] = *loc_regs; |
604 | 572 | } |
605 | 631 | cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]); |
606 | 631 | if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) { |
607 | 234 | last_error_ = cfa.last_error(); |
608 | 234 | return false; |
609 | 234 | } |
610 | 397 | return true; |
611 | 631 | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::GetCfaLocationInfo(unsigned long, unwindstack::DwarfFde const*, unwindstack::DwarfLocations*, unwindstack::ArchEnum) unwindstack::DwarfSectionImpl<unsigned long>::GetCfaLocationInfo(unsigned long, unwindstack::DwarfFde const*, unwindstack::DwarfLocations*, unwindstack::ArchEnum) Line | Count | Source | 592 | 758 | DwarfLocations* loc_regs, ArchEnum arch) { | 593 | 758 | DwarfCfa<AddressType> cfa(&memory_, fde, arch); | 594 | | | 595 | | // Look for the cached copy of the cie data. | 596 | 758 | auto reg_entry = cie_loc_regs_.find(fde->cie_offset); | 597 | 758 | if (reg_entry == cie_loc_regs_.end()) { | 598 | 699 | if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end, | 599 | 699 | loc_regs)) { | 600 | 127 | last_error_ = cfa.last_error(); | 601 | 127 | return false; | 602 | 127 | } | 603 | 572 | cie_loc_regs_[fde->cie_offset] = *loc_regs; | 604 | 572 | } | 605 | 631 | cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]); | 606 | 631 | if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) { | 607 | 234 | last_error_ = cfa.last_error(); | 608 | 234 | return false; | 609 | 234 | } | 610 | 397 | return true; | 611 | 631 | } |
|
612 | | |
613 | | template <typename AddressType> |
614 | | bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, |
615 | 0 | ArchEnum arch) { |
616 | 0 | DwarfCfa<AddressType> cfa(&memory_, fde, arch); |
617 | | |
618 | | // Always print the cie information. |
619 | 0 | const DwarfCie* cie = fde->cie; |
620 | 0 | if (!cfa.Log(indent, pc, cie->cfa_instructions_offset, cie->cfa_instructions_end)) { |
621 | 0 | last_error_ = cfa.last_error(); |
622 | 0 | return false; |
623 | 0 | } |
624 | 0 | if (!cfa.Log(indent, pc, fde->cfa_instructions_offset, fde->cfa_instructions_end)) { |
625 | 0 | last_error_ = cfa.last_error(); |
626 | 0 | return false; |
627 | 0 | } |
628 | 0 | return true; |
629 | 0 | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::Log(unsigned char, unsigned long, unwindstack::DwarfFde const*, unwindstack::ArchEnum) Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned long>::Log(unsigned char, unsigned long, unwindstack::DwarfFde const*, unwindstack::ArchEnum) |
630 | | |
631 | | template <typename AddressType> |
632 | 2.06k | bool DwarfSectionImpl<AddressType>::Init(const SectionInfo& info) { |
633 | 2.06k | if (info.flags & SHF_COMPRESSED) { |
634 | 378 | return false; |
635 | 378 | } |
636 | 1.69k | section_bias_ = info.bias; |
637 | 1.69k | entries_offset_ = info.offset; |
638 | 1.69k | entries_end_ = info.offset + info.size; |
639 | | |
640 | 1.69k | memory_.clear_func_offset(); |
641 | 1.69k | memory_.clear_text_offset(); |
642 | 1.69k | memory_.set_cur_offset(info.offset); |
643 | 1.69k | pc_offset_ = info.offset; |
644 | | |
645 | 1.69k | return true; |
646 | 2.06k | } unwindstack::DwarfSectionImpl<unsigned int>::Init(unwindstack::SectionInfo const&) Line | Count | Source | 632 | 261 | bool DwarfSectionImpl<AddressType>::Init(const SectionInfo& info) { | 633 | 261 | if (info.flags & SHF_COMPRESSED) { | 634 | 220 | return false; | 635 | 220 | } | 636 | 41 | section_bias_ = info.bias; | 637 | 41 | entries_offset_ = info.offset; | 638 | 41 | entries_end_ = info.offset + info.size; | 639 | | | 640 | 41 | memory_.clear_func_offset(); | 641 | 41 | memory_.clear_text_offset(); | 642 | 41 | memory_.set_cur_offset(info.offset); | 643 | 41 | pc_offset_ = info.offset; | 644 | | | 645 | 41 | return true; | 646 | 261 | } |
unwindstack::DwarfSectionImpl<unsigned long>::Init(unwindstack::SectionInfo const&) Line | Count | Source | 632 | 1.80k | bool DwarfSectionImpl<AddressType>::Init(const SectionInfo& info) { | 633 | 1.80k | if (info.flags & SHF_COMPRESSED) { | 634 | 158 | return false; | 635 | 158 | } | 636 | 1.65k | section_bias_ = info.bias; | 637 | 1.65k | entries_offset_ = info.offset; | 638 | 1.65k | entries_end_ = info.offset + info.size; | 639 | | | 640 | 1.65k | memory_.clear_func_offset(); | 641 | 1.65k | memory_.clear_text_offset(); | 642 | 1.65k | memory_.set_cur_offset(info.offset); | 643 | 1.65k | pc_offset_ = info.offset; | 644 | | | 645 | 1.65k | return true; | 646 | 1.80k | } |
|
647 | | |
648 | | // Read CIE or FDE entry at the given offset, and set the offset to the following entry. |
649 | | // The 'fde' argument is set only if we have seen an FDE entry. |
650 | | template <typename AddressType> |
651 | | bool DwarfSectionImpl<AddressType>::GetNextCieOrFde(uint64_t& next_entries_offset, |
652 | 3.62k | std::optional<DwarfFde>& fde_entry) { |
653 | 3.62k | const uint64_t start_offset = next_entries_offset; |
654 | | |
655 | 3.62k | memory_.set_data_offset(entries_offset_); |
656 | 3.62k | memory_.set_cur_offset(next_entries_offset); |
657 | 3.62k | uint32_t value32; |
658 | 3.62k | if (!memory_.ReadBytes(&value32, sizeof(value32))) { |
659 | 111 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
660 | 111 | last_error_.address = memory_.cur_offset(); |
661 | 111 | return false; |
662 | 111 | } |
663 | | |
664 | 3.51k | uint64_t cie_offset; |
665 | 3.51k | uint8_t cie_fde_encoding; |
666 | 3.51k | bool entry_is_cie = false; |
667 | 3.51k | if (value32 == static_cast<uint32_t>(-1)) { |
668 | | // 64 bit entry. |
669 | 106 | uint64_t value64; |
670 | 106 | if (!memory_.ReadBytes(&value64, sizeof(value64))) { |
671 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
672 | 0 | last_error_.address = memory_.cur_offset(); |
673 | 0 | return false; |
674 | 0 | } |
675 | | |
676 | 106 | next_entries_offset = memory_.cur_offset() + value64; |
677 | | // Read the Cie Id of a Cie or the pointer of the Fde. |
678 | 106 | if (!memory_.ReadBytes(&value64, sizeof(value64))) { |
679 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
680 | 0 | last_error_.address = memory_.cur_offset(); |
681 | 0 | return false; |
682 | 0 | } |
683 | | |
684 | 106 | if (value64 == cie64_value_) { |
685 | 4 | entry_is_cie = true; |
686 | 4 | cie_fde_encoding = DW_EH_PE_udata8; |
687 | 102 | } else { |
688 | 102 | cie_offset = GetCieOffsetFromFde64(value64); |
689 | 102 | } |
690 | 3.40k | } else { |
691 | 3.40k | next_entries_offset = memory_.cur_offset() + value32; |
692 | | |
693 | | // 32 bit Cie |
694 | 3.40k | if (!memory_.ReadBytes(&value32, sizeof(value32))) { |
695 | 11 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; |
696 | 11 | last_error_.address = memory_.cur_offset(); |
697 | 11 | return false; |
698 | 11 | } |
699 | | |
700 | 3.39k | if (value32 == cie32_value_) { |
701 | 50 | entry_is_cie = true; |
702 | 50 | cie_fde_encoding = DW_EH_PE_udata4; |
703 | 3.34k | } else { |
704 | 3.34k | cie_offset = GetCieOffsetFromFde32(value32); |
705 | 3.34k | } |
706 | 3.39k | } |
707 | | |
708 | 3.50k | if (entry_is_cie) { |
709 | 54 | auto entry = cie_entries_.find(start_offset); |
710 | 54 | if (entry == cie_entries_.end()) { |
711 | 53 | DwarfCie* cie = &cie_entries_[start_offset]; |
712 | 53 | cie->lsda_encoding = DW_EH_PE_omit; |
713 | 53 | cie->cfa_instructions_end = next_entries_offset; |
714 | 53 | cie->fde_address_encoding = cie_fde_encoding; |
715 | | |
716 | 53 | if (!FillInCie(cie)) { |
717 | 33 | cie_entries_.erase(start_offset); |
718 | 33 | return false; |
719 | 33 | } |
720 | 53 | } |
721 | 21 | fde_entry.reset(); |
722 | 3.44k | } else { |
723 | 3.44k | fde_entry = DwarfFde{}; |
724 | 3.44k | fde_entry->cfa_instructions_end = next_entries_offset; |
725 | 3.44k | fde_entry->cie_offset = cie_offset; |
726 | 3.44k | if (!FillInFde(&*fde_entry)) { |
727 | 438 | return false; |
728 | 438 | } |
729 | 3.44k | } |
730 | 3.02k | return true; |
731 | 3.50k | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::GetNextCieOrFde(unsigned long&, std::__1::optional<unwindstack::DwarfFde>&) unwindstack::DwarfSectionImpl<unsigned long>::GetNextCieOrFde(unsigned long&, std::__1::optional<unwindstack::DwarfFde>&) Line | Count | Source | 652 | 3.62k | std::optional<DwarfFde>& fde_entry) { | 653 | 3.62k | const uint64_t start_offset = next_entries_offset; | 654 | | | 655 | 3.62k | memory_.set_data_offset(entries_offset_); | 656 | 3.62k | memory_.set_cur_offset(next_entries_offset); | 657 | 3.62k | uint32_t value32; | 658 | 3.62k | if (!memory_.ReadBytes(&value32, sizeof(value32))) { | 659 | 111 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 660 | 111 | last_error_.address = memory_.cur_offset(); | 661 | 111 | return false; | 662 | 111 | } | 663 | | | 664 | 3.51k | uint64_t cie_offset; | 665 | 3.51k | uint8_t cie_fde_encoding; | 666 | 3.51k | bool entry_is_cie = false; | 667 | 3.51k | if (value32 == static_cast<uint32_t>(-1)) { | 668 | | // 64 bit entry. | 669 | 106 | uint64_t value64; | 670 | 106 | if (!memory_.ReadBytes(&value64, sizeof(value64))) { | 671 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 672 | 0 | last_error_.address = memory_.cur_offset(); | 673 | 0 | return false; | 674 | 0 | } | 675 | | | 676 | 106 | next_entries_offset = memory_.cur_offset() + value64; | 677 | | // Read the Cie Id of a Cie or the pointer of the Fde. | 678 | 106 | if (!memory_.ReadBytes(&value64, sizeof(value64))) { | 679 | 0 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 680 | 0 | last_error_.address = memory_.cur_offset(); | 681 | 0 | return false; | 682 | 0 | } | 683 | | | 684 | 106 | if (value64 == cie64_value_) { | 685 | 4 | entry_is_cie = true; | 686 | 4 | cie_fde_encoding = DW_EH_PE_udata8; | 687 | 102 | } else { | 688 | 102 | cie_offset = GetCieOffsetFromFde64(value64); | 689 | 102 | } | 690 | 3.40k | } else { | 691 | 3.40k | next_entries_offset = memory_.cur_offset() + value32; | 692 | | | 693 | | // 32 bit Cie | 694 | 3.40k | if (!memory_.ReadBytes(&value32, sizeof(value32))) { | 695 | 11 | last_error_.code = DWARF_ERROR_MEMORY_INVALID; | 696 | 11 | last_error_.address = memory_.cur_offset(); | 697 | 11 | return false; | 698 | 11 | } | 699 | | | 700 | 3.39k | if (value32 == cie32_value_) { | 701 | 50 | entry_is_cie = true; | 702 | 50 | cie_fde_encoding = DW_EH_PE_udata4; | 703 | 3.34k | } else { | 704 | 3.34k | cie_offset = GetCieOffsetFromFde32(value32); | 705 | 3.34k | } | 706 | 3.39k | } | 707 | | | 708 | 3.50k | if (entry_is_cie) { | 709 | 54 | auto entry = cie_entries_.find(start_offset); | 710 | 54 | if (entry == cie_entries_.end()) { | 711 | 53 | DwarfCie* cie = &cie_entries_[start_offset]; | 712 | 53 | cie->lsda_encoding = DW_EH_PE_omit; | 713 | 53 | cie->cfa_instructions_end = next_entries_offset; | 714 | 53 | cie->fde_address_encoding = cie_fde_encoding; | 715 | | | 716 | 53 | if (!FillInCie(cie)) { | 717 | 33 | cie_entries_.erase(start_offset); | 718 | 33 | return false; | 719 | 33 | } | 720 | 53 | } | 721 | 21 | fde_entry.reset(); | 722 | 3.44k | } else { | 723 | 3.44k | fde_entry = DwarfFde{}; | 724 | 3.44k | fde_entry->cfa_instructions_end = next_entries_offset; | 725 | 3.44k | fde_entry->cie_offset = cie_offset; | 726 | 3.44k | if (!FillInFde(&*fde_entry)) { | 727 | 438 | return false; | 728 | 438 | } | 729 | 3.44k | } | 730 | 3.02k | return true; | 731 | 3.50k | } |
|
732 | | |
733 | | template <typename AddressType> |
734 | 0 | void DwarfSectionImpl<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) { |
735 | 0 | if (fde_index_.empty()) { |
736 | 0 | BuildFdeIndex(); |
737 | 0 | } |
738 | 0 | for (auto& it : fde_index_) { |
739 | 0 | fdes->push_back(GetFdeFromOffset(it.second)); |
740 | 0 | } |
741 | 0 | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::GetFdes(std::__1::vector<unwindstack::DwarfFde const*, std::__1::allocator<unwindstack::DwarfFde const*> >*) Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned long>::GetFdes(std::__1::vector<unwindstack::DwarfFde const*, std::__1::allocator<unwindstack::DwarfFde const*> >*) |
742 | | |
743 | | template <typename AddressType> |
744 | 675 | const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromPc(uint64_t pc) { |
745 | | // Ensure that the binary search table is initialized. |
746 | 675 | if (fde_index_.empty()) { |
747 | 674 | BuildFdeIndex(); |
748 | 674 | } |
749 | | |
750 | | // Find the FDE offset in the binary search table. |
751 | 1.17k | auto comp = [](uint64_t pc, auto& entry) { return pc < entry.first; };Unexecuted instantiation: auto unwindstack::DwarfSectionImpl<unsigned int>::GetFdeFromPc(unsigned long)::{lambda(unsigned long, auto:1&)#1}::operator()<std::__1::pair<unsigned long, unsigned long> >(unsigned long, std::__1::pair<unsigned long, unsigned long>&) constauto unwindstack::DwarfSectionImpl<unsigned long>::GetFdeFromPc(unsigned long)::{lambda(unsigned long, auto:1&)#1}::operator()<std::__1::pair<unsigned long, unsigned long> >(unsigned long, std::__1::pair<unsigned long, unsigned long>&) constLine | Count | Source | 751 | 1.17k | auto comp = [](uint64_t pc, auto& entry) { return pc < entry.first; }; |
|
752 | 675 | auto it = std::upper_bound(fde_index_.begin(), fde_index_.end(), pc, comp); |
753 | 675 | if (it == fde_index_.end()) { |
754 | 319 | return nullptr; |
755 | 319 | } |
756 | | |
757 | | // Load the full FDE entry based on the offset. |
758 | 356 | const DwarfFde* fde = GetFdeFromOffset(/*fde_offset=*/it->second); |
759 | 356 | return fde != nullptr && fde->pc_start <= pc ? fde : nullptr; |
760 | 675 | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::GetFdeFromPc(unsigned long) unwindstack::DwarfSectionImpl<unsigned long>::GetFdeFromPc(unsigned long) Line | Count | Source | 744 | 675 | const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromPc(uint64_t pc) { | 745 | | // Ensure that the binary search table is initialized. | 746 | 675 | if (fde_index_.empty()) { | 747 | 674 | BuildFdeIndex(); | 748 | 674 | } | 749 | | | 750 | | // Find the FDE offset in the binary search table. | 751 | 675 | auto comp = [](uint64_t pc, auto& entry) { return pc < entry.first; }; | 752 | 675 | auto it = std::upper_bound(fde_index_.begin(), fde_index_.end(), pc, comp); | 753 | 675 | if (it == fde_index_.end()) { | 754 | 319 | return nullptr; | 755 | 319 | } | 756 | | | 757 | | // Load the full FDE entry based on the offset. | 758 | 356 | const DwarfFde* fde = GetFdeFromOffset(/*fde_offset=*/it->second); | 759 | 356 | return fde != nullptr && fde->pc_start <= pc ? fde : nullptr; | 760 | 675 | } |
|
761 | | |
762 | | // Create binary search table to make FDE lookups fast (sorted by pc_end). |
763 | | // We store only the FDE offset rather than the full entry to save memory. |
764 | | // |
765 | | // If there are overlapping entries, it inserts additional entries to ensure |
766 | | // that one of the overlapping entries is found (it is undefined which one). |
767 | | template <typename AddressType> |
768 | 674 | void DwarfSectionImpl<AddressType>::BuildFdeIndex() { |
769 | 674 | struct FdeInfo { |
770 | 674 | uint64_t pc_start, pc_end, fde_offset; |
771 | 674 | }; |
772 | 674 | std::vector<FdeInfo> fdes; |
773 | 3.70k | for (uint64_t offset = entries_offset_; offset < entries_end_;) { |
774 | 3.62k | const uint64_t initial_offset = offset; |
775 | 3.62k | std::optional<DwarfFde> fde; |
776 | 3.62k | if (!GetNextCieOrFde(offset, fde)) { |
777 | 593 | break; |
778 | 593 | } |
779 | 3.02k | if (fde.has_value() && /* defensive check */ (fde->pc_start < fde->pc_end)) { |
780 | 2.94k | fdes.push_back({fde->pc_start, fde->pc_end, initial_offset}); |
781 | 2.94k | } |
782 | 3.02k | if (offset <= initial_offset) { |
783 | 0 | break; // Jump back. Simply consider the processing done in this case. |
784 | 0 | } |
785 | 3.02k | } |
786 | 11.4k | std::sort(fdes.begin(), fdes.end(), [](const FdeInfo& a, const FdeInfo& b) { |
787 | 11.4k | return std::tie(a.pc_end, a.fde_offset) < std::tie(b.pc_end, b.fde_offset); |
788 | 11.4k | }); Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::BuildFdeIndex()::{lambda(unwindstack::DwarfSectionImpl<unsigned int>::BuildFdeIndex()::FdeInfo const&, unwindstack::DwarfSectionImpl<unsigned int>::BuildFdeIndex()::FdeInfo const&)#1}::operator()(unwindstack::DwarfSectionImpl<unsigned int>::BuildFdeIndex()::FdeInfo const&, unwindstack::DwarfSectionImpl<unsigned int>::BuildFdeIndex()::FdeInfo const&) constunwindstack::DwarfSectionImpl<unsigned long>::BuildFdeIndex()::{lambda(unwindstack::DwarfSectionImpl<unsigned long>::BuildFdeIndex()::FdeInfo const&, unwindstack::DwarfSectionImpl<unsigned long>::BuildFdeIndex()::FdeInfo const&)#1}::operator()(unwindstack::DwarfSectionImpl<unsigned long>::BuildFdeIndex()::FdeInfo const&, unwindstack::DwarfSectionImpl<unsigned long>::BuildFdeIndex()::FdeInfo const&) constLine | Count | Source | 786 | 11.4k | std::sort(fdes.begin(), fdes.end(), [](const FdeInfo& a, const FdeInfo& b) { | 787 | 11.4k | return std::tie(a.pc_end, a.fde_offset) < std::tie(b.pc_end, b.fde_offset); | 788 | 11.4k | }); |
|
789 | | |
790 | | // If there are overlapping entries, ensure that we can always find one of them. |
791 | | // For example, for entries: [300, 350) [400, 450) [100, 550) [600, 650) |
792 | | // We add the following: [100, 300) [100, 400) |
793 | | // Which ensures that the [100, 550) entry can be found in its whole range. |
794 | 674 | if (!fdes.empty()) { |
795 | 360 | FdeInfo filling = fdes.back(); // Entry with the minimal pc_start seen so far. |
796 | 3.30k | for (ssize_t i = fdes.size() - 1; i >= 0; i--) { // Iterate backwards. |
797 | 2.94k | uint64_t prev_pc_end = (i > 0) ? fdes[i - 1].pc_end : 0; |
798 | | // If there is a gap between entries and the filling reaches the gap, fill it. |
799 | 2.94k | if (prev_pc_end < fdes[i].pc_start && filling.pc_start < fdes[i].pc_start) { |
800 | 922 | fdes.push_back({filling.pc_start, fdes[i].pc_start, filling.fde_offset}); |
801 | 922 | } |
802 | 2.94k | if (fdes[i].pc_start < filling.pc_start) { |
803 | 759 | filling = fdes[i]; |
804 | 759 | } |
805 | 2.94k | } |
806 | 360 | } |
807 | | |
808 | | // Copy data to the final binary search table (pc_end, fde_offset) and sort it. |
809 | 674 | fde_index_.reserve(fdes.size()); |
810 | 3.87k | for (const FdeInfo& it : fdes) { |
811 | 3.87k | fde_index_.emplace_back(it.pc_end, it.fde_offset); |
812 | 3.87k | } |
813 | 674 | if (!std::is_sorted(fde_index_.begin(), fde_index_.end())) { |
814 | 260 | std::sort(fde_index_.begin(), fde_index_.end()); |
815 | 260 | } |
816 | 674 | } Unexecuted instantiation: unwindstack::DwarfSectionImpl<unsigned int>::BuildFdeIndex() unwindstack::DwarfSectionImpl<unsigned long>::BuildFdeIndex() Line | Count | Source | 768 | 674 | void DwarfSectionImpl<AddressType>::BuildFdeIndex() { | 769 | 674 | struct FdeInfo { | 770 | 674 | uint64_t pc_start, pc_end, fde_offset; | 771 | 674 | }; | 772 | 674 | std::vector<FdeInfo> fdes; | 773 | 3.70k | for (uint64_t offset = entries_offset_; offset < entries_end_;) { | 774 | 3.62k | const uint64_t initial_offset = offset; | 775 | 3.62k | std::optional<DwarfFde> fde; | 776 | 3.62k | if (!GetNextCieOrFde(offset, fde)) { | 777 | 593 | break; | 778 | 593 | } | 779 | 3.02k | if (fde.has_value() && /* defensive check */ (fde->pc_start < fde->pc_end)) { | 780 | 2.94k | fdes.push_back({fde->pc_start, fde->pc_end, initial_offset}); | 781 | 2.94k | } | 782 | 3.02k | if (offset <= initial_offset) { | 783 | 0 | break; // Jump back. Simply consider the processing done in this case. | 784 | 0 | } | 785 | 3.02k | } | 786 | 674 | std::sort(fdes.begin(), fdes.end(), [](const FdeInfo& a, const FdeInfo& b) { | 787 | 674 | return std::tie(a.pc_end, a.fde_offset) < std::tie(b.pc_end, b.fde_offset); | 788 | 674 | }); | 789 | | | 790 | | // If there are overlapping entries, ensure that we can always find one of them. | 791 | | // For example, for entries: [300, 350) [400, 450) [100, 550) [600, 650) | 792 | | // We add the following: [100, 300) [100, 400) | 793 | | // Which ensures that the [100, 550) entry can be found in its whole range. | 794 | 674 | if (!fdes.empty()) { | 795 | 360 | FdeInfo filling = fdes.back(); // Entry with the minimal pc_start seen so far. | 796 | 3.30k | for (ssize_t i = fdes.size() - 1; i >= 0; i--) { // Iterate backwards. | 797 | 2.94k | uint64_t prev_pc_end = (i > 0) ? fdes[i - 1].pc_end : 0; | 798 | | // If there is a gap between entries and the filling reaches the gap, fill it. | 799 | 2.94k | if (prev_pc_end < fdes[i].pc_start && filling.pc_start < fdes[i].pc_start) { | 800 | 922 | fdes.push_back({filling.pc_start, fdes[i].pc_start, filling.fde_offset}); | 801 | 922 | } | 802 | 2.94k | if (fdes[i].pc_start < filling.pc_start) { | 803 | 759 | filling = fdes[i]; | 804 | 759 | } | 805 | 2.94k | } | 806 | 360 | } | 807 | | | 808 | | // Copy data to the final binary search table (pc_end, fde_offset) and sort it. | 809 | 674 | fde_index_.reserve(fdes.size()); | 810 | 3.87k | for (const FdeInfo& it : fdes) { | 811 | 3.87k | fde_index_.emplace_back(it.pc_end, it.fde_offset); | 812 | 3.87k | } | 813 | 674 | if (!std::is_sorted(fde_index_.begin(), fde_index_.end())) { | 814 | 260 | std::sort(fde_index_.begin(), fde_index_.end()); | 815 | 260 | } | 816 | 674 | } |
|
817 | | |
818 | | // Explicitly instantiate DwarfSectionImpl |
819 | | template class DwarfSectionImpl<uint32_t>; |
820 | | template class DwarfSectionImpl<uint64_t>; |
821 | | |
822 | | // Explicitly instantiate DwarfDebugFrame |
823 | | template class DwarfDebugFrame<uint32_t>; |
824 | | template class DwarfDebugFrame<uint64_t>; |
825 | | |
826 | | // Explicitly instantiate DwarfEhFrame |
827 | | template class DwarfEhFrame<uint32_t>; |
828 | | template class DwarfEhFrame<uint64_t>; |
829 | | |
830 | | } // namespace unwindstack |