blob: 04a1faefa7ff1f4880fa5b1f439d516dbec084cd [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 Ferrisd226a512017-07-14 10:37:19 -070019#include <unwindstack/DwarfLocation.h>
20#include <unwindstack/DwarfMemory.h>
21#include <unwindstack/DwarfSection.h>
22#include <unwindstack/DwarfStructs.h>
23#include <unwindstack/Log.h>
24#include <unwindstack/Memory.h>
25#include <unwindstack/Regs.h>
26
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070027#include "DwarfCfa.h"
Christopher Ferrisd226a512017-07-14 10:37:19 -070028#include "DwarfEncoding.h"
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070029#include "DwarfError.h"
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070030#include "DwarfOp.h"
Christopher Ferrisd226a512017-07-14 10:37:19 -070031
Christopher Ferrisc9dee842017-11-03 14:50:27 -070032#include "DwarfDebugFrame.h"
33#include "DwarfEhFrame.h"
34
Christopher Ferrisd226a512017-07-14 10:37:19 -070035namespace unwindstack {
36
Christopher Ferris98984b42018-01-17 12:59:45 -080037constexpr uint64_t DEX_PC_REG = 0x20444558;
38
Christopher Ferrisd226a512017-07-14 10:37:19 -070039DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {}
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070040
41const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
42 uint64_t fde_offset;
43 if (!GetFdeOffsetFromPc(pc, &fde_offset)) {
44 return nullptr;
45 }
46 const DwarfFde* fde = GetFdeFromOffset(fde_offset);
Christopher Ferris13b86652017-11-05 14:01:43 -080047 if (fde == nullptr) {
48 return nullptr;
49 }
50
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070051 // Guaranteed pc >= pc_start, need to check pc in the fde range.
52 if (pc < fde->pc_end) {
53 return fde;
54 }
55 last_error_ = DWARF_ERROR_ILLEGAL_STATE;
56 return nullptr;
57}
58
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070059bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
Christopher Ferrisd226a512017-07-14 10:37:19 -070060 last_error_ = DWARF_ERROR_NONE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070061 const DwarfFde* fde = GetFdeFromPc(pc);
62 if (fde == nullptr || fde->cie == nullptr) {
63 last_error_ = DWARF_ERROR_ILLEGAL_STATE;
64 return false;
65 }
66
67 // Now get the location information for this pc.
68 dwarf_loc_regs_t loc_regs;
69 if (!GetCfaLocationInfo(pc, fde, &loc_regs)) {
70 return false;
71 }
72
73 // Now eval the actual registers.
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070074 return Eval(fde->cie, process_memory, loc_regs, regs, finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070075}
76
77template <typename AddressType>
78bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uint8_t version,
79 Memory* regular_memory, AddressType* value) {
80 DwarfOp<AddressType> op(&memory_, regular_memory);
81
82 // Need to evaluate the op data.
83 uint64_t start = loc.values[1];
84 uint64_t end = start + loc.values[0];
85 if (!op.Eval(start, end, version)) {
86 last_error_ = op.last_error();
87 return false;
88 }
89 if (op.StackSize() == 0) {
90 last_error_ = DWARF_ERROR_ILLEGAL_STATE;
91 return false;
92 }
93 // We don't support an expression that evaluates to a register number.
94 if (op.is_register()) {
95 last_error_ = DWARF_ERROR_NOT_IMPLEMENTED;
96 return false;
97 }
98 *value = op.StackAt(0);
99 return true;
100}
101
102template <typename AddressType>
Christopher Ferris98984b42018-01-17 12:59:45 -0800103struct EvalInfo {
104 const dwarf_loc_regs_t* loc_regs;
105 const DwarfCie* cie;
106 RegsImpl<AddressType>* cur_regs;
107 Memory* regular_memory;
108 AddressType cfa;
109 bool return_address_undefined = false;
110 uint64_t reg_map = 0;
111 AddressType reg_values[64];
112};
113
114template <typename AddressType>
115bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg,
116 AddressType* reg_ptr, void* info) {
117 EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info);
118 Memory* regular_memory = eval_info->regular_memory;
119 switch (loc->type) {
120 case DWARF_LOCATION_OFFSET:
121 if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) {
122 last_error_ = DWARF_ERROR_MEMORY_INVALID;
123 return false;
124 }
125 break;
126 case DWARF_LOCATION_VAL_OFFSET:
127 *reg_ptr = eval_info->cfa + loc->values[0];
128 break;
129 case DWARF_LOCATION_REGISTER: {
130 uint32_t cur_reg = loc->values[0];
131 if (cur_reg >= eval_info->cur_regs->total_regs()) {
132 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
133 return false;
134 }
135 AddressType* cur_reg_ptr = &(*eval_info->cur_regs)[cur_reg];
136 const auto& entry = eval_info->loc_regs->find(cur_reg);
137 if (entry != eval_info->loc_regs->end()) {
138 if (!(eval_info->reg_map & (1 << cur_reg))) {
139 eval_info->reg_map |= 1 << cur_reg;
140 eval_info->reg_values[cur_reg] = *cur_reg_ptr;
141 if (!EvalRegister(&entry->second, cur_reg, cur_reg_ptr, eval_info)) {
142 return false;
143 }
144 }
145
146 // Use the register value from before any evaluations.
147 *reg_ptr = eval_info->reg_values[cur_reg] + loc->values[1];
148 } else {
149 *reg_ptr = *cur_reg_ptr + loc->values[1];
150 }
151 break;
152 }
153 case DWARF_LOCATION_EXPRESSION:
154 case DWARF_LOCATION_VAL_EXPRESSION: {
155 AddressType value;
156 if (!EvalExpression(*loc, eval_info->cie->version, regular_memory, &value)) {
157 return false;
158 }
159 if (loc->type == DWARF_LOCATION_EXPRESSION) {
160 if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) {
161 last_error_ = DWARF_ERROR_MEMORY_INVALID;
162 return false;
163 }
164 } else {
165 *reg_ptr = value;
166 }
167 break;
168 }
169 case DWARF_LOCATION_UNDEFINED:
170 if (reg == eval_info->cie->return_address_register) {
171 eval_info->return_address_undefined = true;
172 }
173 default:
174 break;
175 }
176
177 return true;
178}
179
180template <typename AddressType>
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700181bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700182 const dwarf_loc_regs_t& loc_regs, Regs* regs,
183 bool* finished) {
Christopher Ferris7b8e4672017-06-01 17:55:25 -0700184 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700185 if (cie->return_address_register >= cur_regs->total_regs()) {
186 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
187 return false;
188 }
189
190 // Get the cfa value;
191 auto cfa_entry = loc_regs.find(CFA_REG);
192 if (cfa_entry == loc_regs.end()) {
193 last_error_ = DWARF_ERROR_CFA_NOT_DEFINED;
194 return false;
195 }
196
Christopher Ferris98984b42018-01-17 12:59:45 -0800197 // Always set the dex pc to zero when evaluating.
198 cur_regs->set_dex_pc(0);
199
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700200 AddressType prev_cfa = regs->sp();
201
Christopher Ferris98984b42018-01-17 12:59:45 -0800202 EvalInfo<AddressType> eval_info{
203 .loc_regs = &loc_regs, .cie = cie, .regular_memory = regular_memory, .cur_regs = cur_regs};
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700204 const DwarfLocation* loc = &cfa_entry->second;
205 // Only a few location types are valid for the cfa.
206 switch (loc->type) {
207 case DWARF_LOCATION_REGISTER:
208 if (loc->values[0] >= cur_regs->total_regs()) {
209 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
210 return false;
211 }
212 // If the stack pointer register is the CFA, and the stack
213 // pointer register does not have any associated location
214 // information, use the current cfa value.
215 if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) {
Christopher Ferris98984b42018-01-17 12:59:45 -0800216 eval_info.cfa = prev_cfa;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700217 } else {
Christopher Ferris98984b42018-01-17 12:59:45 -0800218 eval_info.cfa = (*cur_regs)[loc->values[0]];
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700219 }
Christopher Ferris98984b42018-01-17 12:59:45 -0800220 eval_info.cfa += loc->values[1];
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700221 break;
222 case DWARF_LOCATION_EXPRESSION:
223 case DWARF_LOCATION_VAL_EXPRESSION: {
224 AddressType value;
225 if (!EvalExpression(*loc, cie->version, regular_memory, &value)) {
226 return false;
227 }
228 if (loc->type == DWARF_LOCATION_EXPRESSION) {
Christopher Ferris98984b42018-01-17 12:59:45 -0800229 if (!regular_memory->ReadFully(value, &eval_info.cfa, sizeof(AddressType))) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700230 last_error_ = DWARF_ERROR_MEMORY_INVALID;
231 return false;
232 }
233 } else {
Christopher Ferris98984b42018-01-17 12:59:45 -0800234 eval_info.cfa = value;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700235 }
236 break;
237 }
238 default:
239 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
240 return false;
241 }
242
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700243 for (const auto& entry : loc_regs) {
Christopher Ferris98984b42018-01-17 12:59:45 -0800244 uint32_t reg = entry.first;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700245 // Already handled the CFA register.
246 if (reg == CFA_REG) continue;
247
Christopher Ferris98984b42018-01-17 12:59:45 -0800248 AddressType* reg_ptr;
249 AddressType dex_pc = 0;
250 if (reg == DEX_PC_REG) {
251 // Special register that indicates this is a dex pc.
252 dex_pc = 0;
253 reg_ptr = &dex_pc;
254 } else if (reg >= cur_regs->total_regs() || eval_info.reg_map & (1 << reg)) {
255 // Skip this unknown register, or a register that has already been
256 // processed.
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700257 continue;
Christopher Ferris98984b42018-01-17 12:59:45 -0800258 } else {
259 reg_ptr = &(*cur_regs)[reg];
260 eval_info.reg_map |= 1 << reg;
261 eval_info.reg_values[reg] = *reg_ptr;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700262 }
263
Christopher Ferris98984b42018-01-17 12:59:45 -0800264 if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
265 return false;
266 }
267
268 if (reg == DEX_PC_REG) {
269 cur_regs->set_dex_pc(dex_pc);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700270 }
271 }
272
273 // Find the return address location.
Christopher Ferris98984b42018-01-17 12:59:45 -0800274 if (eval_info.return_address_undefined) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700275 cur_regs->set_pc(0);
276 } else {
277 cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
278 }
Christopher Ferris2502a602017-10-23 13:51:54 -0700279
280 // If the pc was set to zero, consider this the final frame.
281 *finished = (cur_regs->pc() == 0) ? true : false;
282
Christopher Ferris98984b42018-01-17 12:59:45 -0800283 cur_regs->set_sp(eval_info.cfa);
Christopher Ferrisfda7edd2017-10-31 16:10:42 -0700284
285 return true;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700286}
287
288template <typename AddressType>
289const DwarfCie* DwarfSectionImpl<AddressType>::GetCie(uint64_t offset) {
290 auto cie_entry = cie_entries_.find(offset);
291 if (cie_entry != cie_entries_.end()) {
292 return &cie_entry->second;
293 }
294 DwarfCie* cie = &cie_entries_[offset];
295 memory_.set_cur_offset(offset);
296 if (!FillInCie(cie)) {
297 // Erase the cached entry.
298 cie_entries_.erase(offset);
299 return nullptr;
300 }
301 return cie;
302}
303
304template <typename AddressType>
305bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
306 uint32_t length32;
307 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
308 last_error_ = DWARF_ERROR_MEMORY_INVALID;
309 return false;
310 }
Christopher Ferrisd226a512017-07-14 10:37:19 -0700311 // Set the default for the lsda encoding.
312 cie->lsda_encoding = DW_EH_PE_omit;
313
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700314 if (length32 == static_cast<uint32_t>(-1)) {
315 // 64 bit Cie
316 uint64_t length64;
317 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
318 last_error_ = DWARF_ERROR_MEMORY_INVALID;
319 return false;
320 }
321
322 cie->cfa_instructions_end = memory_.cur_offset() + length64;
323 cie->fde_address_encoding = DW_EH_PE_sdata8;
324
325 uint64_t cie_id;
326 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
327 last_error_ = DWARF_ERROR_MEMORY_INVALID;
328 return false;
329 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700330 if (cie_id != cie64_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700331 // This is not a Cie, something has gone horribly wrong.
332 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
333 return false;
334 }
335 } else {
336 // 32 bit Cie
337 cie->cfa_instructions_end = memory_.cur_offset() + length32;
338 cie->fde_address_encoding = DW_EH_PE_sdata4;
339
340 uint32_t cie_id;
341 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
342 last_error_ = DWARF_ERROR_MEMORY_INVALID;
343 return false;
344 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700345 if (cie_id != cie32_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700346 // This is not a Cie, something has gone horribly wrong.
347 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
348 return false;
349 }
350 }
351
352 if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
353 last_error_ = DWARF_ERROR_MEMORY_INVALID;
354 return false;
355 }
356
357 if (cie->version != 1 && cie->version != 3 && cie->version != 4) {
358 // Unrecognized version.
359 last_error_ = DWARF_ERROR_UNSUPPORTED_VERSION;
360 return false;
361 }
362
363 // Read the augmentation string.
364 char aug_value;
365 do {
366 if (!memory_.ReadBytes(&aug_value, 1)) {
367 last_error_ = DWARF_ERROR_MEMORY_INVALID;
368 return false;
369 }
370 cie->augmentation_string.push_back(aug_value);
371 } while (aug_value != '\0');
372
373 if (cie->version == 4) {
374 // Skip the Address Size field since we only use it for validation.
375 memory_.set_cur_offset(memory_.cur_offset() + 1);
376
377 // Segment Size
378 if (!memory_.ReadBytes(&cie->segment_size, 1)) {
379 last_error_ = DWARF_ERROR_MEMORY_INVALID;
380 return false;
381 }
382 }
383
384 // Code Alignment Factor
385 if (!memory_.ReadULEB128(&cie->code_alignment_factor)) {
386 last_error_ = DWARF_ERROR_MEMORY_INVALID;
387 return false;
388 }
389
390 // Data Alignment Factor
391 if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) {
392 last_error_ = DWARF_ERROR_MEMORY_INVALID;
393 return false;
394 }
395
396 if (cie->version == 1) {
397 // Return Address is a single byte.
398 uint8_t return_address_register;
399 if (!memory_.ReadBytes(&return_address_register, 1)) {
400 last_error_ = DWARF_ERROR_MEMORY_INVALID;
401 return false;
402 }
403 cie->return_address_register = return_address_register;
404 } else if (!memory_.ReadULEB128(&cie->return_address_register)) {
405 last_error_ = DWARF_ERROR_MEMORY_INVALID;
406 return false;
407 }
408
409 if (cie->augmentation_string[0] != 'z') {
410 cie->cfa_instructions_offset = memory_.cur_offset();
411 return true;
412 }
413
414 uint64_t aug_length;
415 if (!memory_.ReadULEB128(&aug_length)) {
416 last_error_ = DWARF_ERROR_MEMORY_INVALID;
417 return false;
418 }
419 cie->cfa_instructions_offset = memory_.cur_offset() + aug_length;
420
421 for (size_t i = 1; i < cie->augmentation_string.size(); i++) {
422 switch (cie->augmentation_string[i]) {
423 case 'L':
424 if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) {
425 last_error_ = DWARF_ERROR_MEMORY_INVALID;
426 return false;
427 }
428 break;
429 case 'P': {
430 uint8_t encoding;
431 if (!memory_.ReadBytes(&encoding, 1)) {
432 last_error_ = DWARF_ERROR_MEMORY_INVALID;
433 return false;
434 }
435 if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
436 last_error_ = DWARF_ERROR_MEMORY_INVALID;
437 return false;
438 }
439 } break;
440 case 'R':
441 if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) {
442 last_error_ = DWARF_ERROR_MEMORY_INVALID;
443 return false;
444 }
445 break;
446 }
447 }
448 return true;
449}
450
451template <typename AddressType>
452const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) {
453 auto fde_entry = fde_entries_.find(offset);
454 if (fde_entry != fde_entries_.end()) {
455 return &fde_entry->second;
456 }
457 DwarfFde* fde = &fde_entries_[offset];
458 memory_.set_cur_offset(offset);
459 if (!FillInFde(fde)) {
460 fde_entries_.erase(offset);
461 return nullptr;
462 }
463 return fde;
464}
465
466template <typename AddressType>
467bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
468 uint32_t length32;
469 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
470 last_error_ = DWARF_ERROR_MEMORY_INVALID;
471 return false;
472 }
473
474 if (length32 == static_cast<uint32_t>(-1)) {
475 // 64 bit Fde.
476 uint64_t length64;
477 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
478 last_error_ = DWARF_ERROR_MEMORY_INVALID;
479 return false;
480 }
481 fde->cfa_instructions_end = memory_.cur_offset() + length64;
482
483 uint64_t value64;
484 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
485 last_error_ = DWARF_ERROR_MEMORY_INVALID;
486 return false;
487 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700488 if (value64 == cie64_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700489 // This is a Cie, this means something has gone wrong.
490 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
491 return false;
492 }
493
494 // Get the Cie pointer, which is necessary to properly read the rest of
495 // of the Fde information.
496 fde->cie_offset = GetCieOffsetFromFde64(value64);
497 } else {
498 // 32 bit Fde.
499 fde->cfa_instructions_end = memory_.cur_offset() + length32;
500
501 uint32_t value32;
502 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
503 last_error_ = DWARF_ERROR_MEMORY_INVALID;
504 return false;
505 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700506 if (value32 == cie32_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700507 // This is a Cie, this means something has gone wrong.
508 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
509 return false;
510 }
511
512 // Get the Cie pointer, which is necessary to properly read the rest of
513 // of the Fde information.
514 fde->cie_offset = GetCieOffsetFromFde32(value32);
515 }
516 uint64_t cur_offset = memory_.cur_offset();
517
518 const DwarfCie* cie = GetCie(fde->cie_offset);
519 if (cie == nullptr) {
520 return false;
521 }
522 fde->cie = cie;
523
524 if (cie->segment_size != 0) {
525 // Skip over the segment selector for now.
526 cur_offset += cie->segment_size;
527 }
528 memory_.set_cur_offset(cur_offset);
529
530 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_start)) {
531 last_error_ = DWARF_ERROR_MEMORY_INVALID;
532 return false;
533 }
534 fde->pc_start = AdjustPcFromFde(fde->pc_start);
535
536 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_end)) {
537 last_error_ = DWARF_ERROR_MEMORY_INVALID;
538 return false;
539 }
540 fde->pc_end += fde->pc_start;
541 if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') {
542 // Augmentation Size
543 uint64_t aug_length;
544 if (!memory_.ReadULEB128(&aug_length)) {
545 last_error_ = DWARF_ERROR_MEMORY_INVALID;
546 return false;
547 }
548 uint64_t cur_offset = memory_.cur_offset();
549
550 if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
551 last_error_ = DWARF_ERROR_MEMORY_INVALID;
552 return false;
553 }
554
555 // Set our position to after all of the augmentation data.
556 memory_.set_cur_offset(cur_offset + aug_length);
557 }
558 fde->cfa_instructions_offset = memory_.cur_offset();
559
560 return true;
561}
562
563template <typename AddressType>
564bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
565 dwarf_loc_regs_t* loc_regs) {
566 DwarfCfa<AddressType> cfa(&memory_, fde);
567
568 // Look for the cached copy of the cie data.
569 auto reg_entry = cie_loc_regs_.find(fde->cie_offset);
570 if (reg_entry == cie_loc_regs_.end()) {
571 if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end,
572 loc_regs)) {
573 last_error_ = cfa.last_error();
574 return false;
575 }
576 cie_loc_regs_[fde->cie_offset] = *loc_regs;
577 }
578 cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]);
579 if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) {
580 last_error_ = cfa.last_error();
581 return false;
582 }
583 return true;
584}
585
586template <typename AddressType>
587bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t load_bias,
588 const DwarfFde* fde) {
589 DwarfCfa<AddressType> cfa(&memory_, fde);
590
591 // Always print the cie information.
592 const DwarfCie* cie = fde->cie;
593 if (!cfa.Log(indent, pc, load_bias, cie->cfa_instructions_offset, cie->cfa_instructions_end)) {
594 last_error_ = cfa.last_error();
595 return false;
596 }
597 if (!cfa.Log(indent, pc, load_bias, fde->cfa_instructions_offset, fde->cfa_instructions_end)) {
598 last_error_ = cfa.last_error();
599 return false;
600 }
601 return true;
602}
603
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700604template <typename AddressType>
605bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size) {
606 entries_offset_ = offset;
607 entries_end_ = offset + size;
608
609 memory_.clear_func_offset();
610 memory_.clear_text_offset();
611 memory_.set_data_offset(offset);
612 memory_.set_cur_offset(offset);
613 memory_.set_pc_offset(offset);
614
615 return CreateSortedFdeList();
616}
617
618template <typename AddressType>
619bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) {
620 uint8_t version;
621 if (!memory_.ReadBytes(&version, 1)) {
622 last_error_ = DWARF_ERROR_MEMORY_INVALID;
623 return false;
624 }
625 // Read the augmentation string.
626 std::vector<char> aug_string;
627 char aug_value;
628 bool get_encoding = false;
629 do {
630 if (!memory_.ReadBytes(&aug_value, 1)) {
631 last_error_ = DWARF_ERROR_MEMORY_INVALID;
632 return false;
633 }
634 if (aug_value == 'R') {
635 get_encoding = true;
636 }
637 aug_string.push_back(aug_value);
638 } while (aug_value != '\0');
639
640 if (version == 4) {
641 // Skip the Address Size field.
642 memory_.set_cur_offset(memory_.cur_offset() + 1);
643
644 // Read the segment size.
645 if (!memory_.ReadBytes(segment_size, 1)) {
646 last_error_ = DWARF_ERROR_MEMORY_INVALID;
647 return false;
648 }
649 } else {
650 *segment_size = 0;
651 }
652
653 if (aug_string[0] != 'z' || !get_encoding) {
654 // No encoding
655 return true;
656 }
657
658 // Skip code alignment factor
659 uint8_t value;
660 do {
661 if (!memory_.ReadBytes(&value, 1)) {
662 last_error_ = DWARF_ERROR_MEMORY_INVALID;
663 return false;
664 }
665 } while (value & 0x80);
666
667 // Skip data alignment factor
668 do {
669 if (!memory_.ReadBytes(&value, 1)) {
670 last_error_ = DWARF_ERROR_MEMORY_INVALID;
671 return false;
672 }
673 } while (value & 0x80);
674
675 if (version == 1) {
676 // Skip return address register.
677 memory_.set_cur_offset(memory_.cur_offset() + 1);
678 } else {
679 // Skip return address register.
680 do {
681 if (!memory_.ReadBytes(&value, 1)) {
682 last_error_ = DWARF_ERROR_MEMORY_INVALID;
683 return false;
684 }
685 } while (value & 0x80);
686 }
687
688 // Skip the augmentation length.
689 do {
690 if (!memory_.ReadBytes(&value, 1)) {
691 last_error_ = DWARF_ERROR_MEMORY_INVALID;
692 return false;
693 }
694 } while (value & 0x80);
695
696 for (size_t i = 1; i < aug_string.size(); i++) {
697 if (aug_string[i] == 'R') {
698 if (!memory_.ReadBytes(encoding, 1)) {
699 last_error_ = DWARF_ERROR_MEMORY_INVALID;
700 return false;
701 }
702 // Got the encoding, that's all we are looking for.
703 return true;
704 } else if (aug_string[i] == 'L') {
705 memory_.set_cur_offset(memory_.cur_offset() + 1);
706 } else if (aug_string[i] == 'P') {
707 uint8_t encoding;
708 if (!memory_.ReadBytes(&encoding, 1)) {
709 last_error_ = DWARF_ERROR_MEMORY_INVALID;
710 return false;
711 }
712 uint64_t value;
713 if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) {
714 last_error_ = DWARF_ERROR_MEMORY_INVALID;
715 return false;
716 }
717 }
718 }
719
720 // It should be impossible to get here.
721 abort();
722}
723
724template <typename AddressType>
725bool DwarfSectionImpl<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size,
726 uint8_t encoding) {
727 if (segment_size != 0) {
728 memory_.set_cur_offset(memory_.cur_offset() + 1);
729 }
730
731 uint64_t start;
732 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) {
733 last_error_ = DWARF_ERROR_MEMORY_INVALID;
734 return false;
735 }
736 start = AdjustPcFromFde(start);
737
738 uint64_t length;
739 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) {
740 last_error_ = DWARF_ERROR_MEMORY_INVALID;
741 return false;
742 }
743 if (length != 0) {
744 fdes_.emplace_back(entry_offset, start, length);
745 }
746
747 return true;
748}
749
750template <typename AddressType>
751bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() {
752 memory_.set_cur_offset(entries_offset_);
753
754 // Loop through all of the entries and read just enough to create
755 // a sorted list of pcs.
756 // This code assumes that first comes the cie, then the fdes that
757 // it applies to.
758 uint64_t cie_offset = 0;
759 uint8_t address_encoding;
760 uint8_t segment_size;
761 while (memory_.cur_offset() < entries_end_) {
762 uint64_t cur_entry_offset = memory_.cur_offset();
763
764 // Figure out the entry length and type.
765 uint32_t value32;
766 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
767 last_error_ = DWARF_ERROR_MEMORY_INVALID;
768 return false;
769 }
770
771 uint64_t next_entry_offset;
772 if (value32 == static_cast<uint32_t>(-1)) {
773 uint64_t value64;
774 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
775 last_error_ = DWARF_ERROR_MEMORY_INVALID;
776 return false;
777 }
778 next_entry_offset = memory_.cur_offset() + value64;
779
780 // Read the Cie Id of a Cie or the pointer of the Fde.
781 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
782 last_error_ = DWARF_ERROR_MEMORY_INVALID;
783 return false;
784 }
785
786 if (value64 == cie64_value_) {
787 // Cie 64 bit
788 address_encoding = DW_EH_PE_sdata8;
789 if (!GetCieInfo(&segment_size, &address_encoding)) {
790 return false;
791 }
792 cie_offset = cur_entry_offset;
793 } else {
794 uint64_t last_cie_offset = GetCieOffsetFromFde64(value64);
795 if (last_cie_offset != cie_offset) {
796 // This means that this Fde is not following the Cie.
797 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
798 return false;
799 }
800
801 // Fde 64 bit
802 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
803 return false;
804 }
805 }
806 } else {
807 next_entry_offset = memory_.cur_offset() + value32;
808
809 // Read the Cie Id of a Cie or the pointer of the Fde.
810 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
811 last_error_ = DWARF_ERROR_MEMORY_INVALID;
812 return false;
813 }
814
815 if (value32 == cie32_value_) {
816 // Cie 32 bit
817 address_encoding = DW_EH_PE_sdata4;
818 if (!GetCieInfo(&segment_size, &address_encoding)) {
819 return false;
820 }
821 cie_offset = cur_entry_offset;
822 } else {
823 uint64_t last_cie_offset = GetCieOffsetFromFde32(value32);
824 if (last_cie_offset != cie_offset) {
825 // This means that this Fde is not following the Cie.
826 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
827 return false;
828 }
829
830 // Fde 32 bit
831 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
832 return false;
833 }
834 }
835 }
836
837 if (next_entry_offset < memory_.cur_offset()) {
Christopher Ferris1a141a02018-01-24 08:52:47 -0800838 // Simply consider the processing done in this case.
839 break;
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700840 }
841 memory_.set_cur_offset(next_entry_offset);
842 }
843
844 // Sort the entries.
845 std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) {
846 if (a.start == b.start) return a.end < b.end;
847 return a.start < b.start;
848 });
849
850 fde_count_ = fdes_.size();
851
852 return true;
853}
854
855template <typename AddressType>
856bool DwarfSectionImpl<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
857 if (fde_count_ == 0) {
858 return false;
859 }
860
861 size_t first = 0;
862 size_t last = fde_count_;
863 while (first < last) {
864 size_t current = (first + last) / 2;
865 const FdeInfo* info = &fdes_[current];
866 if (pc >= info->start && pc <= info->end) {
867 *fde_offset = info->offset;
868 return true;
869 }
870
871 if (pc < info->start) {
872 last = current;
873 } else {
874 first = current + 1;
875 }
876 }
877 return false;
878}
879
880template <typename AddressType>
881const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromIndex(size_t index) {
882 if (index >= fdes_.size()) {
883 return nullptr;
884 }
885 return this->GetFdeFromOffset(fdes_[index].offset);
886}
887
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700888// Explicitly instantiate DwarfSectionImpl
889template class DwarfSectionImpl<uint32_t>;
890template class DwarfSectionImpl<uint64_t>;
Christopher Ferrisd226a512017-07-14 10:37:19 -0700891
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700892// Explicitly instantiate DwarfDebugFrame
893template class DwarfDebugFrame<uint32_t>;
894template class DwarfDebugFrame<uint64_t>;
895
896// Explicitly instantiate DwarfEhFrame
897template class DwarfEhFrame<uint32_t>;
898template class DwarfEhFrame<uint64_t>;
899
Christopher Ferrisd226a512017-07-14 10:37:19 -0700900} // namespace unwindstack