blob: 095418726ecb95ccba874c74e8ad89c3d30245a5 [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
37DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {}
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070038
39const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
40 uint64_t fde_offset;
41 if (!GetFdeOffsetFromPc(pc, &fde_offset)) {
42 return nullptr;
43 }
44 const DwarfFde* fde = GetFdeFromOffset(fde_offset);
Christopher Ferris13b86652017-11-05 14:01:43 -080045 if (fde == nullptr) {
46 return nullptr;
47 }
48
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070049 // Guaranteed pc >= pc_start, need to check pc in the fde range.
50 if (pc < fde->pc_end) {
51 return fde;
52 }
53 last_error_ = DWARF_ERROR_ILLEGAL_STATE;
54 return nullptr;
55}
56
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070057bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
Christopher Ferrisd226a512017-07-14 10:37:19 -070058 last_error_ = DWARF_ERROR_NONE;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070059 const DwarfFde* fde = GetFdeFromPc(pc);
60 if (fde == nullptr || fde->cie == nullptr) {
61 last_error_ = DWARF_ERROR_ILLEGAL_STATE;
62 return false;
63 }
64
65 // Now get the location information for this pc.
66 dwarf_loc_regs_t loc_regs;
67 if (!GetCfaLocationInfo(pc, fde, &loc_regs)) {
68 return false;
69 }
70
71 // Now eval the actual registers.
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070072 return Eval(fde->cie, process_memory, loc_regs, regs, finished);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070073}
74
75template <typename AddressType>
76bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uint8_t version,
77 Memory* regular_memory, AddressType* value) {
78 DwarfOp<AddressType> op(&memory_, regular_memory);
79
80 // Need to evaluate the op data.
81 uint64_t start = loc.values[1];
82 uint64_t end = start + loc.values[0];
83 if (!op.Eval(start, end, version)) {
84 last_error_ = op.last_error();
85 return false;
86 }
87 if (op.StackSize() == 0) {
88 last_error_ = DWARF_ERROR_ILLEGAL_STATE;
89 return false;
90 }
91 // We don't support an expression that evaluates to a register number.
92 if (op.is_register()) {
93 last_error_ = DWARF_ERROR_NOT_IMPLEMENTED;
94 return false;
95 }
96 *value = op.StackAt(0);
97 return true;
98}
99
100template <typename AddressType>
101bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700102 const dwarf_loc_regs_t& loc_regs, Regs* regs,
103 bool* finished) {
Christopher Ferris7b8e4672017-06-01 17:55:25 -0700104 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700105 if (cie->return_address_register >= cur_regs->total_regs()) {
106 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
107 return false;
108 }
109
110 // Get the cfa value;
111 auto cfa_entry = loc_regs.find(CFA_REG);
112 if (cfa_entry == loc_regs.end()) {
113 last_error_ = DWARF_ERROR_CFA_NOT_DEFINED;
114 return false;
115 }
116
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700117 AddressType prev_cfa = regs->sp();
118
119 AddressType cfa;
120 const DwarfLocation* loc = &cfa_entry->second;
121 // Only a few location types are valid for the cfa.
122 switch (loc->type) {
123 case DWARF_LOCATION_REGISTER:
124 if (loc->values[0] >= cur_regs->total_regs()) {
125 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
126 return false;
127 }
128 // If the stack pointer register is the CFA, and the stack
129 // pointer register does not have any associated location
130 // information, use the current cfa value.
131 if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) {
132 cfa = prev_cfa;
133 } else {
134 cfa = (*cur_regs)[loc->values[0]];
135 }
136 cfa += loc->values[1];
137 break;
138 case DWARF_LOCATION_EXPRESSION:
139 case DWARF_LOCATION_VAL_EXPRESSION: {
140 AddressType value;
141 if (!EvalExpression(*loc, cie->version, regular_memory, &value)) {
142 return false;
143 }
144 if (loc->type == DWARF_LOCATION_EXPRESSION) {
Josh Gaoef35aa52017-10-18 11:44:51 -0700145 if (!regular_memory->ReadFully(value, &cfa, sizeof(AddressType))) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700146 last_error_ = DWARF_ERROR_MEMORY_INVALID;
147 return false;
148 }
149 } else {
150 cfa = value;
151 }
152 break;
153 }
154 default:
155 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
156 return false;
157 }
158
159 // This code is not guaranteed to work in cases where a register location
160 // is a double indirection to the actual value. For example, if r3 is set
161 // to r5 + 4, and r5 is set to CFA + 4, then this won't necessarily work
162 // because it does not guarantee that r5 is evaluated before r3.
163 // Check that this case does not exist, and error if it does.
164 bool return_address_undefined = false;
165 for (const auto& entry : loc_regs) {
166 uint16_t reg = entry.first;
167 // Already handled the CFA register.
168 if (reg == CFA_REG) continue;
169
170 if (reg >= cur_regs->total_regs()) {
171 // Skip this unknown register.
172 continue;
173 }
174
175 const DwarfLocation* loc = &entry.second;
176 switch (loc->type) {
177 case DWARF_LOCATION_OFFSET:
Josh Gaoef35aa52017-10-18 11:44:51 -0700178 if (!regular_memory->ReadFully(cfa + loc->values[0], &(*cur_regs)[reg],
179 sizeof(AddressType))) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700180 last_error_ = DWARF_ERROR_MEMORY_INVALID;
181 return false;
182 }
183 break;
184 case DWARF_LOCATION_VAL_OFFSET:
185 (*cur_regs)[reg] = cfa + loc->values[0];
186 break;
187 case DWARF_LOCATION_REGISTER: {
188 uint16_t cur_reg = loc->values[0];
189 if (cur_reg >= cur_regs->total_regs()) {
190 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
191 return false;
192 }
193 if (loc_regs.find(cur_reg) != loc_regs.end()) {
194 // This is a double indirection, a register definition references
195 // another register which is also defined as something other
196 // than a register.
197 log(0,
198 "Invalid indirection: register %d references register %d which is "
199 "not a plain register.\n",
200 reg, cur_reg);
201 last_error_ = DWARF_ERROR_ILLEGAL_STATE;
202 return false;
203 }
204 (*cur_regs)[reg] = (*cur_regs)[cur_reg] + loc->values[1];
205 break;
206 }
207 case DWARF_LOCATION_EXPRESSION:
208 case DWARF_LOCATION_VAL_EXPRESSION: {
209 AddressType value;
210 if (!EvalExpression(*loc, cie->version, regular_memory, &value)) {
211 return false;
212 }
213 if (loc->type == DWARF_LOCATION_EXPRESSION) {
Josh Gaoef35aa52017-10-18 11:44:51 -0700214 if (!regular_memory->ReadFully(value, &(*cur_regs)[reg], sizeof(AddressType))) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700215 last_error_ = DWARF_ERROR_MEMORY_INVALID;
216 return false;
217 }
218 } else {
219 (*cur_regs)[reg] = value;
220 }
221 break;
222 }
223 case DWARF_LOCATION_UNDEFINED:
224 if (reg == cie->return_address_register) {
225 return_address_undefined = true;
226 }
227 default:
228 break;
229 }
230 }
231
232 // Find the return address location.
233 if (return_address_undefined) {
234 cur_regs->set_pc(0);
235 } else {
236 cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
237 }
Christopher Ferris2502a602017-10-23 13:51:54 -0700238
239 // If the pc was set to zero, consider this the final frame.
240 *finished = (cur_regs->pc() == 0) ? true : false;
241
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700242 cur_regs->set_sp(cfa);
Christopher Ferrisfda7edd2017-10-31 16:10:42 -0700243
244 return true;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700245}
246
247template <typename AddressType>
248const DwarfCie* DwarfSectionImpl<AddressType>::GetCie(uint64_t offset) {
249 auto cie_entry = cie_entries_.find(offset);
250 if (cie_entry != cie_entries_.end()) {
251 return &cie_entry->second;
252 }
253 DwarfCie* cie = &cie_entries_[offset];
254 memory_.set_cur_offset(offset);
255 if (!FillInCie(cie)) {
256 // Erase the cached entry.
257 cie_entries_.erase(offset);
258 return nullptr;
259 }
260 return cie;
261}
262
263template <typename AddressType>
264bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
265 uint32_t length32;
266 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
267 last_error_ = DWARF_ERROR_MEMORY_INVALID;
268 return false;
269 }
Christopher Ferrisd226a512017-07-14 10:37:19 -0700270 // Set the default for the lsda encoding.
271 cie->lsda_encoding = DW_EH_PE_omit;
272
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700273 if (length32 == static_cast<uint32_t>(-1)) {
274 // 64 bit Cie
275 uint64_t length64;
276 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
277 last_error_ = DWARF_ERROR_MEMORY_INVALID;
278 return false;
279 }
280
281 cie->cfa_instructions_end = memory_.cur_offset() + length64;
282 cie->fde_address_encoding = DW_EH_PE_sdata8;
283
284 uint64_t cie_id;
285 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
286 last_error_ = DWARF_ERROR_MEMORY_INVALID;
287 return false;
288 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700289 if (cie_id != cie64_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700290 // This is not a Cie, something has gone horribly wrong.
291 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
292 return false;
293 }
294 } else {
295 // 32 bit Cie
296 cie->cfa_instructions_end = memory_.cur_offset() + length32;
297 cie->fde_address_encoding = DW_EH_PE_sdata4;
298
299 uint32_t cie_id;
300 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
301 last_error_ = DWARF_ERROR_MEMORY_INVALID;
302 return false;
303 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700304 if (cie_id != cie32_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700305 // This is not a Cie, something has gone horribly wrong.
306 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
307 return false;
308 }
309 }
310
311 if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
312 last_error_ = DWARF_ERROR_MEMORY_INVALID;
313 return false;
314 }
315
316 if (cie->version != 1 && cie->version != 3 && cie->version != 4) {
317 // Unrecognized version.
318 last_error_ = DWARF_ERROR_UNSUPPORTED_VERSION;
319 return false;
320 }
321
322 // Read the augmentation string.
323 char aug_value;
324 do {
325 if (!memory_.ReadBytes(&aug_value, 1)) {
326 last_error_ = DWARF_ERROR_MEMORY_INVALID;
327 return false;
328 }
329 cie->augmentation_string.push_back(aug_value);
330 } while (aug_value != '\0');
331
332 if (cie->version == 4) {
333 // Skip the Address Size field since we only use it for validation.
334 memory_.set_cur_offset(memory_.cur_offset() + 1);
335
336 // Segment Size
337 if (!memory_.ReadBytes(&cie->segment_size, 1)) {
338 last_error_ = DWARF_ERROR_MEMORY_INVALID;
339 return false;
340 }
341 }
342
343 // Code Alignment Factor
344 if (!memory_.ReadULEB128(&cie->code_alignment_factor)) {
345 last_error_ = DWARF_ERROR_MEMORY_INVALID;
346 return false;
347 }
348
349 // Data Alignment Factor
350 if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) {
351 last_error_ = DWARF_ERROR_MEMORY_INVALID;
352 return false;
353 }
354
355 if (cie->version == 1) {
356 // Return Address is a single byte.
357 uint8_t return_address_register;
358 if (!memory_.ReadBytes(&return_address_register, 1)) {
359 last_error_ = DWARF_ERROR_MEMORY_INVALID;
360 return false;
361 }
362 cie->return_address_register = return_address_register;
363 } else if (!memory_.ReadULEB128(&cie->return_address_register)) {
364 last_error_ = DWARF_ERROR_MEMORY_INVALID;
365 return false;
366 }
367
368 if (cie->augmentation_string[0] != 'z') {
369 cie->cfa_instructions_offset = memory_.cur_offset();
370 return true;
371 }
372
373 uint64_t aug_length;
374 if (!memory_.ReadULEB128(&aug_length)) {
375 last_error_ = DWARF_ERROR_MEMORY_INVALID;
376 return false;
377 }
378 cie->cfa_instructions_offset = memory_.cur_offset() + aug_length;
379
380 for (size_t i = 1; i < cie->augmentation_string.size(); i++) {
381 switch (cie->augmentation_string[i]) {
382 case 'L':
383 if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) {
384 last_error_ = DWARF_ERROR_MEMORY_INVALID;
385 return false;
386 }
387 break;
388 case 'P': {
389 uint8_t encoding;
390 if (!memory_.ReadBytes(&encoding, 1)) {
391 last_error_ = DWARF_ERROR_MEMORY_INVALID;
392 return false;
393 }
394 if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
395 last_error_ = DWARF_ERROR_MEMORY_INVALID;
396 return false;
397 }
398 } break;
399 case 'R':
400 if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) {
401 last_error_ = DWARF_ERROR_MEMORY_INVALID;
402 return false;
403 }
404 break;
405 }
406 }
407 return true;
408}
409
410template <typename AddressType>
411const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) {
412 auto fde_entry = fde_entries_.find(offset);
413 if (fde_entry != fde_entries_.end()) {
414 return &fde_entry->second;
415 }
416 DwarfFde* fde = &fde_entries_[offset];
417 memory_.set_cur_offset(offset);
418 if (!FillInFde(fde)) {
419 fde_entries_.erase(offset);
420 return nullptr;
421 }
422 return fde;
423}
424
425template <typename AddressType>
426bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
427 uint32_t length32;
428 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
429 last_error_ = DWARF_ERROR_MEMORY_INVALID;
430 return false;
431 }
432
433 if (length32 == static_cast<uint32_t>(-1)) {
434 // 64 bit Fde.
435 uint64_t length64;
436 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
437 last_error_ = DWARF_ERROR_MEMORY_INVALID;
438 return false;
439 }
440 fde->cfa_instructions_end = memory_.cur_offset() + length64;
441
442 uint64_t value64;
443 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
444 last_error_ = DWARF_ERROR_MEMORY_INVALID;
445 return false;
446 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700447 if (value64 == cie64_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700448 // This is a Cie, this means something has gone wrong.
449 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
450 return false;
451 }
452
453 // Get the Cie pointer, which is necessary to properly read the rest of
454 // of the Fde information.
455 fde->cie_offset = GetCieOffsetFromFde64(value64);
456 } else {
457 // 32 bit Fde.
458 fde->cfa_instructions_end = memory_.cur_offset() + length32;
459
460 uint32_t value32;
461 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
462 last_error_ = DWARF_ERROR_MEMORY_INVALID;
463 return false;
464 }
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700465 if (value32 == cie32_value_) {
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700466 // This is a Cie, this means something has gone wrong.
467 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
468 return false;
469 }
470
471 // Get the Cie pointer, which is necessary to properly read the rest of
472 // of the Fde information.
473 fde->cie_offset = GetCieOffsetFromFde32(value32);
474 }
475 uint64_t cur_offset = memory_.cur_offset();
476
477 const DwarfCie* cie = GetCie(fde->cie_offset);
478 if (cie == nullptr) {
479 return false;
480 }
481 fde->cie = cie;
482
483 if (cie->segment_size != 0) {
484 // Skip over the segment selector for now.
485 cur_offset += cie->segment_size;
486 }
487 memory_.set_cur_offset(cur_offset);
488
489 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_start)) {
490 last_error_ = DWARF_ERROR_MEMORY_INVALID;
491 return false;
492 }
493 fde->pc_start = AdjustPcFromFde(fde->pc_start);
494
495 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_end)) {
496 last_error_ = DWARF_ERROR_MEMORY_INVALID;
497 return false;
498 }
499 fde->pc_end += fde->pc_start;
500 if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') {
501 // Augmentation Size
502 uint64_t aug_length;
503 if (!memory_.ReadULEB128(&aug_length)) {
504 last_error_ = DWARF_ERROR_MEMORY_INVALID;
505 return false;
506 }
507 uint64_t cur_offset = memory_.cur_offset();
508
509 if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
510 last_error_ = DWARF_ERROR_MEMORY_INVALID;
511 return false;
512 }
513
514 // Set our position to after all of the augmentation data.
515 memory_.set_cur_offset(cur_offset + aug_length);
516 }
517 fde->cfa_instructions_offset = memory_.cur_offset();
518
519 return true;
520}
521
522template <typename AddressType>
523bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
524 dwarf_loc_regs_t* loc_regs) {
525 DwarfCfa<AddressType> cfa(&memory_, fde);
526
527 // Look for the cached copy of the cie data.
528 auto reg_entry = cie_loc_regs_.find(fde->cie_offset);
529 if (reg_entry == cie_loc_regs_.end()) {
530 if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end,
531 loc_regs)) {
532 last_error_ = cfa.last_error();
533 return false;
534 }
535 cie_loc_regs_[fde->cie_offset] = *loc_regs;
536 }
537 cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]);
538 if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) {
539 last_error_ = cfa.last_error();
540 return false;
541 }
542 return true;
543}
544
545template <typename AddressType>
546bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t load_bias,
547 const DwarfFde* fde) {
548 DwarfCfa<AddressType> cfa(&memory_, fde);
549
550 // Always print the cie information.
551 const DwarfCie* cie = fde->cie;
552 if (!cfa.Log(indent, pc, load_bias, cie->cfa_instructions_offset, cie->cfa_instructions_end)) {
553 last_error_ = cfa.last_error();
554 return false;
555 }
556 if (!cfa.Log(indent, pc, load_bias, fde->cfa_instructions_offset, fde->cfa_instructions_end)) {
557 last_error_ = cfa.last_error();
558 return false;
559 }
560 return true;
561}
562
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700563template <typename AddressType>
564bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size) {
565 entries_offset_ = offset;
566 entries_end_ = offset + size;
567
568 memory_.clear_func_offset();
569 memory_.clear_text_offset();
570 memory_.set_data_offset(offset);
571 memory_.set_cur_offset(offset);
572 memory_.set_pc_offset(offset);
573
574 return CreateSortedFdeList();
575}
576
577template <typename AddressType>
578bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) {
579 uint8_t version;
580 if (!memory_.ReadBytes(&version, 1)) {
581 last_error_ = DWARF_ERROR_MEMORY_INVALID;
582 return false;
583 }
584 // Read the augmentation string.
585 std::vector<char> aug_string;
586 char aug_value;
587 bool get_encoding = false;
588 do {
589 if (!memory_.ReadBytes(&aug_value, 1)) {
590 last_error_ = DWARF_ERROR_MEMORY_INVALID;
591 return false;
592 }
593 if (aug_value == 'R') {
594 get_encoding = true;
595 }
596 aug_string.push_back(aug_value);
597 } while (aug_value != '\0');
598
599 if (version == 4) {
600 // Skip the Address Size field.
601 memory_.set_cur_offset(memory_.cur_offset() + 1);
602
603 // Read the segment size.
604 if (!memory_.ReadBytes(segment_size, 1)) {
605 last_error_ = DWARF_ERROR_MEMORY_INVALID;
606 return false;
607 }
608 } else {
609 *segment_size = 0;
610 }
611
612 if (aug_string[0] != 'z' || !get_encoding) {
613 // No encoding
614 return true;
615 }
616
617 // Skip code alignment factor
618 uint8_t value;
619 do {
620 if (!memory_.ReadBytes(&value, 1)) {
621 last_error_ = DWARF_ERROR_MEMORY_INVALID;
622 return false;
623 }
624 } while (value & 0x80);
625
626 // Skip data alignment factor
627 do {
628 if (!memory_.ReadBytes(&value, 1)) {
629 last_error_ = DWARF_ERROR_MEMORY_INVALID;
630 return false;
631 }
632 } while (value & 0x80);
633
634 if (version == 1) {
635 // Skip return address register.
636 memory_.set_cur_offset(memory_.cur_offset() + 1);
637 } else {
638 // Skip return address register.
639 do {
640 if (!memory_.ReadBytes(&value, 1)) {
641 last_error_ = DWARF_ERROR_MEMORY_INVALID;
642 return false;
643 }
644 } while (value & 0x80);
645 }
646
647 // Skip the augmentation length.
648 do {
649 if (!memory_.ReadBytes(&value, 1)) {
650 last_error_ = DWARF_ERROR_MEMORY_INVALID;
651 return false;
652 }
653 } while (value & 0x80);
654
655 for (size_t i = 1; i < aug_string.size(); i++) {
656 if (aug_string[i] == 'R') {
657 if (!memory_.ReadBytes(encoding, 1)) {
658 last_error_ = DWARF_ERROR_MEMORY_INVALID;
659 return false;
660 }
661 // Got the encoding, that's all we are looking for.
662 return true;
663 } else if (aug_string[i] == 'L') {
664 memory_.set_cur_offset(memory_.cur_offset() + 1);
665 } else if (aug_string[i] == 'P') {
666 uint8_t encoding;
667 if (!memory_.ReadBytes(&encoding, 1)) {
668 last_error_ = DWARF_ERROR_MEMORY_INVALID;
669 return false;
670 }
671 uint64_t value;
672 if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) {
673 last_error_ = DWARF_ERROR_MEMORY_INVALID;
674 return false;
675 }
676 }
677 }
678
679 // It should be impossible to get here.
680 abort();
681}
682
683template <typename AddressType>
684bool DwarfSectionImpl<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size,
685 uint8_t encoding) {
686 if (segment_size != 0) {
687 memory_.set_cur_offset(memory_.cur_offset() + 1);
688 }
689
690 uint64_t start;
691 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) {
692 last_error_ = DWARF_ERROR_MEMORY_INVALID;
693 return false;
694 }
695 start = AdjustPcFromFde(start);
696
697 uint64_t length;
698 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) {
699 last_error_ = DWARF_ERROR_MEMORY_INVALID;
700 return false;
701 }
702 if (length != 0) {
703 fdes_.emplace_back(entry_offset, start, length);
704 }
705
706 return true;
707}
708
709template <typename AddressType>
710bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() {
711 memory_.set_cur_offset(entries_offset_);
712
713 // Loop through all of the entries and read just enough to create
714 // a sorted list of pcs.
715 // This code assumes that first comes the cie, then the fdes that
716 // it applies to.
717 uint64_t cie_offset = 0;
718 uint8_t address_encoding;
719 uint8_t segment_size;
720 while (memory_.cur_offset() < entries_end_) {
721 uint64_t cur_entry_offset = memory_.cur_offset();
722
723 // Figure out the entry length and type.
724 uint32_t value32;
725 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
726 last_error_ = DWARF_ERROR_MEMORY_INVALID;
727 return false;
728 }
729
730 uint64_t next_entry_offset;
731 if (value32 == static_cast<uint32_t>(-1)) {
732 uint64_t value64;
733 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
734 last_error_ = DWARF_ERROR_MEMORY_INVALID;
735 return false;
736 }
737 next_entry_offset = memory_.cur_offset() + value64;
738
739 // Read the Cie Id of a Cie or the pointer of the Fde.
740 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
741 last_error_ = DWARF_ERROR_MEMORY_INVALID;
742 return false;
743 }
744
745 if (value64 == cie64_value_) {
746 // Cie 64 bit
747 address_encoding = DW_EH_PE_sdata8;
748 if (!GetCieInfo(&segment_size, &address_encoding)) {
749 return false;
750 }
751 cie_offset = cur_entry_offset;
752 } else {
753 uint64_t last_cie_offset = GetCieOffsetFromFde64(value64);
754 if (last_cie_offset != cie_offset) {
755 // This means that this Fde is not following the Cie.
756 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
757 return false;
758 }
759
760 // Fde 64 bit
761 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
762 return false;
763 }
764 }
765 } else {
766 next_entry_offset = memory_.cur_offset() + value32;
767
768 // Read the Cie Id of a Cie or the pointer of the Fde.
769 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
770 last_error_ = DWARF_ERROR_MEMORY_INVALID;
771 return false;
772 }
773
774 if (value32 == cie32_value_) {
775 // Cie 32 bit
776 address_encoding = DW_EH_PE_sdata4;
777 if (!GetCieInfo(&segment_size, &address_encoding)) {
778 return false;
779 }
780 cie_offset = cur_entry_offset;
781 } else {
782 uint64_t last_cie_offset = GetCieOffsetFromFde32(value32);
783 if (last_cie_offset != cie_offset) {
784 // This means that this Fde is not following the Cie.
785 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
786 return false;
787 }
788
789 // Fde 32 bit
790 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
791 return false;
792 }
793 }
794 }
795
796 if (next_entry_offset < memory_.cur_offset()) {
797 // This indicates some kind of corruption, or malformed section data.
798 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
799 return false;
800 }
801 memory_.set_cur_offset(next_entry_offset);
802 }
803
804 // Sort the entries.
805 std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) {
806 if (a.start == b.start) return a.end < b.end;
807 return a.start < b.start;
808 });
809
810 fde_count_ = fdes_.size();
811
812 return true;
813}
814
815template <typename AddressType>
816bool DwarfSectionImpl<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
817 if (fde_count_ == 0) {
818 return false;
819 }
820
821 size_t first = 0;
822 size_t last = fde_count_;
823 while (first < last) {
824 size_t current = (first + last) / 2;
825 const FdeInfo* info = &fdes_[current];
826 if (pc >= info->start && pc <= info->end) {
827 *fde_offset = info->offset;
828 return true;
829 }
830
831 if (pc < info->start) {
832 last = current;
833 } else {
834 first = current + 1;
835 }
836 }
837 return false;
838}
839
840template <typename AddressType>
841const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromIndex(size_t index) {
842 if (index >= fdes_.size()) {
843 return nullptr;
844 }
845 return this->GetFdeFromOffset(fdes_[index].offset);
846}
847
Christopher Ferris53a3c9b2017-05-10 18:34:15 -0700848// Explicitly instantiate DwarfSectionImpl
849template class DwarfSectionImpl<uint32_t>;
850template class DwarfSectionImpl<uint64_t>;
Christopher Ferrisd226a512017-07-14 10:37:19 -0700851
Christopher Ferrisc9dee842017-11-03 14:50:27 -0700852// Explicitly instantiate DwarfDebugFrame
853template class DwarfDebugFrame<uint32_t>;
854template class DwarfDebugFrame<uint64_t>;
855
856// Explicitly instantiate DwarfEhFrame
857template class DwarfEhFrame<uint32_t>;
858template class DwarfEhFrame<uint64_t>;
859
Christopher Ferrisd226a512017-07-14 10:37:19 -0700860} // namespace unwindstack