• 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/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 
27 #include "DwarfCfa.h"
28 #include "DwarfEncoding.h"
29 #include "DwarfError.h"
30 #include "DwarfOp.h"
31 
32 namespace unwindstack {
33 
DwarfSection(Memory * memory)34 DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {}
35 
GetFdeFromPc(uint64_t pc)36 const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
37   uint64_t fde_offset;
38   if (!GetFdeOffsetFromPc(pc, &fde_offset)) {
39     return nullptr;
40   }
41   const DwarfFde* fde = GetFdeFromOffset(fde_offset);
42   // Guaranteed pc >= pc_start, need to check pc in the fde range.
43   if (pc < fde->pc_end) {
44     return fde;
45   }
46   last_error_ = DWARF_ERROR_ILLEGAL_STATE;
47   return nullptr;
48 }
49 
Step(uint64_t pc,Regs * regs,Memory * process_memory)50 bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory) {
51   last_error_ = DWARF_ERROR_NONE;
52   const DwarfFde* fde = GetFdeFromPc(pc);
53   if (fde == nullptr || fde->cie == nullptr) {
54     last_error_ = DWARF_ERROR_ILLEGAL_STATE;
55     return false;
56   }
57 
58   // Now get the location information for this pc.
59   dwarf_loc_regs_t loc_regs;
60   if (!GetCfaLocationInfo(pc, fde, &loc_regs)) {
61     return false;
62   }
63 
64   // Now eval the actual registers.
65   return Eval(fde->cie, process_memory, loc_regs, regs);
66 }
67 
68 template <typename AddressType>
EvalExpression(const DwarfLocation & loc,uint8_t version,Memory * regular_memory,AddressType * value)69 bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uint8_t version,
70                                                    Memory* regular_memory, AddressType* value) {
71   DwarfOp<AddressType> op(&memory_, regular_memory);
72 
73   // Need to evaluate the op data.
74   uint64_t start = loc.values[1];
75   uint64_t end = start + loc.values[0];
76   if (!op.Eval(start, end, version)) {
77     last_error_ = op.last_error();
78     return false;
79   }
80   if (op.StackSize() == 0) {
81     last_error_ = DWARF_ERROR_ILLEGAL_STATE;
82     return false;
83   }
84   // We don't support an expression that evaluates to a register number.
85   if (op.is_register()) {
86     last_error_ = DWARF_ERROR_NOT_IMPLEMENTED;
87     return false;
88   }
89   *value = op.StackAt(0);
90   return true;
91 }
92 
93 template <typename AddressType>
Eval(const DwarfCie * cie,Memory * regular_memory,const dwarf_loc_regs_t & loc_regs,Regs * regs)94 bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
95                                          const dwarf_loc_regs_t& loc_regs, Regs* regs) {
96   RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
97   if (cie->return_address_register >= cur_regs->total_regs()) {
98     last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
99     return false;
100   }
101 
102   // Get the cfa value;
103   auto cfa_entry = loc_regs.find(CFA_REG);
104   if (cfa_entry == loc_regs.end()) {
105     last_error_ = DWARF_ERROR_CFA_NOT_DEFINED;
106     return false;
107   }
108 
109   AddressType prev_pc = regs->pc();
110   AddressType prev_cfa = regs->sp();
111 
112   AddressType cfa;
113   const DwarfLocation* loc = &cfa_entry->second;
114   // Only a few location types are valid for the cfa.
115   switch (loc->type) {
116     case DWARF_LOCATION_REGISTER:
117       if (loc->values[0] >= cur_regs->total_regs()) {
118         last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
119         return false;
120       }
121       // If the stack pointer register is the CFA, and the stack
122       // pointer register does not have any associated location
123       // information, use the current cfa value.
124       if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) {
125         cfa = prev_cfa;
126       } else {
127         cfa = (*cur_regs)[loc->values[0]];
128       }
129       cfa += loc->values[1];
130       break;
131     case DWARF_LOCATION_EXPRESSION:
132     case DWARF_LOCATION_VAL_EXPRESSION: {
133       AddressType value;
134       if (!EvalExpression(*loc, cie->version, regular_memory, &value)) {
135         return false;
136       }
137       if (loc->type == DWARF_LOCATION_EXPRESSION) {
138         if (!regular_memory->Read(value, &cfa, sizeof(AddressType))) {
139           last_error_ = DWARF_ERROR_MEMORY_INVALID;
140           return false;
141         }
142       } else {
143         cfa = value;
144       }
145       break;
146     }
147     default:
148       last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
149       return false;
150   }
151 
152   // This code is not guaranteed to work in cases where a register location
153   // is a double indirection to the actual value. For example, if r3 is set
154   // to r5 + 4, and r5 is set to CFA + 4, then this won't necessarily work
155   // because it does not guarantee that r5 is evaluated before r3.
156   // Check that this case does not exist, and error if it does.
157   bool return_address_undefined = false;
158   for (const auto& entry : loc_regs) {
159     uint16_t reg = entry.first;
160     // Already handled the CFA register.
161     if (reg == CFA_REG) continue;
162 
163     if (reg >= cur_regs->total_regs()) {
164       // Skip this unknown register.
165       continue;
166     }
167 
168     const DwarfLocation* loc = &entry.second;
169     switch (loc->type) {
170       case DWARF_LOCATION_OFFSET:
171         if (!regular_memory->Read(cfa + loc->values[0], &(*cur_regs)[reg], sizeof(AddressType))) {
172           last_error_ = DWARF_ERROR_MEMORY_INVALID;
173           return false;
174         }
175         break;
176       case DWARF_LOCATION_VAL_OFFSET:
177         (*cur_regs)[reg] = cfa + loc->values[0];
178         break;
179       case DWARF_LOCATION_REGISTER: {
180         uint16_t cur_reg = loc->values[0];
181         if (cur_reg >= cur_regs->total_regs()) {
182           last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
183           return false;
184         }
185         if (loc_regs.find(cur_reg) != loc_regs.end()) {
186           // This is a double indirection, a register definition references
187           // another register which is also defined as something other
188           // than a register.
189           log(0,
190               "Invalid indirection: register %d references register %d which is "
191               "not a plain register.\n",
192               reg, cur_reg);
193           last_error_ = DWARF_ERROR_ILLEGAL_STATE;
194           return false;
195         }
196         (*cur_regs)[reg] = (*cur_regs)[cur_reg] + loc->values[1];
197         break;
198       }
199       case DWARF_LOCATION_EXPRESSION:
200       case DWARF_LOCATION_VAL_EXPRESSION: {
201         AddressType value;
202         if (!EvalExpression(*loc, cie->version, regular_memory, &value)) {
203           return false;
204         }
205         if (loc->type == DWARF_LOCATION_EXPRESSION) {
206           if (!regular_memory->Read(value, &(*cur_regs)[reg], sizeof(AddressType))) {
207             last_error_ = DWARF_ERROR_MEMORY_INVALID;
208             return false;
209           }
210         } else {
211           (*cur_regs)[reg] = value;
212         }
213         break;
214       }
215       case DWARF_LOCATION_UNDEFINED:
216         if (reg == cie->return_address_register) {
217           return_address_undefined = true;
218         }
219       default:
220         break;
221     }
222   }
223 
224   // Find the return address location.
225   if (return_address_undefined) {
226     cur_regs->set_pc(0);
227   } else {
228     cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
229   }
230   cur_regs->set_sp(cfa);
231   // Stop if the cfa and pc are the same.
232   return prev_cfa != cfa || prev_pc != cur_regs->pc();
233 }
234 
235 template <typename AddressType>
GetCie(uint64_t offset)236 const DwarfCie* DwarfSectionImpl<AddressType>::GetCie(uint64_t offset) {
237   auto cie_entry = cie_entries_.find(offset);
238   if (cie_entry != cie_entries_.end()) {
239     return &cie_entry->second;
240   }
241   DwarfCie* cie = &cie_entries_[offset];
242   memory_.set_cur_offset(offset);
243   if (!FillInCie(cie)) {
244     // Erase the cached entry.
245     cie_entries_.erase(offset);
246     return nullptr;
247   }
248   return cie;
249 }
250 
251 template <typename AddressType>
FillInCie(DwarfCie * cie)252 bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
253   uint32_t length32;
254   if (!memory_.ReadBytes(&length32, sizeof(length32))) {
255     last_error_ = DWARF_ERROR_MEMORY_INVALID;
256     return false;
257   }
258   // Set the default for the lsda encoding.
259   cie->lsda_encoding = DW_EH_PE_omit;
260 
261   if (length32 == static_cast<uint32_t>(-1)) {
262     // 64 bit Cie
263     uint64_t length64;
264     if (!memory_.ReadBytes(&length64, sizeof(length64))) {
265       last_error_ = DWARF_ERROR_MEMORY_INVALID;
266       return false;
267     }
268 
269     cie->cfa_instructions_end = memory_.cur_offset() + length64;
270     cie->fde_address_encoding = DW_EH_PE_sdata8;
271 
272     uint64_t cie_id;
273     if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
274       last_error_ = DWARF_ERROR_MEMORY_INVALID;
275       return false;
276     }
277     if (!IsCie64(cie_id)) {
278       // This is not a Cie, something has gone horribly wrong.
279       last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
280       return false;
281     }
282   } else {
283     // 32 bit Cie
284     cie->cfa_instructions_end = memory_.cur_offset() + length32;
285     cie->fde_address_encoding = DW_EH_PE_sdata4;
286 
287     uint32_t cie_id;
288     if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
289       last_error_ = DWARF_ERROR_MEMORY_INVALID;
290       return false;
291     }
292     if (!IsCie32(cie_id)) {
293       // This is not a Cie, something has gone horribly wrong.
294       last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
295       return false;
296     }
297   }
298 
299   if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
300     last_error_ = DWARF_ERROR_MEMORY_INVALID;
301     return false;
302   }
303 
304   if (cie->version != 1 && cie->version != 3 && cie->version != 4) {
305     // Unrecognized version.
306     last_error_ = DWARF_ERROR_UNSUPPORTED_VERSION;
307     return false;
308   }
309 
310   // Read the augmentation string.
311   char aug_value;
312   do {
313     if (!memory_.ReadBytes(&aug_value, 1)) {
314       last_error_ = DWARF_ERROR_MEMORY_INVALID;
315       return false;
316     }
317     cie->augmentation_string.push_back(aug_value);
318   } while (aug_value != '\0');
319 
320   if (cie->version == 4) {
321     // Skip the Address Size field since we only use it for validation.
322     memory_.set_cur_offset(memory_.cur_offset() + 1);
323 
324     // Segment Size
325     if (!memory_.ReadBytes(&cie->segment_size, 1)) {
326       last_error_ = DWARF_ERROR_MEMORY_INVALID;
327       return false;
328     }
329   }
330 
331   // Code Alignment Factor
332   if (!memory_.ReadULEB128(&cie->code_alignment_factor)) {
333     last_error_ = DWARF_ERROR_MEMORY_INVALID;
334     return false;
335   }
336 
337   // Data Alignment Factor
338   if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) {
339     last_error_ = DWARF_ERROR_MEMORY_INVALID;
340     return false;
341   }
342 
343   if (cie->version == 1) {
344     // Return Address is a single byte.
345     uint8_t return_address_register;
346     if (!memory_.ReadBytes(&return_address_register, 1)) {
347       last_error_ = DWARF_ERROR_MEMORY_INVALID;
348       return false;
349     }
350     cie->return_address_register = return_address_register;
351   } else if (!memory_.ReadULEB128(&cie->return_address_register)) {
352     last_error_ = DWARF_ERROR_MEMORY_INVALID;
353     return false;
354   }
355 
356   if (cie->augmentation_string[0] != 'z') {
357     cie->cfa_instructions_offset = memory_.cur_offset();
358     return true;
359   }
360 
361   uint64_t aug_length;
362   if (!memory_.ReadULEB128(&aug_length)) {
363     last_error_ = DWARF_ERROR_MEMORY_INVALID;
364     return false;
365   }
366   cie->cfa_instructions_offset = memory_.cur_offset() + aug_length;
367 
368   for (size_t i = 1; i < cie->augmentation_string.size(); i++) {
369     switch (cie->augmentation_string[i]) {
370       case 'L':
371         if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) {
372           last_error_ = DWARF_ERROR_MEMORY_INVALID;
373           return false;
374         }
375         break;
376       case 'P': {
377         uint8_t encoding;
378         if (!memory_.ReadBytes(&encoding, 1)) {
379           last_error_ = DWARF_ERROR_MEMORY_INVALID;
380           return false;
381         }
382         if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
383           last_error_ = DWARF_ERROR_MEMORY_INVALID;
384           return false;
385         }
386       } break;
387       case 'R':
388         if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) {
389           last_error_ = DWARF_ERROR_MEMORY_INVALID;
390           return false;
391         }
392         break;
393     }
394   }
395   return true;
396 }
397 
398 template <typename AddressType>
GetFdeFromOffset(uint64_t offset)399 const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) {
400   auto fde_entry = fde_entries_.find(offset);
401   if (fde_entry != fde_entries_.end()) {
402     return &fde_entry->second;
403   }
404   DwarfFde* fde = &fde_entries_[offset];
405   memory_.set_cur_offset(offset);
406   if (!FillInFde(fde)) {
407     fde_entries_.erase(offset);
408     return nullptr;
409   }
410   return fde;
411 }
412 
413 template <typename AddressType>
FillInFde(DwarfFde * fde)414 bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
415   uint32_t length32;
416   if (!memory_.ReadBytes(&length32, sizeof(length32))) {
417     last_error_ = DWARF_ERROR_MEMORY_INVALID;
418     return false;
419   }
420 
421   if (length32 == static_cast<uint32_t>(-1)) {
422     // 64 bit Fde.
423     uint64_t length64;
424     if (!memory_.ReadBytes(&length64, sizeof(length64))) {
425       last_error_ = DWARF_ERROR_MEMORY_INVALID;
426       return false;
427     }
428     fde->cfa_instructions_end = memory_.cur_offset() + length64;
429 
430     uint64_t value64;
431     if (!memory_.ReadBytes(&value64, sizeof(value64))) {
432       last_error_ = DWARF_ERROR_MEMORY_INVALID;
433       return false;
434     }
435     if (IsCie64(value64)) {
436       // This is a Cie, this means something has gone wrong.
437       last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
438       return false;
439     }
440 
441     // Get the Cie pointer, which is necessary to properly read the rest of
442     // of the Fde information.
443     fde->cie_offset = GetCieOffsetFromFde64(value64);
444   } else {
445     // 32 bit Fde.
446     fde->cfa_instructions_end = memory_.cur_offset() + length32;
447 
448     uint32_t value32;
449     if (!memory_.ReadBytes(&value32, sizeof(value32))) {
450       last_error_ = DWARF_ERROR_MEMORY_INVALID;
451       return false;
452     }
453     if (IsCie32(value32)) {
454       // This is a Cie, this means something has gone wrong.
455       last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
456       return false;
457     }
458 
459     // Get the Cie pointer, which is necessary to properly read the rest of
460     // of the Fde information.
461     fde->cie_offset = GetCieOffsetFromFde32(value32);
462   }
463   uint64_t cur_offset = memory_.cur_offset();
464 
465   const DwarfCie* cie = GetCie(fde->cie_offset);
466   if (cie == nullptr) {
467     return false;
468   }
469   fde->cie = cie;
470 
471   if (cie->segment_size != 0) {
472     // Skip over the segment selector for now.
473     cur_offset += cie->segment_size;
474   }
475   memory_.set_cur_offset(cur_offset);
476 
477   if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_start)) {
478     last_error_ = DWARF_ERROR_MEMORY_INVALID;
479     return false;
480   }
481   fde->pc_start = AdjustPcFromFde(fde->pc_start);
482 
483   if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_end)) {
484     last_error_ = DWARF_ERROR_MEMORY_INVALID;
485     return false;
486   }
487   fde->pc_end += fde->pc_start;
488   if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') {
489     // Augmentation Size
490     uint64_t aug_length;
491     if (!memory_.ReadULEB128(&aug_length)) {
492       last_error_ = DWARF_ERROR_MEMORY_INVALID;
493       return false;
494     }
495     uint64_t cur_offset = memory_.cur_offset();
496 
497     if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
498       last_error_ = DWARF_ERROR_MEMORY_INVALID;
499       return false;
500     }
501 
502     // Set our position to after all of the augmentation data.
503     memory_.set_cur_offset(cur_offset + aug_length);
504   }
505   fde->cfa_instructions_offset = memory_.cur_offset();
506 
507   return true;
508 }
509 
510 template <typename AddressType>
GetCfaLocationInfo(uint64_t pc,const DwarfFde * fde,dwarf_loc_regs_t * loc_regs)511 bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
512                                                        dwarf_loc_regs_t* loc_regs) {
513   DwarfCfa<AddressType> cfa(&memory_, fde);
514 
515   // Look for the cached copy of the cie data.
516   auto reg_entry = cie_loc_regs_.find(fde->cie_offset);
517   if (reg_entry == cie_loc_regs_.end()) {
518     if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end,
519                              loc_regs)) {
520       last_error_ = cfa.last_error();
521       return false;
522     }
523     cie_loc_regs_[fde->cie_offset] = *loc_regs;
524   }
525   cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]);
526   if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) {
527     last_error_ = cfa.last_error();
528     return false;
529   }
530   return true;
531 }
532 
533 template <typename AddressType>
Log(uint8_t indent,uint64_t pc,uint64_t load_bias,const DwarfFde * fde)534 bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t load_bias,
535                                         const DwarfFde* fde) {
536   DwarfCfa<AddressType> cfa(&memory_, fde);
537 
538   // Always print the cie information.
539   const DwarfCie* cie = fde->cie;
540   if (!cfa.Log(indent, pc, load_bias, cie->cfa_instructions_offset, cie->cfa_instructions_end)) {
541     last_error_ = cfa.last_error();
542     return false;
543   }
544   if (!cfa.Log(indent, pc, load_bias, fde->cfa_instructions_offset, fde->cfa_instructions_end)) {
545     last_error_ = cfa.last_error();
546     return false;
547   }
548   return true;
549 }
550 
551 // Explicitly instantiate DwarfSectionImpl
552 template class DwarfSectionImpl<uint32_t>;
553 template class DwarfSectionImpl<uint64_t>;
554 
555 }  // namespace unwindstack
556