blob: ad25e809a70d4c6d0beacbd3525a20c881442549 [file] [log] [blame]
Christopher Ferris53a3c9b2017-05-10 18:34:15 -07001/*
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
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080019#include <unwindstack/DwarfError.h>
Christopher Ferrisd226a512017-07-14 10:37:19 -070020#include <unwindstack/DwarfLocation.h>
21#include <unwindstack/DwarfMemory.h>
22#include <unwindstack/DwarfSection.h>
23#include <unwindstack/DwarfStructs.h>
Tamas Petz6835d012020-01-22 14:22:41 +010024#include <unwindstack/Elf.h>
Christopher Ferrisd226a512017-07-14 10:37:19 -070025#include <unwindstack/Log.h>
26#include <unwindstack/Memory.h>
27#include <unwindstack/Regs.h>
28
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070029#include "DwarfCfa.h"
Christopher Ferrisc9dee842017-11-03 14:50:27 -070030#include "DwarfDebugFrame.h"
31#include "DwarfEhFrame.h"
Christopher Ferris559c7f22018-02-12 20:18:03 -080032#include "DwarfEncoding.h"
33#include "DwarfOp.h"
34#include "RegsInfo.h"
Christopher Ferrisc9dee842017-11-03 14:50:27 -070035
Christopher Ferrisd226a512017-07-14 10:37:19 -070036namespace unwindstack {
37
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -080038DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {}
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070039
Ryan Prichard9b8f5452020-09-30 18:31:05 -070040bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished,
41 bool* is_signal_frame) {
David Srbecky3386eba2018-03-14 21:30:25 +000042 // Lookup the pc in the cache.
43 auto it = loc_regs_.upper_bound(pc);
44 if (it == loc_regs_.end() || pc < it->second.pc_start) {
45 last_error_.code = DWARF_ERROR_NONE;
46 const DwarfFde* fde = GetFdeFromPc(pc);
47 if (fde == nullptr || fde->cie == nullptr) {
48 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
49 return false;
50 }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070051
David Srbecky3386eba2018-03-14 21:30:25 +000052 // Now get the location information for this pc.
53 dwarf_loc_regs_t loc_regs;
Tamas Petz6835d012020-01-22 14:22:41 +010054 if (!GetCfaLocationInfo(pc, fde, &loc_regs, regs->Arch())) {
David Srbecky3386eba2018-03-14 21:30:25 +000055 return false;
56 }
57 loc_regs.cie = fde->cie;
58
59 // Store it in the cache.
60 it = loc_regs_.emplace(loc_regs.pc_end, std::move(loc_regs)).first;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070061 }
62
Ryan Prichard9b8f5452020-09-30 18:31:05 -070063 *is_signal_frame = it->second.cie->is_signal_frame;
64
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070065 // Now eval the actual registers.
David Srbecky3386eba2018-03-14 21:30:25 +000066 return Eval(it->second.cie, process_memory, it->second, regs, finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070067}
68
69template <typename AddressType>
Christopher Ferris92acaac2018-06-21 10:44:02 -070070const DwarfCie* DwarfSectionImpl<AddressType>::GetCieFromOffset(uint64_t offset) {
71 auto cie_entry = cie_entries_.find(offset);
72 if (cie_entry != cie_entries_.end()) {
73 return &cie_entry->second;
74 }
75 DwarfCie* cie = &cie_entries_[offset];
Christopher Ferris4ca98e12019-10-29 10:21:11 -070076 memory_.set_data_offset(entries_offset_);
Christopher Ferris92acaac2018-06-21 10:44:02 -070077 memory_.set_cur_offset(offset);
78 if (!FillInCieHeader(cie) || !FillInCie(cie)) {
79 // Erase the cached entry.
80 cie_entries_.erase(offset);
81 return nullptr;
82 }
83 return cie;
84}
85
86template <typename AddressType>
87bool DwarfSectionImpl<AddressType>::FillInCieHeader(DwarfCie* cie) {
88 cie->lsda_encoding = DW_EH_PE_omit;
89 uint32_t length32;
90 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
91 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
92 last_error_.address = memory_.cur_offset();
93 return false;
94 }
95 if (length32 == static_cast<uint32_t>(-1)) {
96 // 64 bit Cie
97 uint64_t length64;
98 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
99 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
100 last_error_.address = memory_.cur_offset();
101 return false;
102 }
103
104 cie->cfa_instructions_end = memory_.cur_offset() + length64;
105 cie->fde_address_encoding = DW_EH_PE_sdata8;
106
107 uint64_t cie_id;
108 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
109 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
110 last_error_.address = memory_.cur_offset();
111 return false;
112 }
113 if (cie_id != cie64_value_) {
114 // This is not a Cie, something has gone horribly wrong.
115 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
116 return false;
117 }
118 } else {
119 // 32 bit Cie
120 cie->cfa_instructions_end = memory_.cur_offset() + length32;
121 cie->fde_address_encoding = DW_EH_PE_sdata4;
122
123 uint32_t cie_id;
124 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
125 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
126 last_error_.address = memory_.cur_offset();
127 return false;
128 }
129 if (cie_id != cie32_value_) {
130 // This is not a Cie, something has gone horribly wrong.
131 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
132 return false;
133 }
134 }
135 return true;
136}
137
138template <typename AddressType>
139bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
140 if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
141 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
142 last_error_.address = memory_.cur_offset();
143 return false;
144 }
145
Christopher Ferrisc312c9a2019-04-01 16:53:56 -0700146 if (cie->version != 1 && cie->version != 3 && cie->version != 4 && cie->version != 5) {
Christopher Ferris92acaac2018-06-21 10:44:02 -0700147 // Unrecognized version.
148 last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION;
149 return false;
150 }
151
152 // Read the augmentation string.
153 char aug_value;
154 do {
155 if (!memory_.ReadBytes(&aug_value, 1)) {
156 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
157 last_error_.address = memory_.cur_offset();
158 return false;
159 }
160 cie->augmentation_string.push_back(aug_value);
161 } while (aug_value != '\0');
162
Christopher Ferrisc312c9a2019-04-01 16:53:56 -0700163 if (cie->version == 4 || cie->version == 5) {
Christopher Ferris92acaac2018-06-21 10:44:02 -0700164 // Skip the Address Size field since we only use it for validation.
165 memory_.set_cur_offset(memory_.cur_offset() + 1);
166
167 // Segment Size
168 if (!memory_.ReadBytes(&cie->segment_size, 1)) {
169 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
170 last_error_.address = memory_.cur_offset();
171 return false;
172 }
173 }
174
175 // Code Alignment Factor
176 if (!memory_.ReadULEB128(&cie->code_alignment_factor)) {
177 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
178 last_error_.address = memory_.cur_offset();
179 return false;
180 }
181
182 // Data Alignment Factor
183 if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) {
184 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
185 last_error_.address = memory_.cur_offset();
186 return false;
187 }
188
189 if (cie->version == 1) {
190 // Return Address is a single byte.
191 uint8_t return_address_register;
192 if (!memory_.ReadBytes(&return_address_register, 1)) {
193 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
194 last_error_.address = memory_.cur_offset();
195 return false;
196 }
197 cie->return_address_register = return_address_register;
198 } else if (!memory_.ReadULEB128(&cie->return_address_register)) {
199 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
200 last_error_.address = memory_.cur_offset();
201 return false;
202 }
203
204 if (cie->augmentation_string[0] != 'z') {
205 cie->cfa_instructions_offset = memory_.cur_offset();
206 return true;
207 }
208
209 uint64_t aug_length;
210 if (!memory_.ReadULEB128(&aug_length)) {
211 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
212 last_error_.address = memory_.cur_offset();
213 return false;
214 }
215 cie->cfa_instructions_offset = memory_.cur_offset() + aug_length;
216
217 for (size_t i = 1; i < cie->augmentation_string.size(); i++) {
218 switch (cie->augmentation_string[i]) {
219 case 'L':
220 if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) {
221 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
222 last_error_.address = memory_.cur_offset();
223 return false;
224 }
225 break;
226 case 'P': {
227 uint8_t encoding;
228 if (!memory_.ReadBytes(&encoding, 1)) {
229 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
230 last_error_.address = memory_.cur_offset();
231 return false;
232 }
233 memory_.set_pc_offset(pc_offset_);
234 if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
235 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
236 last_error_.address = memory_.cur_offset();
237 return false;
238 }
239 } break;
240 case 'R':
241 if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) {
242 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
243 last_error_.address = memory_.cur_offset();
244 return false;
245 }
246 break;
Ryan Prichard9b8f5452020-09-30 18:31:05 -0700247 case 'S':
248 cie->is_signal_frame = true;
249 break;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700250 }
251 }
252 return true;
253}
254
255template <typename AddressType>
256const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) {
257 auto fde_entry = fde_entries_.find(offset);
258 if (fde_entry != fde_entries_.end()) {
259 return &fde_entry->second;
260 }
261 DwarfFde* fde = &fde_entries_[offset];
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700262 memory_.set_data_offset(entries_offset_);
Christopher Ferris92acaac2018-06-21 10:44:02 -0700263 memory_.set_cur_offset(offset);
264 if (!FillInFdeHeader(fde) || !FillInFde(fde)) {
265 fde_entries_.erase(offset);
266 return nullptr;
267 }
268 return fde;
269}
270
271template <typename AddressType>
272bool DwarfSectionImpl<AddressType>::FillInFdeHeader(DwarfFde* fde) {
273 uint32_t length32;
274 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
275 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
276 last_error_.address = memory_.cur_offset();
277 return false;
278 }
279
280 if (length32 == static_cast<uint32_t>(-1)) {
281 // 64 bit Fde.
282 uint64_t length64;
283 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
284 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
285 last_error_.address = memory_.cur_offset();
286 return false;
287 }
288 fde->cfa_instructions_end = memory_.cur_offset() + length64;
289
290 uint64_t value64;
291 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
292 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
293 last_error_.address = memory_.cur_offset();
294 return false;
295 }
296 if (value64 == cie64_value_) {
297 // This is a Cie, this means something has gone wrong.
298 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
299 return false;
300 }
301
302 // Get the Cie pointer, which is necessary to properly read the rest of
303 // of the Fde information.
304 fde->cie_offset = GetCieOffsetFromFde64(value64);
305 } else {
306 // 32 bit Fde.
307 fde->cfa_instructions_end = memory_.cur_offset() + length32;
308
309 uint32_t value32;
310 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
311 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
312 last_error_.address = memory_.cur_offset();
313 return false;
314 }
315 if (value32 == cie32_value_) {
316 // This is a Cie, this means something has gone wrong.
317 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
318 return false;
319 }
320
321 // Get the Cie pointer, which is necessary to properly read the rest of
322 // of the Fde information.
323 fde->cie_offset = GetCieOffsetFromFde32(value32);
324 }
325 return true;
326}
327
328template <typename AddressType>
329bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
330 uint64_t cur_offset = memory_.cur_offset();
331
332 const DwarfCie* cie = GetCieFromOffset(fde->cie_offset);
333 if (cie == nullptr) {
334 return false;
335 }
336 fde->cie = cie;
337
338 if (cie->segment_size != 0) {
339 // Skip over the segment selector for now.
340 cur_offset += cie->segment_size;
341 }
342 memory_.set_cur_offset(cur_offset);
343
344 // The load bias only applies to the start.
Christopher Ferris819f1312019-10-03 13:35:48 -0700345 memory_.set_pc_offset(section_bias_);
Christopher Ferris92acaac2018-06-21 10:44:02 -0700346 bool valid = memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_start);
347 fde->pc_start = AdjustPcFromFde(fde->pc_start);
348
349 memory_.set_pc_offset(0);
350 if (!valid || !memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_end)) {
351 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
352 last_error_.address = memory_.cur_offset();
353 return false;
354 }
355 fde->pc_end += fde->pc_start;
356
357 if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') {
358 // Augmentation Size
359 uint64_t aug_length;
360 if (!memory_.ReadULEB128(&aug_length)) {
361 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
362 last_error_.address = memory_.cur_offset();
363 return false;
364 }
365 uint64_t cur_offset = memory_.cur_offset();
366
367 memory_.set_pc_offset(pc_offset_);
368 if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
369 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
370 last_error_.address = memory_.cur_offset();
371 return false;
372 }
373
374 // Set our position to after all of the augmentation data.
375 memory_.set_cur_offset(cur_offset + aug_length);
376 }
377 fde->cfa_instructions_offset = memory_.cur_offset();
378
379 return true;
380}
381
382template <typename AddressType>
Christopher Ferris559c7f22018-02-12 20:18:03 -0800383bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, Memory* regular_memory,
384 AddressType* value,
385 RegsInfo<AddressType>* regs_info,
386 bool* is_dex_pc) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700387 DwarfOp<AddressType> op(&memory_, regular_memory);
Christopher Ferris559c7f22018-02-12 20:18:03 -0800388 op.set_regs_info(regs_info);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700389
390 // Need to evaluate the op data.
Christopher Ferris559c7f22018-02-12 20:18:03 -0800391 uint64_t end = loc.values[1];
392 uint64_t start = end - loc.values[0];
393 if (!op.Eval(start, end)) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700394 last_error_ = op.last_error();
395 return false;
396 }
397 if (op.StackSize() == 0) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800398 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700399 return false;
400 }
401 // We don't support an expression that evaluates to a register number.
402 if (op.is_register()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800403 last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700404 return false;
405 }
406 *value = op.StackAt(0);
Christopher Ferris559c7f22018-02-12 20:18:03 -0800407 if (is_dex_pc != nullptr && op.dex_pc_set()) {
408 *is_dex_pc = true;
409 }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700410 return true;
411}
412
413template <typename AddressType>
Christopher Ferris98984b42018-01-17 12:59:45 -0800414struct EvalInfo {
415 const dwarf_loc_regs_t* loc_regs;
416 const DwarfCie* cie;
Christopher Ferris98984b42018-01-17 12:59:45 -0800417 Memory* regular_memory;
418 AddressType cfa;
419 bool return_address_undefined = false;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800420 RegsInfo<AddressType> regs_info;
Christopher Ferris98984b42018-01-17 12:59:45 -0800421};
422
423template <typename AddressType>
424bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg,
425 AddressType* reg_ptr, void* info) {
426 EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info);
427 Memory* regular_memory = eval_info->regular_memory;
428 switch (loc->type) {
429 case DWARF_LOCATION_OFFSET:
430 if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800431 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
432 last_error_.address = eval_info->cfa + loc->values[0];
Christopher Ferris98984b42018-01-17 12:59:45 -0800433 return false;
434 }
435 break;
436 case DWARF_LOCATION_VAL_OFFSET:
437 *reg_ptr = eval_info->cfa + loc->values[0];
438 break;
439 case DWARF_LOCATION_REGISTER: {
440 uint32_t cur_reg = loc->values[0];
Christopher Ferris559c7f22018-02-12 20:18:03 -0800441 if (cur_reg >= eval_info->regs_info.Total()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800442 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris98984b42018-01-17 12:59:45 -0800443 return false;
444 }
Christopher Ferris559c7f22018-02-12 20:18:03 -0800445 *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1];
Christopher Ferris98984b42018-01-17 12:59:45 -0800446 break;
447 }
448 case DWARF_LOCATION_EXPRESSION:
449 case DWARF_LOCATION_VAL_EXPRESSION: {
450 AddressType value;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800451 bool is_dex_pc = false;
452 if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) {
Christopher Ferris98984b42018-01-17 12:59:45 -0800453 return false;
454 }
455 if (loc->type == DWARF_LOCATION_EXPRESSION) {
456 if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800457 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
458 last_error_.address = value;
Christopher Ferris98984b42018-01-17 12:59:45 -0800459 return false;
460 }
461 } else {
462 *reg_ptr = value;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800463 if (is_dex_pc) {
464 eval_info->regs_info.regs->set_dex_pc(value);
465 }
Christopher Ferris98984b42018-01-17 12:59:45 -0800466 }
467 break;
468 }
469 case DWARF_LOCATION_UNDEFINED:
470 if (reg == eval_info->cie->return_address_register) {
471 eval_info->return_address_undefined = true;
472 }
Christopher Ferris3f9582f2018-09-19 14:12:59 -0700473 break;
Tamas Zsoldosf30a46f2020-08-18 12:04:56 +0200474 case DWARF_LOCATION_PSEUDO_REGISTER:
475 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
476 return false;
Christopher Ferris98984b42018-01-17 12:59:45 -0800477 default:
478 break;
479 }
480
481 return true;
482}
483
484template <typename AddressType>
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700485bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700486 const dwarf_loc_regs_t& loc_regs, Regs* regs,
487 bool* finished) {
Christopher Ferris7b8e4672017-06-01 17:55:25 -0700488 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700489 if (cie->return_address_register >= cur_regs->total_regs()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800490 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700491 return false;
492 }
493
494 // Get the cfa value;
495 auto cfa_entry = loc_regs.find(CFA_REG);
496 if (cfa_entry == loc_regs.end()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800497 last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700498 return false;
499 }
500
Christopher Ferris98984b42018-01-17 12:59:45 -0800501 // Always set the dex pc to zero when evaluating.
502 cur_regs->set_dex_pc(0);
503
Tamas Petz6835d012020-01-22 14:22:41 +0100504 // Reset necessary pseudo registers before evaluation.
505 // This is needed for ARM64, for example.
506 regs->ResetPseudoRegisters();
507
Christopher Ferris559c7f22018-02-12 20:18:03 -0800508 EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
509 .cie = cie,
510 .regular_memory = regular_memory,
511 .regs_info = RegsInfo<AddressType>(cur_regs)};
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700512 const DwarfLocation* loc = &cfa_entry->second;
513 // Only a few location types are valid for the cfa.
514 switch (loc->type) {
515 case DWARF_LOCATION_REGISTER:
516 if (loc->values[0] >= cur_regs->total_regs()) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800517 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700518 return false;
519 }
Yabin Cui11e96fe2018-03-14 18:16:22 -0700520 eval_info.cfa = (*cur_regs)[loc->values[0]];
Christopher Ferris98984b42018-01-17 12:59:45 -0800521 eval_info.cfa += loc->values[1];
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700522 break;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700523 case DWARF_LOCATION_VAL_EXPRESSION: {
524 AddressType value;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800525 if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700526 return false;
527 }
David Srbecky3692f252018-03-08 16:57:19 +0000528 // There is only one type of valid expression for CFA evaluation.
529 eval_info.cfa = value;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700530 break;
531 }
532 default:
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800533 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700534 return false;
535 }
536
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700537 for (const auto& entry : loc_regs) {
Christopher Ferris98984b42018-01-17 12:59:45 -0800538 uint32_t reg = entry.first;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700539 // Already handled the CFA register.
540 if (reg == CFA_REG) continue;
541
Christopher Ferris98984b42018-01-17 12:59:45 -0800542 AddressType* reg_ptr;
Christopher Ferris559c7f22018-02-12 20:18:03 -0800543 if (reg >= cur_regs->total_regs()) {
Tamas Petz6835d012020-01-22 14:22:41 +0100544 if (entry.second.type != DWARF_LOCATION_PSEUDO_REGISTER) {
545 // Skip this unknown register.
546 continue;
547 }
Tamas Zsoldosf30a46f2020-08-18 12:04:56 +0200548 if (!eval_info.regs_info.regs->SetPseudoRegister(reg, entry.second.values[0])) {
549 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
550 return false;
551 }
552 } else {
553 reg_ptr = eval_info.regs_info.Save(reg);
554 if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
555 return false;
556 }
Christopher Ferris98984b42018-01-17 12:59:45 -0800557 }
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700558 }
559
560 // Find the return address location.
Christopher Ferris98984b42018-01-17 12:59:45 -0800561 if (eval_info.return_address_undefined) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700562 cur_regs->set_pc(0);
563 } else {
564 cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
565 }
Christopher Ferris2502a602017-10-23 13:51:54 -0700566
Ryan Prichard9b8f5452020-09-30 18:31:05 -0700567 // If the pc was set to zero, consider this the final frame. Exception: if
568 // this is the sigreturn frame, then we want to try to recover the real PC
569 // using the return address (from LR or the stack), so keep going.
570 *finished = (cur_regs->pc() == 0 && !cie->is_signal_frame) ? true : false;
Christopher Ferris2502a602017-10-23 13:51:54 -0700571
Christopher Ferris98984b42018-01-17 12:59:45 -0800572 cur_regs->set_sp(eval_info.cfa);
Christopher Ferrisfda7edd2017-10-31 16:10:42 -0700573
574 return true;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700575}
576
577template <typename AddressType>
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700578bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
Tamas Petz6835d012020-01-22 14:22:41 +0100579 dwarf_loc_regs_t* loc_regs, ArchEnum arch) {
580 DwarfCfa<AddressType> cfa(&memory_, fde, arch);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700581
582 // Look for the cached copy of the cie data.
583 auto reg_entry = cie_loc_regs_.find(fde->cie_offset);
584 if (reg_entry == cie_loc_regs_.end()) {
585 if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end,
586 loc_regs)) {
587 last_error_ = cfa.last_error();
588 return false;
589 }
590 cie_loc_regs_[fde->cie_offset] = *loc_regs;
591 }
592 cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]);
593 if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) {
594 last_error_ = cfa.last_error();
595 return false;
596 }
597 return true;
598}
599
600template <typename AddressType>
Tamas Petz6835d012020-01-22 14:22:41 +0100601bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const DwarfFde* fde,
602 ArchEnum arch) {
603 DwarfCfa<AddressType> cfa(&memory_, fde, arch);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700604
605 // Always print the cie information.
606 const DwarfCie* cie = fde->cie;
Christopher Ferris4cc36d22018-06-06 14:47:31 -0700607 if (!cfa.Log(indent, pc, cie->cfa_instructions_offset, cie->cfa_instructions_end)) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700608 last_error_ = cfa.last_error();
609 return false;
610 }
Christopher Ferris4cc36d22018-06-06 14:47:31 -0700611 if (!cfa.Log(indent, pc, fde->cfa_instructions_offset, fde->cfa_instructions_end)) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700612 last_error_ = cfa.last_error();
613 return false;
614 }
615 return true;
616}
617
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700618template <typename AddressType>
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700619bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size, int64_t section_bias) {
Christopher Ferris819f1312019-10-03 13:35:48 -0700620 section_bias_ = section_bias;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700621 entries_offset_ = offset;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700622 next_entries_offset_ = offset;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700623 entries_end_ = offset + size;
624
625 memory_.clear_func_offset();
626 memory_.clear_text_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700627 memory_.set_cur_offset(offset);
Christopher Ferris4cc36d22018-06-06 14:47:31 -0700628 pc_offset_ = offset;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700629
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700630 return true;
631}
632
Christopher Ferris92acaac2018-06-21 10:44:02 -0700633// Create a cached version of the fde information such that it is a std::map
634// that is indexed by end pc and contains a pair that represents the start pc
635// followed by the fde object. The fde pointers are owned by fde_entries_
636// and not by the map object.
637// It is possible for an fde to be represented by multiple entries in
638// the map. This can happen if the the start pc and end pc overlap already
639// existing entries. For example, if there is already an entry of 0x400, 0x200,
640// and an fde has a start pc of 0x100 and end pc of 0x500, two new entries
641// will be added: 0x200, 0x100 and 0x500, 0x400.
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700642template <typename AddressType>
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700643void DwarfSectionImpl<AddressType>::InsertFde(const DwarfFde* fde) {
Christopher Ferris92acaac2018-06-21 10:44:02 -0700644 uint64_t start = fde->pc_start;
645 uint64_t end = fde->pc_end;
646 auto it = fdes_.upper_bound(start);
David Srbeckya6617cb2020-02-20 16:22:52 +0000647 while (it != fdes_.end() && start < end && it->second.first < end) {
648 if (start < it->second.first) {
649 fdes_[it->second.first] = std::make_pair(start, fde);
Christopher Ferris92acaac2018-06-21 10:44:02 -0700650 }
651 start = it->first;
652 ++it;
653 }
654 if (start < end) {
655 fdes_[end] = std::make_pair(start, fde);
656 }
657}
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700658
Christopher Ferris92acaac2018-06-21 10:44:02 -0700659template <typename AddressType>
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700660bool DwarfSectionImpl<AddressType>::GetNextCieOrFde(const DwarfFde** fde_entry) {
Christopher Ferris92acaac2018-06-21 10:44:02 -0700661 uint64_t start_offset = next_entries_offset_;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700662
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700663 memory_.set_data_offset(entries_offset_);
Christopher Ferris92acaac2018-06-21 10:44:02 -0700664 memory_.set_cur_offset(next_entries_offset_);
665 uint32_t value32;
666 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
667 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
668 last_error_.address = memory_.cur_offset();
669 return false;
670 }
671
672 uint64_t cie_offset;
673 uint8_t cie_fde_encoding;
674 bool entry_is_cie = false;
675 if (value32 == static_cast<uint32_t>(-1)) {
676 // 64 bit entry.
677 uint64_t value64;
678 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
679 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
680 last_error_.address = memory_.cur_offset();
681 return false;
682 }
683
684 next_entries_offset_ = memory_.cur_offset() + value64;
685 // Read the Cie Id of a Cie or the pointer of the Fde.
686 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
687 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
688 last_error_.address = memory_.cur_offset();
689 return false;
690 }
691
692 if (value64 == cie64_value_) {
693 entry_is_cie = true;
694 cie_fde_encoding = DW_EH_PE_sdata8;
695 } else {
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700696 cie_offset = GetCieOffsetFromFde64(value64);
Christopher Ferris92acaac2018-06-21 10:44:02 -0700697 }
698 } else {
699 next_entries_offset_ = memory_.cur_offset() + value32;
700
701 // 32 bit Cie
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700702 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
Christopher Ferris2fcf4cf2018-01-23 17:52:23 -0800703 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
704 last_error_.address = memory_.cur_offset();
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700705 return false;
706 }
707
Christopher Ferris92acaac2018-06-21 10:44:02 -0700708 if (value32 == cie32_value_) {
709 entry_is_cie = true;
710 cie_fde_encoding = DW_EH_PE_sdata4;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700711 } else {
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700712 cie_offset = GetCieOffsetFromFde32(value32);
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700713 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700714 }
715
Christopher Ferris92acaac2018-06-21 10:44:02 -0700716 if (entry_is_cie) {
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700717 auto entry = cie_entries_.find(start_offset);
718 if (entry == cie_entries_.end()) {
719 DwarfCie* cie = &cie_entries_[start_offset];
720 cie->lsda_encoding = DW_EH_PE_omit;
721 cie->cfa_instructions_end = next_entries_offset_;
722 cie->fde_address_encoding = cie_fde_encoding;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700723
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700724 if (!FillInCie(cie)) {
725 cie_entries_.erase(start_offset);
726 return false;
727 }
Christopher Ferris92acaac2018-06-21 10:44:02 -0700728 }
729 *fde_entry = nullptr;
730 } else {
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700731 auto entry = fde_entries_.find(start_offset);
732 if (entry != fde_entries_.end()) {
733 *fde_entry = &entry->second;
734 } else {
735 DwarfFde* fde = &fde_entries_[start_offset];
736 fde->cfa_instructions_end = next_entries_offset_;
737 fde->cie_offset = cie_offset;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700738
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700739 if (!FillInFde(fde)) {
740 fde_entries_.erase(start_offset);
741 return false;
742 }
743 *fde_entry = fde;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700744 }
Christopher Ferris92acaac2018-06-21 10:44:02 -0700745 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700746 return true;
747}
748
749template <typename AddressType>
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700750void DwarfSectionImpl<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
Christopher Ferris92acaac2018-06-21 10:44:02 -0700751 // Loop through the already cached entries.
752 uint64_t entry_offset = entries_offset_;
753 while (entry_offset < next_entries_offset_) {
754 auto cie_it = cie_entries_.find(entry_offset);
755 if (cie_it != cie_entries_.end()) {
756 entry_offset = cie_it->second.cfa_instructions_end;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700757 } else {
Christopher Ferris92acaac2018-06-21 10:44:02 -0700758 auto fde_it = fde_entries_.find(entry_offset);
759 if (fde_it == fde_entries_.end()) {
760 // No fde or cie at this entry, should not be possible.
761 return;
762 }
763 entry_offset = fde_it->second.cfa_instructions_end;
764 fdes->push_back(&fde_it->second);
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700765 }
766 }
Christopher Ferris92acaac2018-06-21 10:44:02 -0700767
768 while (next_entries_offset_ < entries_end_) {
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700769 const DwarfFde* fde;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700770 if (!GetNextCieOrFde(&fde)) {
771 break;
772 }
773 if (fde != nullptr) {
774 InsertFde(fde);
775 fdes->push_back(fde);
776 }
777
778 if (next_entries_offset_ < memory_.cur_offset()) {
779 // Simply consider the processing done in this case.
780 break;
781 }
782 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700783}
784
785template <typename AddressType>
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700786const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromPc(uint64_t pc) {
Christopher Ferris92acaac2018-06-21 10:44:02 -0700787 // Search in the list of fdes we already have.
788 auto it = fdes_.upper_bound(pc);
789 if (it != fdes_.end()) {
790 if (pc >= it->second.first) {
791 return it->second.second;
792 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700793 }
Christopher Ferris92acaac2018-06-21 10:44:02 -0700794
795 // The section might have overlapping pcs in fdes, so it is necessary
796 // to do a linear search of the fdes by pc. As fdes are read, a cached
797 // search map is created.
798 while (next_entries_offset_ < entries_end_) {
Christopher Ferris4ca98e12019-10-29 10:21:11 -0700799 const DwarfFde* fde;
Christopher Ferris92acaac2018-06-21 10:44:02 -0700800 if (!GetNextCieOrFde(&fde)) {
801 return nullptr;
802 }
803 if (fde != nullptr) {
804 InsertFde(fde);
805 if (pc >= fde->pc_start && pc < fde->pc_end) {
806 return fde;
807 }
808 }
809
810 if (next_entries_offset_ < memory_.cur_offset()) {
811 // Simply consider the processing done in this case.
812 break;
813 }
814 }
815 return nullptr;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700816}
817
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700818// Explicitly instantiate DwarfSectionImpl
819template class DwarfSectionImpl<uint32_t>;
820template class DwarfSectionImpl<uint64_t>;
Christopher Ferrisd226a512017-07-14 10:37:19 -0700821
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700822// Explicitly instantiate DwarfDebugFrame
823template class DwarfDebugFrame<uint32_t>;
824template class DwarfDebugFrame<uint64_t>;
825
826// Explicitly instantiate DwarfEhFrame
827template class DwarfEhFrame<uint32_t>;
828template class DwarfEhFrame<uint64_t>;
829
Christopher Ferrisd226a512017-07-14 10:37:19 -0700830} // namespace unwindstack