• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdint.h>
18 
19 #include <unwindstack/DwarfError.h>
20 #include <unwindstack/DwarfLocation.h>
21 #include <unwindstack/DwarfMemory.h>
22 #include <unwindstack/DwarfSection.h>
23 #include <unwindstack/DwarfStructs.h>
24 #include <unwindstack/Log.h>
25 #include <unwindstack/Memory.h>
26 #include <unwindstack/Regs.h>
27 
28 #include "DwarfCfa.h"
29 #include "DwarfDebugFrame.h"
30 #include "DwarfEhFrame.h"
31 #include "DwarfEncoding.h"
32 #include "DwarfOp.h"
33 #include "RegsInfo.h"
34 
35 namespace unwindstack {
36 
DwarfSection(Memory * memory)37 DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {}
38 
GetFdeFromPc(uint64_t pc)39 const 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);
45   if (fde == nullptr) {
46     return nullptr;
47   }
48 
49   // 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_.code = DWARF_ERROR_ILLEGAL_STATE;
54   return nullptr;
55 }
56 
Step(uint64_t pc,Regs * regs,Memory * process_memory,bool * finished)57 bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
58   // Lookup the pc in the cache.
59   auto it = loc_regs_.upper_bound(pc);
60   if (it == loc_regs_.end() || pc < it->second.pc_start) {
61     last_error_.code = DWARF_ERROR_NONE;
62     const DwarfFde* fde = GetFdeFromPc(pc);
63     if (fde == nullptr || fde->cie == nullptr) {
64       last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
65       return false;
66     }
67 
68     // Now get the location information for this pc.
69     dwarf_loc_regs_t loc_regs;
70     if (!GetCfaLocationInfo(pc, fde, &loc_regs)) {
71       return false;
72     }
73     loc_regs.cie = fde->cie;
74 
75     // Store it in the cache.
76     it = loc_regs_.emplace(loc_regs.pc_end, std::move(loc_regs)).first;
77   }
78 
79   // Now eval the actual registers.
80   return Eval(it->second.cie, process_memory, it->second, regs, finished);
81 }
82 
83 template <typename AddressType>
EvalExpression(const DwarfLocation & loc,Memory * regular_memory,AddressType * value,RegsInfo<AddressType> * regs_info,bool * is_dex_pc)84 bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, Memory* regular_memory,
85                                                    AddressType* value,
86                                                    RegsInfo<AddressType>* regs_info,
87                                                    bool* is_dex_pc) {
88   DwarfOp<AddressType> op(&memory_, regular_memory);
89   op.set_regs_info(regs_info);
90 
91   // Need to evaluate the op data.
92   uint64_t end = loc.values[1];
93   uint64_t start = end - loc.values[0];
94   if (!op.Eval(start, end)) {
95     last_error_ = op.last_error();
96     return false;
97   }
98   if (op.StackSize() == 0) {
99     last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
100     return false;
101   }
102   // We don't support an expression that evaluates to a register number.
103   if (op.is_register()) {
104     last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
105     return false;
106   }
107   *value = op.StackAt(0);
108   if (is_dex_pc != nullptr && op.dex_pc_set()) {
109     *is_dex_pc = true;
110   }
111   return true;
112 }
113 
114 template <typename AddressType>
115 struct EvalInfo {
116   const dwarf_loc_regs_t* loc_regs;
117   const DwarfCie* cie;
118   Memory* regular_memory;
119   AddressType cfa;
120   bool return_address_undefined = false;
121   RegsInfo<AddressType> regs_info;
122 };
123 
124 template <typename AddressType>
EvalRegister(const DwarfLocation * loc,uint32_t reg,AddressType * reg_ptr,void * info)125 bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg,
126                                                  AddressType* reg_ptr, void* info) {
127   EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info);
128   Memory* regular_memory = eval_info->regular_memory;
129   switch (loc->type) {
130     case DWARF_LOCATION_OFFSET:
131       if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) {
132         last_error_.code = DWARF_ERROR_MEMORY_INVALID;
133         last_error_.address = eval_info->cfa + loc->values[0];
134         return false;
135       }
136       break;
137     case DWARF_LOCATION_VAL_OFFSET:
138       *reg_ptr = eval_info->cfa + loc->values[0];
139       break;
140     case DWARF_LOCATION_REGISTER: {
141       uint32_t cur_reg = loc->values[0];
142       if (cur_reg >= eval_info->regs_info.Total()) {
143         last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
144         return false;
145       }
146       *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1];
147       break;
148     }
149     case DWARF_LOCATION_EXPRESSION:
150     case DWARF_LOCATION_VAL_EXPRESSION: {
151       AddressType value;
152       bool is_dex_pc = false;
153       if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) {
154         return false;
155       }
156       if (loc->type == DWARF_LOCATION_EXPRESSION) {
157         if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) {
158           last_error_.code = DWARF_ERROR_MEMORY_INVALID;
159           last_error_.address = value;
160           return false;
161         }
162       } else {
163         *reg_ptr = value;
164         if (is_dex_pc) {
165           eval_info->regs_info.regs->set_dex_pc(value);
166         }
167       }
168       break;
169     }
170     case DWARF_LOCATION_UNDEFINED:
171       if (reg == eval_info->cie->return_address_register) {
172         eval_info->return_address_undefined = true;
173       }
174     default:
175       break;
176   }
177 
178   return true;
179 }
180 
181 template <typename AddressType>
Eval(const DwarfCie * cie,Memory * regular_memory,const dwarf_loc_regs_t & loc_regs,Regs * regs,bool * finished)182 bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
183                                          const dwarf_loc_regs_t& loc_regs, Regs* regs,
184                                          bool* finished) {
185   RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
186   if (cie->return_address_register >= cur_regs->total_regs()) {
187     last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
188     return false;
189   }
190 
191   // Get the cfa value;
192   auto cfa_entry = loc_regs.find(CFA_REG);
193   if (cfa_entry == loc_regs.end()) {
194     last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED;
195     return false;
196   }
197 
198   // Always set the dex pc to zero when evaluating.
199   cur_regs->set_dex_pc(0);
200 
201   EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
202                                   .cie = cie,
203                                   .regular_memory = regular_memory,
204                                   .regs_info = RegsInfo<AddressType>(cur_regs)};
205   const DwarfLocation* loc = &cfa_entry->second;
206   // Only a few location types are valid for the cfa.
207   switch (loc->type) {
208     case DWARF_LOCATION_REGISTER:
209       if (loc->values[0] >= cur_regs->total_regs()) {
210         last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
211         return false;
212       }
213       eval_info.cfa = (*cur_regs)[loc->values[0]];
214       eval_info.cfa += loc->values[1];
215       break;
216     case DWARF_LOCATION_VAL_EXPRESSION: {
217       AddressType value;
218       if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) {
219         return false;
220       }
221       // There is only one type of valid expression for CFA evaluation.
222       eval_info.cfa = value;
223       break;
224     }
225     default:
226       last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
227       return false;
228   }
229 
230   for (const auto& entry : loc_regs) {
231     uint32_t reg = entry.first;
232     // Already handled the CFA register.
233     if (reg == CFA_REG) continue;
234 
235     AddressType* reg_ptr;
236     if (reg >= cur_regs->total_regs()) {
237       // Skip this unknown register.
238       continue;
239     }
240 
241     reg_ptr = eval_info.regs_info.Save(reg);
242     if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
243       return false;
244     }
245   }
246 
247   // Find the return address location.
248   if (eval_info.return_address_undefined) {
249     cur_regs->set_pc(0);
250   } else {
251     cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
252   }
253 
254   // If the pc was set to zero, consider this the final frame.
255   *finished = (cur_regs->pc() == 0) ? true : false;
256 
257   cur_regs->set_sp(eval_info.cfa);
258 
259   return true;
260 }
261 
262 template <typename AddressType>
GetCie(uint64_t offset)263 const DwarfCie* DwarfSectionImpl<AddressType>::GetCie(uint64_t offset) {
264   auto cie_entry = cie_entries_.find(offset);
265   if (cie_entry != cie_entries_.end()) {
266     return &cie_entry->second;
267   }
268   DwarfCie* cie = &cie_entries_[offset];
269   memory_.set_cur_offset(offset);
270   if (!FillInCie(cie)) {
271     // Erase the cached entry.
272     cie_entries_.erase(offset);
273     return nullptr;
274   }
275   return cie;
276 }
277 
278 template <typename AddressType>
FillInCie(DwarfCie * cie)279 bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
280   uint32_t length32;
281   if (!memory_.ReadBytes(&length32, sizeof(length32))) {
282     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
283     last_error_.address = memory_.cur_offset();
284     return false;
285   }
286   // Set the default for the lsda encoding.
287   cie->lsda_encoding = DW_EH_PE_omit;
288 
289   if (length32 == static_cast<uint32_t>(-1)) {
290     // 64 bit Cie
291     uint64_t length64;
292     if (!memory_.ReadBytes(&length64, sizeof(length64))) {
293       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
294       last_error_.address = memory_.cur_offset();
295       return false;
296     }
297 
298     cie->cfa_instructions_end = memory_.cur_offset() + length64;
299     cie->fde_address_encoding = DW_EH_PE_sdata8;
300 
301     uint64_t cie_id;
302     if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
303       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
304       last_error_.address = memory_.cur_offset();
305       return false;
306     }
307     if (cie_id != cie64_value_) {
308       // This is not a Cie, something has gone horribly wrong.
309       last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
310       return false;
311     }
312   } else {
313     // 32 bit Cie
314     cie->cfa_instructions_end = memory_.cur_offset() + length32;
315     cie->fde_address_encoding = DW_EH_PE_sdata4;
316 
317     uint32_t cie_id;
318     if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
319       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
320       last_error_.address = memory_.cur_offset();
321       return false;
322     }
323     if (cie_id != cie32_value_) {
324       // This is not a Cie, something has gone horribly wrong.
325       last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
326       return false;
327     }
328   }
329 
330   if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
331     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
332     last_error_.address = memory_.cur_offset();
333     return false;
334   }
335 
336   if (cie->version != 1 && cie->version != 3 && cie->version != 4) {
337     // Unrecognized version.
338     last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION;
339     return false;
340   }
341 
342   // Read the augmentation string.
343   char aug_value;
344   do {
345     if (!memory_.ReadBytes(&aug_value, 1)) {
346       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
347       last_error_.address = memory_.cur_offset();
348       return false;
349     }
350     cie->augmentation_string.push_back(aug_value);
351   } while (aug_value != '\0');
352 
353   if (cie->version == 4) {
354     // Skip the Address Size field since we only use it for validation.
355     memory_.set_cur_offset(memory_.cur_offset() + 1);
356 
357     // Segment Size
358     if (!memory_.ReadBytes(&cie->segment_size, 1)) {
359       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
360       last_error_.address = memory_.cur_offset();
361       return false;
362     }
363   }
364 
365   // Code Alignment Factor
366   if (!memory_.ReadULEB128(&cie->code_alignment_factor)) {
367     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
368     last_error_.address = memory_.cur_offset();
369     return false;
370   }
371 
372   // Data Alignment Factor
373   if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) {
374     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
375     last_error_.address = memory_.cur_offset();
376     return false;
377   }
378 
379   if (cie->version == 1) {
380     // Return Address is a single byte.
381     uint8_t return_address_register;
382     if (!memory_.ReadBytes(&return_address_register, 1)) {
383       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
384       last_error_.address = memory_.cur_offset();
385       return false;
386     }
387     cie->return_address_register = return_address_register;
388   } else if (!memory_.ReadULEB128(&cie->return_address_register)) {
389     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
390     last_error_.address = memory_.cur_offset();
391     return false;
392   }
393 
394   if (cie->augmentation_string[0] != 'z') {
395     cie->cfa_instructions_offset = memory_.cur_offset();
396     return true;
397   }
398 
399   uint64_t aug_length;
400   if (!memory_.ReadULEB128(&aug_length)) {
401     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
402     last_error_.address = memory_.cur_offset();
403     return false;
404   }
405   cie->cfa_instructions_offset = memory_.cur_offset() + aug_length;
406 
407   for (size_t i = 1; i < cie->augmentation_string.size(); i++) {
408     switch (cie->augmentation_string[i]) {
409       case 'L':
410         if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) {
411           last_error_.code = DWARF_ERROR_MEMORY_INVALID;
412           last_error_.address = memory_.cur_offset();
413           return false;
414         }
415         break;
416       case 'P': {
417         uint8_t encoding;
418         if (!memory_.ReadBytes(&encoding, 1)) {
419           last_error_.code = DWARF_ERROR_MEMORY_INVALID;
420           last_error_.address = memory_.cur_offset();
421           return false;
422         }
423         if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
424           last_error_.code = DWARF_ERROR_MEMORY_INVALID;
425           last_error_.address = memory_.cur_offset();
426           return false;
427         }
428       } break;
429       case 'R':
430         if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) {
431           last_error_.code = DWARF_ERROR_MEMORY_INVALID;
432           last_error_.address = memory_.cur_offset();
433           return false;
434         }
435         break;
436     }
437   }
438   return true;
439 }
440 
441 template <typename AddressType>
GetFdeFromOffset(uint64_t offset)442 const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) {
443   auto fde_entry = fde_entries_.find(offset);
444   if (fde_entry != fde_entries_.end()) {
445     return &fde_entry->second;
446   }
447   DwarfFde* fde = &fde_entries_[offset];
448   memory_.set_cur_offset(offset);
449   if (!FillInFde(fde)) {
450     fde_entries_.erase(offset);
451     return nullptr;
452   }
453   return fde;
454 }
455 
456 template <typename AddressType>
FillInFde(DwarfFde * fde)457 bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
458   uint32_t length32;
459   if (!memory_.ReadBytes(&length32, sizeof(length32))) {
460     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
461     last_error_.address = memory_.cur_offset();
462     return false;
463   }
464 
465   if (length32 == static_cast<uint32_t>(-1)) {
466     // 64 bit Fde.
467     uint64_t length64;
468     if (!memory_.ReadBytes(&length64, sizeof(length64))) {
469       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
470       last_error_.address = memory_.cur_offset();
471       return false;
472     }
473     fde->cfa_instructions_end = memory_.cur_offset() + length64;
474 
475     uint64_t value64;
476     if (!memory_.ReadBytes(&value64, sizeof(value64))) {
477       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
478       last_error_.address = memory_.cur_offset();
479       return false;
480     }
481     if (value64 == cie64_value_) {
482       // This is a Cie, this means something has gone wrong.
483       last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
484       return false;
485     }
486 
487     // Get the Cie pointer, which is necessary to properly read the rest of
488     // of the Fde information.
489     fde->cie_offset = GetCieOffsetFromFde64(value64);
490   } else {
491     // 32 bit Fde.
492     fde->cfa_instructions_end = memory_.cur_offset() + length32;
493 
494     uint32_t value32;
495     if (!memory_.ReadBytes(&value32, sizeof(value32))) {
496       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
497       last_error_.address = memory_.cur_offset();
498       return false;
499     }
500     if (value32 == cie32_value_) {
501       // This is a Cie, this means something has gone wrong.
502       last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
503       return false;
504     }
505 
506     // Get the Cie pointer, which is necessary to properly read the rest of
507     // of the Fde information.
508     fde->cie_offset = GetCieOffsetFromFde32(value32);
509   }
510   uint64_t cur_offset = memory_.cur_offset();
511 
512   const DwarfCie* cie = GetCie(fde->cie_offset);
513   if (cie == nullptr) {
514     return false;
515   }
516   fde->cie = cie;
517 
518   if (cie->segment_size != 0) {
519     // Skip over the segment selector for now.
520     cur_offset += cie->segment_size;
521   }
522   memory_.set_cur_offset(cur_offset);
523 
524   if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_start)) {
525     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
526     last_error_.address = memory_.cur_offset();
527     return false;
528   }
529   fde->pc_start = AdjustPcFromFde(fde->pc_start);
530 
531   if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_end)) {
532     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
533     last_error_.address = memory_.cur_offset();
534     return false;
535   }
536   fde->pc_end += fde->pc_start;
537   if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') {
538     // Augmentation Size
539     uint64_t aug_length;
540     if (!memory_.ReadULEB128(&aug_length)) {
541       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
542       last_error_.address = memory_.cur_offset();
543       return false;
544     }
545     uint64_t cur_offset = memory_.cur_offset();
546 
547     if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
548       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
549       last_error_.address = memory_.cur_offset();
550       return false;
551     }
552 
553     // Set our position to after all of the augmentation data.
554     memory_.set_cur_offset(cur_offset + aug_length);
555   }
556   fde->cfa_instructions_offset = memory_.cur_offset();
557 
558   return true;
559 }
560 
561 template <typename AddressType>
GetCfaLocationInfo(uint64_t pc,const DwarfFde * fde,dwarf_loc_regs_t * loc_regs)562 bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
563                                                        dwarf_loc_regs_t* loc_regs) {
564   DwarfCfa<AddressType> cfa(&memory_, fde);
565 
566   // Look for the cached copy of the cie data.
567   auto reg_entry = cie_loc_regs_.find(fde->cie_offset);
568   if (reg_entry == cie_loc_regs_.end()) {
569     if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end,
570                              loc_regs)) {
571       last_error_ = cfa.last_error();
572       return false;
573     }
574     cie_loc_regs_[fde->cie_offset] = *loc_regs;
575   }
576   cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]);
577   if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) {
578     last_error_ = cfa.last_error();
579     return false;
580   }
581   return true;
582 }
583 
584 template <typename AddressType>
Log(uint8_t indent,uint64_t pc,uint64_t load_bias,const DwarfFde * fde)585 bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t load_bias,
586                                         const DwarfFde* fde) {
587   DwarfCfa<AddressType> cfa(&memory_, fde);
588 
589   // Always print the cie information.
590   const DwarfCie* cie = fde->cie;
591   if (!cfa.Log(indent, pc, load_bias, cie->cfa_instructions_offset, cie->cfa_instructions_end)) {
592     last_error_ = cfa.last_error();
593     return false;
594   }
595   if (!cfa.Log(indent, pc, load_bias, fde->cfa_instructions_offset, fde->cfa_instructions_end)) {
596     last_error_ = cfa.last_error();
597     return false;
598   }
599   return true;
600 }
601 
602 template <typename AddressType>
Init(uint64_t offset,uint64_t size)603 bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size) {
604   entries_offset_ = offset;
605   entries_end_ = offset + size;
606 
607   memory_.clear_func_offset();
608   memory_.clear_text_offset();
609   memory_.set_data_offset(offset);
610   memory_.set_cur_offset(offset);
611   memory_.set_pc_offset(offset);
612 
613   return CreateSortedFdeList();
614 }
615 
616 template <typename AddressType>
GetCieInfo(uint8_t * segment_size,uint8_t * encoding)617 bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) {
618   uint8_t version;
619   if (!memory_.ReadBytes(&version, 1)) {
620     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
621     last_error_.address = memory_.cur_offset();
622     return false;
623   }
624   // Read the augmentation string.
625   std::vector<char> aug_string;
626   char aug_value;
627   bool get_encoding = false;
628   do {
629     if (!memory_.ReadBytes(&aug_value, 1)) {
630       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
631       last_error_.address = memory_.cur_offset();
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_.code = DWARF_ERROR_MEMORY_INVALID;
647       last_error_.address = memory_.cur_offset();
648       return false;
649     }
650   } else {
651     *segment_size = 0;
652   }
653 
654   if (aug_string[0] != 'z' || !get_encoding) {
655     // No encoding
656     return true;
657   }
658 
659   // Skip code alignment factor
660   uint8_t value;
661   do {
662     if (!memory_.ReadBytes(&value, 1)) {
663       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
664       last_error_.address = memory_.cur_offset();
665       return false;
666     }
667   } while (value & 0x80);
668 
669   // Skip data alignment factor
670   do {
671     if (!memory_.ReadBytes(&value, 1)) {
672       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
673       last_error_.address = memory_.cur_offset();
674       return false;
675     }
676   } while (value & 0x80);
677 
678   if (version == 1) {
679     // Skip return address register.
680     memory_.set_cur_offset(memory_.cur_offset() + 1);
681   } else {
682     // Skip return address register.
683     do {
684       if (!memory_.ReadBytes(&value, 1)) {
685         last_error_.code = DWARF_ERROR_MEMORY_INVALID;
686         last_error_.address = memory_.cur_offset();
687         return false;
688       }
689     } while (value & 0x80);
690   }
691 
692   // Skip the augmentation length.
693   do {
694     if (!memory_.ReadBytes(&value, 1)) {
695       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
696       last_error_.address = memory_.cur_offset();
697       return false;
698     }
699   } while (value & 0x80);
700 
701   for (size_t i = 1; i < aug_string.size(); i++) {
702     if (aug_string[i] == 'R') {
703       if (!memory_.ReadBytes(encoding, 1)) {
704         last_error_.code = DWARF_ERROR_MEMORY_INVALID;
705         last_error_.address = memory_.cur_offset();
706         return false;
707       }
708       // Got the encoding, that's all we are looking for.
709       return true;
710     } else if (aug_string[i] == 'L') {
711       memory_.set_cur_offset(memory_.cur_offset() + 1);
712     } else if (aug_string[i] == 'P') {
713       uint8_t encoding;
714       if (!memory_.ReadBytes(&encoding, 1)) {
715         last_error_.code = DWARF_ERROR_MEMORY_INVALID;
716         last_error_.address = memory_.cur_offset();
717         return false;
718       }
719       uint64_t value;
720       if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) {
721         last_error_.code = DWARF_ERROR_MEMORY_INVALID;
722         last_error_.address = memory_.cur_offset();
723         return false;
724       }
725     }
726   }
727 
728   // It should be impossible to get here.
729   abort();
730 }
731 
732 template <typename AddressType>
AddFdeInfo(uint64_t entry_offset,uint8_t segment_size,uint8_t encoding)733 bool DwarfSectionImpl<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size,
734                                                uint8_t encoding) {
735   if (segment_size != 0) {
736     memory_.set_cur_offset(memory_.cur_offset() + 1);
737   }
738 
739   uint64_t start;
740   if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) {
741     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
742     last_error_.address = memory_.cur_offset();
743     return false;
744   }
745   start = AdjustPcFromFde(start);
746 
747   uint64_t length;
748   if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) {
749     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
750     last_error_.address = memory_.cur_offset();
751     return false;
752   }
753   if (length != 0) {
754     fdes_.emplace_back(entry_offset, start, length);
755   }
756 
757   return true;
758 }
759 
760 template <typename AddressType>
CreateSortedFdeList()761 bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() {
762   memory_.set_cur_offset(entries_offset_);
763 
764   // Loop through all of the entries and read just enough to create
765   // a sorted list of pcs.
766   // This code assumes that first comes the cie, then the fdes that
767   // it applies to.
768   uint64_t cie_offset = 0;
769   uint8_t address_encoding;
770   uint8_t segment_size;
771   while (memory_.cur_offset() < entries_end_) {
772     uint64_t cur_entry_offset = memory_.cur_offset();
773 
774     // Figure out the entry length and type.
775     uint32_t value32;
776     if (!memory_.ReadBytes(&value32, sizeof(value32))) {
777       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
778       last_error_.address = memory_.cur_offset();
779       return false;
780     }
781 
782     uint64_t next_entry_offset;
783     if (value32 == static_cast<uint32_t>(-1)) {
784       uint64_t value64;
785       if (!memory_.ReadBytes(&value64, sizeof(value64))) {
786         last_error_.code = DWARF_ERROR_MEMORY_INVALID;
787         last_error_.address = memory_.cur_offset();
788         return false;
789       }
790       next_entry_offset = memory_.cur_offset() + value64;
791 
792       // Read the Cie Id of a Cie or the pointer of the Fde.
793       if (!memory_.ReadBytes(&value64, sizeof(value64))) {
794         last_error_.code = DWARF_ERROR_MEMORY_INVALID;
795         last_error_.address = memory_.cur_offset();
796         return false;
797       }
798 
799       if (value64 == cie64_value_) {
800         // Cie 64 bit
801         address_encoding = DW_EH_PE_sdata8;
802         if (!GetCieInfo(&segment_size, &address_encoding)) {
803           return false;
804         }
805         cie_offset = cur_entry_offset;
806       } else {
807         uint64_t last_cie_offset = GetCieOffsetFromFde64(value64);
808         if (last_cie_offset != cie_offset) {
809           // This means that this Fde is not following the Cie.
810           last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
811           return false;
812         }
813 
814         // Fde 64 bit
815         if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
816           return false;
817         }
818       }
819     } else {
820       next_entry_offset = memory_.cur_offset() + value32;
821 
822       // Read the Cie Id of a Cie or the pointer of the Fde.
823       if (!memory_.ReadBytes(&value32, sizeof(value32))) {
824         last_error_.code = DWARF_ERROR_MEMORY_INVALID;
825         last_error_.address = memory_.cur_offset();
826         return false;
827       }
828 
829       if (value32 == cie32_value_) {
830         // Cie 32 bit
831         address_encoding = DW_EH_PE_sdata4;
832         if (!GetCieInfo(&segment_size, &address_encoding)) {
833           return false;
834         }
835         cie_offset = cur_entry_offset;
836       } else {
837         uint64_t last_cie_offset = GetCieOffsetFromFde32(value32);
838         if (last_cie_offset != cie_offset) {
839           // This means that this Fde is not following the Cie.
840           last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
841           return false;
842         }
843 
844         // Fde 32 bit
845         if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
846           return false;
847         }
848       }
849     }
850 
851     if (next_entry_offset < memory_.cur_offset()) {
852       // Simply consider the processing done in this case.
853       break;
854     }
855     memory_.set_cur_offset(next_entry_offset);
856   }
857 
858   // Sort the entries.
859   std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) {
860     if (a.start == b.start) return a.end < b.end;
861     return a.start < b.start;
862   });
863 
864   fde_count_ = fdes_.size();
865 
866   return true;
867 }
868 
869 template <typename AddressType>
GetFdeOffsetFromPc(uint64_t pc,uint64_t * fde_offset)870 bool DwarfSectionImpl<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
871   if (fde_count_ == 0) {
872     return false;
873   }
874 
875   size_t first = 0;
876   size_t last = fde_count_;
877   while (first < last) {
878     size_t current = (first + last) / 2;
879     const FdeInfo* info = &fdes_[current];
880     if (pc >= info->start && pc <= info->end) {
881       *fde_offset = info->offset;
882       return true;
883     }
884 
885     if (pc < info->start) {
886       last = current;
887     } else {
888       first = current + 1;
889     }
890   }
891   return false;
892 }
893 
894 template <typename AddressType>
GetFdeFromIndex(size_t index)895 const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromIndex(size_t index) {
896   if (index >= fdes_.size()) {
897     return nullptr;
898   }
899   return this->GetFdeFromOffset(fdes_[index].offset);
900 }
901 
902 // Explicitly instantiate DwarfSectionImpl
903 template class DwarfSectionImpl<uint32_t>;
904 template class DwarfSectionImpl<uint64_t>;
905 
906 // Explicitly instantiate DwarfDebugFrame
907 template class DwarfDebugFrame<uint32_t>;
908 template class DwarfDebugFrame<uint64_t>;
909 
910 // Explicitly instantiate DwarfEhFrame
911 template class DwarfEhFrame<uint32_t>;
912 template class DwarfEhFrame<uint64_t>;
913 
914 }  // namespace unwindstack
915