1 //===--------------------------- DwarfParser.hpp --------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //
9 //  Parses DWARF CFIs (FDEs and CIEs).
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef __DWARF_PARSER_HPP__
14 #define __DWARF_PARSER_HPP__
15 
16 #include <inttypes.h>
17 #include <stdint.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 
21 #include "libunwind.h"
22 #include "dwarf2.h"
23 
24 #include "config.h"
25 
26 namespace libunwind {
27 
28 /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
29 /// See DWARF Spec for details:
30 ///    http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
31 ///
32 template <typename A>
33 class CFI_Parser {
34 public:
35   typedef typename A::pint_t pint_t;
36 
37   /// Information encoded in a CIE (Common Information Entry)
38   struct CIE_Info {
39     pint_t    cieStart;
40     pint_t    cieLength;
41     pint_t    cieInstructions;
42     uint8_t   pointerEncoding;
43     uint8_t   lsdaEncoding;
44     uint8_t   personalityEncoding;
45     uint8_t   personalityOffsetInCIE;
46     pint_t    personality;
47     uint32_t  codeAlignFactor;
48     int       dataAlignFactor;
49     bool      isSignalFrame;
50     bool      fdesHaveAugmentationData;
51     uint8_t   returnAddressRegister;
52   };
53 
54   /// Information about an FDE (Frame Description Entry)
55   struct FDE_Info {
56     pint_t  fdeStart;
57     pint_t  fdeLength;
58     pint_t  fdeInstructions;
59     pint_t  pcStart;
60     pint_t  pcEnd;
61     pint_t  lsda;
62   };
63 
64   enum {
65     kMaxRegisterNumber = _LIBUNWIND_HIGHEST_DWARF_REGISTER
66   };
67   enum RegisterSavedWhere {
68     kRegisterUnused,
69     kRegisterInCFA,
70     kRegisterOffsetFromCFA,
71     kRegisterInRegister,
72     kRegisterAtExpression,
73     kRegisterIsExpression
74   };
75   struct RegisterLocation {
76     RegisterSavedWhere location;
77     int64_t value;
78   };
79   /// Information about a frame layout and registers saved determined
80   /// by "running" the DWARF FDE "instructions"
81   struct PrologInfo {
82     uint32_t          cfaRegister;
83     int32_t           cfaRegisterOffset;  // CFA = (cfaRegister)+cfaRegisterOffset
84     int64_t           cfaExpression;      // CFA = expression
85     uint32_t          spExtraArgSize;
86     uint32_t          codeOffsetAtStackDecrement;
87     bool              registersInOtherRegisters;
88     bool              sameValueUsed;
89     RegisterLocation  savedRegisters[kMaxRegisterNumber + 1];
90   };
91 
92   struct PrologInfoStackEntry {
93     PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
94         : next(n), info(i) {}
95     PrologInfoStackEntry *next;
96     PrologInfo info;
97   };
98 
99   static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
100                       uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
101                       CIE_Info *cieInfo);
102   static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
103                                FDE_Info *fdeInfo, CIE_Info *cieInfo);
104   static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
105                                    const CIE_Info &cieInfo, pint_t upToPC,
106                                    PrologInfo *results);
107 
108   static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
109 
110 private:
111   static bool parseInstructions(A &addressSpace, pint_t instructions,
112                                 pint_t instructionsEnd, const CIE_Info &cieInfo,
113                                 pint_t pcoffset,
114                                 PrologInfoStackEntry *&rememberStack,
115                                 PrologInfo *results);
116 };
117 
118 /// Parse a FDE into a CIE_Info and an FDE_Info
119 template <typename A>
120 const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
121                                      FDE_Info *fdeInfo, CIE_Info *cieInfo) {
122   pint_t p = fdeStart;
123   pint_t cfiLength = (pint_t)addressSpace.get32(p);
124   p += 4;
125   if (cfiLength == 0xffffffff) {
126     // 0xffffffff means length is really next 8 bytes
127     cfiLength = (pint_t)addressSpace.get64(p);
128     p += 8;
129   }
130   if (cfiLength == 0)
131     return "FDE has zero length"; // end marker
132   uint32_t ciePointer = addressSpace.get32(p);
133   if (ciePointer == 0)
134     return "FDE is really a CIE"; // this is a CIE not an FDE
135   pint_t nextCFI = p + cfiLength;
136   pint_t cieStart = p - ciePointer;
137   const char *err = parseCIE(addressSpace, cieStart, cieInfo);
138   if (err != NULL)
139     return err;
140   p += 4;
141   // Parse pc begin and range.
142   pint_t pcStart =
143       addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
144   pint_t pcRange =
145       addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
146   // Parse rest of info.
147   fdeInfo->lsda = 0;
148   // Check for augmentation length.
149   if (cieInfo->fdesHaveAugmentationData) {
150     pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
151     pint_t endOfAug = p + augLen;
152     if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
153       // Peek at value (without indirection).  Zero means no LSDA.
154       pint_t lsdaStart = p;
155       if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) !=
156           0) {
157         // Reset pointer and re-parse LSDA address.
158         p = lsdaStart;
159         fdeInfo->lsda =
160             addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
161       }
162     }
163     p = endOfAug;
164   }
165   fdeInfo->fdeStart = fdeStart;
166   fdeInfo->fdeLength = nextCFI - fdeStart;
167   fdeInfo->fdeInstructions = p;
168   fdeInfo->pcStart = pcStart;
169   fdeInfo->pcEnd = pcStart + pcRange;
170   return NULL; // success
171 }
172 
173 /// Scan an eh_frame section to find an FDE for a pc
174 template <typename A>
175 bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
176                             uint32_t sectionLength, pint_t fdeHint,
177                             FDE_Info *fdeInfo, CIE_Info *cieInfo) {
178   //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
179   pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
180   const pint_t ehSectionEnd = p + sectionLength;
181   while (p < ehSectionEnd) {
182     pint_t currentCFI = p;
183     //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
184     pint_t cfiLength = addressSpace.get32(p);
185     p += 4;
186     if (cfiLength == 0xffffffff) {
187       // 0xffffffff means length is really next 8 bytes
188       cfiLength = (pint_t)addressSpace.get64(p);
189       p += 8;
190     }
191     if (cfiLength == 0)
192       return false; // end marker
193     uint32_t id = addressSpace.get32(p);
194     if (id == 0) {
195       // Skip over CIEs.
196       p += cfiLength;
197     } else {
198       // Process FDE to see if it covers pc.
199       pint_t nextCFI = p + cfiLength;
200       uint32_t ciePointer = addressSpace.get32(p);
201       pint_t cieStart = p - ciePointer;
202       // Validate pointer to CIE is within section.
203       if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) {
204         if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) {
205           p += 4;
206           // Parse pc begin and range.
207           pint_t pcStart =
208               addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
209           pint_t pcRange = addressSpace.getEncodedP(
210               p, nextCFI, cieInfo->pointerEncoding & 0x0F);
211           // Test if pc is within the function this FDE covers.
212           if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
213             // parse rest of info
214             fdeInfo->lsda = 0;
215             // check for augmentation length
216             if (cieInfo->fdesHaveAugmentationData) {
217               pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
218               pint_t endOfAug = p + augLen;
219               if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
220                 // Peek at value (without indirection).  Zero means no LSDA.
221                 pint_t lsdaStart = p;
222                 if (addressSpace.getEncodedP(
223                         p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) {
224                   // Reset pointer and re-parse LSDA address.
225                   p = lsdaStart;
226                   fdeInfo->lsda = addressSpace
227                       .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
228                 }
229               }
230               p = endOfAug;
231             }
232             fdeInfo->fdeStart = currentCFI;
233             fdeInfo->fdeLength = nextCFI - currentCFI;
234             fdeInfo->fdeInstructions = p;
235             fdeInfo->pcStart = pcStart;
236             fdeInfo->pcEnd = pcStart + pcRange;
237             return true;
238           } else {
239             // pc is not in begin/range, skip this FDE
240           }
241         } else {
242           // Malformed CIE, now augmentation describing pc range encoding.
243         }
244       } else {
245         // malformed FDE.  CIE is bad
246       }
247       p = nextCFI;
248     }
249   }
250   return false;
251 }
252 
253 /// Extract info from a CIE
254 template <typename A>
255 const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
256                                     CIE_Info *cieInfo) {
257   cieInfo->pointerEncoding = 0;
258   cieInfo->lsdaEncoding = DW_EH_PE_omit;
259   cieInfo->personalityEncoding = 0;
260   cieInfo->personalityOffsetInCIE = 0;
261   cieInfo->personality = 0;
262   cieInfo->codeAlignFactor = 0;
263   cieInfo->dataAlignFactor = 0;
264   cieInfo->isSignalFrame = false;
265   cieInfo->fdesHaveAugmentationData = false;
266   cieInfo->cieStart = cie;
267   pint_t p = cie;
268   pint_t cieLength = (pint_t)addressSpace.get32(p);
269   p += 4;
270   pint_t cieContentEnd = p + cieLength;
271   if (cieLength == 0xffffffff) {
272     // 0xffffffff means length is really next 8 bytes
273     cieLength = (pint_t)addressSpace.get64(p);
274     p += 8;
275     cieContentEnd = p + cieLength;
276   }
277   if (cieLength == 0)
278     return NULL;
279   // CIE ID is always 0
280   if (addressSpace.get32(p) != 0)
281     return "CIE ID is not zero";
282   p += 4;
283   // Version is always 1 or 3
284   uint8_t version = addressSpace.get8(p);
285   if ((version != 1) && (version != 3))
286     return "CIE version is not 1 or 3";
287   ++p;
288   // save start of augmentation string and find end
289   pint_t strStart = p;
290   while (addressSpace.get8(p) != 0)
291     ++p;
292   ++p;
293   // parse code aligment factor
294   cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd);
295   // parse data alignment factor
296   cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
297   // parse return address register
298   uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd);
299   assert(raReg < 255 && "return address register too large");
300   cieInfo->returnAddressRegister = (uint8_t)raReg;
301   // parse augmentation data based on augmentation string
302   const char *result = NULL;
303   if (addressSpace.get8(strStart) == 'z') {
304     // parse augmentation data length
305     addressSpace.getULEB128(p, cieContentEnd);
306     for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
307       switch (addressSpace.get8(s)) {
308       case 'z':
309         cieInfo->fdesHaveAugmentationData = true;
310         break;
311       case 'P':
312         cieInfo->personalityEncoding = addressSpace.get8(p);
313         ++p;
314         cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
315         cieInfo->personality = addressSpace
316             .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
317         break;
318       case 'L':
319         cieInfo->lsdaEncoding = addressSpace.get8(p);
320         ++p;
321         break;
322       case 'R':
323         cieInfo->pointerEncoding = addressSpace.get8(p);
324         ++p;
325         break;
326       case 'S':
327         cieInfo->isSignalFrame = true;
328         break;
329       default:
330         // ignore unknown letters
331         break;
332       }
333     }
334   }
335   cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
336   cieInfo->cieInstructions = p;
337   return result;
338 }
339 
340 
341 /// "run" the DWARF instructions and create the abstact PrologInfo for an FDE
342 template <typename A>
343 bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
344                                          const FDE_Info &fdeInfo,
345                                          const CIE_Info &cieInfo, pint_t upToPC,
346                                          PrologInfo *results) {
347   // clear results
348   memset(results, '\0', sizeof(PrologInfo));
349   PrologInfoStackEntry *rememberStack = NULL;
350 
351   // parse CIE then FDE instructions
352   return parseInstructions(addressSpace, cieInfo.cieInstructions,
353                            cieInfo.cieStart + cieInfo.cieLength, cieInfo,
354                            (pint_t)(-1), rememberStack, results) &&
355          parseInstructions(addressSpace, fdeInfo.fdeInstructions,
356                            fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
357                            upToPC - fdeInfo.pcStart, rememberStack, results);
358 }
359 
360 /// "run" the DWARF instructions
361 template <typename A>
362 bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
363                                       pint_t instructionsEnd,
364                                       const CIE_Info &cieInfo, pint_t pcoffset,
365                                       PrologInfoStackEntry *&rememberStack,
366                                       PrologInfo *results) {
367   pint_t p = instructions;
368   pint_t codeOffset = 0;
369   PrologInfo initialState = *results;
370 
371   _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n",
372                          static_cast<uint64_t>(instructionsEnd));
373 
374   // see DWARF Spec, section 6.4.2 for details on unwind opcodes
375   while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
376     uint64_t reg;
377     uint64_t reg2;
378     int64_t offset;
379     uint64_t length;
380     uint8_t opcode = addressSpace.get8(p);
381     uint8_t operand;
382 #if !defined(_LIBUNWIND_NO_HEAP)
383     PrologInfoStackEntry *entry;
384 #endif
385     ++p;
386     switch (opcode) {
387     case DW_CFA_nop:
388       _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n");
389       break;
390     case DW_CFA_set_loc:
391       codeOffset =
392           addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
393       _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n");
394       break;
395     case DW_CFA_advance_loc1:
396       codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
397       p += 1;
398       _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n",
399                              static_cast<uint64_t>(codeOffset));
400       break;
401     case DW_CFA_advance_loc2:
402       codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
403       p += 2;
404       _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n",
405                              static_cast<uint64_t>(codeOffset));
406       break;
407     case DW_CFA_advance_loc4:
408       codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
409       p += 4;
410       _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n",
411                              static_cast<uint64_t>(codeOffset));
412       break;
413     case DW_CFA_offset_extended:
414       reg = addressSpace.getULEB128(p, instructionsEnd);
415       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
416                                                   * cieInfo.dataAlignFactor;
417       if (reg > kMaxRegisterNumber) {
418         _LIBUNWIND_LOG0(
419                 "malformed DW_CFA_offset_extended DWARF unwind, reg too big");
420         return false;
421       }
422       results->savedRegisters[reg].location = kRegisterInCFA;
423       results->savedRegisters[reg].value = offset;
424       _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", "
425                              "offset=%" PRId64 ")\n",
426                              reg, offset);
427       break;
428     case DW_CFA_restore_extended:
429       reg = addressSpace.getULEB128(p, instructionsEnd);
430       if (reg > kMaxRegisterNumber) {
431         _LIBUNWIND_LOG0(
432             "malformed DW_CFA_restore_extended DWARF unwind, reg too big");
433         return false;
434       }
435       results->savedRegisters[reg] = initialState.savedRegisters[reg];
436       _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg);
437       break;
438     case DW_CFA_undefined:
439       reg = addressSpace.getULEB128(p, instructionsEnd);
440       if (reg > kMaxRegisterNumber) {
441         _LIBUNWIND_LOG0(
442                 "malformed DW_CFA_undefined DWARF unwind, reg too big");
443         return false;
444       }
445       results->savedRegisters[reg].location = kRegisterUnused;
446       _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg);
447       break;
448     case DW_CFA_same_value:
449       reg = addressSpace.getULEB128(p, instructionsEnd);
450       if (reg > kMaxRegisterNumber) {
451         _LIBUNWIND_LOG0(
452                 "malformed DW_CFA_same_value DWARF unwind, reg too big");
453         return false;
454       }
455       // <rdar://problem/8456377> DW_CFA_same_value unsupported
456       // "same value" means register was stored in frame, but its current
457       // value has not changed, so no need to restore from frame.
458       // We model this as if the register was never saved.
459       results->savedRegisters[reg].location = kRegisterUnused;
460       // set flag to disable conversion to compact unwind
461       results->sameValueUsed = true;
462       _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg);
463       break;
464     case DW_CFA_register:
465       reg = addressSpace.getULEB128(p, instructionsEnd);
466       reg2 = addressSpace.getULEB128(p, instructionsEnd);
467       if (reg > kMaxRegisterNumber) {
468         _LIBUNWIND_LOG0(
469                 "malformed DW_CFA_register DWARF unwind, reg too big");
470         return false;
471       }
472       if (reg2 > kMaxRegisterNumber) {
473         _LIBUNWIND_LOG0(
474                 "malformed DW_CFA_register DWARF unwind, reg2 too big");
475         return false;
476       }
477       results->savedRegisters[reg].location = kRegisterInRegister;
478       results->savedRegisters[reg].value = (int64_t)reg2;
479       // set flag to disable conversion to compact unwind
480       results->registersInOtherRegisters = true;
481       _LIBUNWIND_TRACE_DWARF(
482           "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2);
483       break;
484 #if !defined(_LIBUNWIND_NO_HEAP)
485     case DW_CFA_remember_state:
486       // avoid operator new, because that would be an upward dependency
487       entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
488       if (entry != NULL) {
489         entry->next = rememberStack;
490         entry->info = *results;
491         rememberStack = entry;
492       } else {
493         return false;
494       }
495       _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n");
496       break;
497     case DW_CFA_restore_state:
498       if (rememberStack != NULL) {
499         PrologInfoStackEntry *top = rememberStack;
500         *results = top->info;
501         rememberStack = top->next;
502         free((char *)top);
503       } else {
504         return false;
505       }
506       _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n");
507       break;
508 #endif
509     case DW_CFA_def_cfa:
510       reg = addressSpace.getULEB128(p, instructionsEnd);
511       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
512       if (reg > kMaxRegisterNumber) {
513         _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big");
514         return false;
515       }
516       results->cfaRegister = (uint32_t)reg;
517       results->cfaRegisterOffset = (int32_t)offset;
518       _LIBUNWIND_TRACE_DWARF(
519           "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", reg, offset);
520       break;
521     case DW_CFA_def_cfa_register:
522       reg = addressSpace.getULEB128(p, instructionsEnd);
523       if (reg > kMaxRegisterNumber) {
524         _LIBUNWIND_LOG0(
525             "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big");
526         return false;
527       }
528       results->cfaRegister = (uint32_t)reg;
529       _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg);
530       break;
531     case DW_CFA_def_cfa_offset:
532       results->cfaRegisterOffset = (int32_t)
533                                   addressSpace.getULEB128(p, instructionsEnd);
534       results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
535       _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n",
536                              results->cfaRegisterOffset);
537       break;
538     case DW_CFA_def_cfa_expression:
539       results->cfaRegister = 0;
540       results->cfaExpression = (int64_t)p;
541       length = addressSpace.getULEB128(p, instructionsEnd);
542       assert(length < static_cast<pint_t>(~0) && "pointer overflow");
543       p += static_cast<pint_t>(length);
544       _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64
545                              ", length=%" PRIu64 ")\n",
546                              results->cfaExpression, length);
547       break;
548     case DW_CFA_expression:
549       reg = addressSpace.getULEB128(p, instructionsEnd);
550       if (reg > kMaxRegisterNumber) {
551         _LIBUNWIND_LOG0(
552                 "malformed DW_CFA_expression DWARF unwind, reg too big");
553         return false;
554       }
555       results->savedRegisters[reg].location = kRegisterAtExpression;
556       results->savedRegisters[reg].value = (int64_t)p;
557       length = addressSpace.getULEB128(p, instructionsEnd);
558       assert(length < static_cast<pint_t>(~0) && "pointer overflow");
559       p += static_cast<pint_t>(length);
560       _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", "
561                              "expression=0x%" PRIx64 ", "
562                              "length=%" PRIu64 ")\n",
563                              reg, results->savedRegisters[reg].value, length);
564       break;
565     case DW_CFA_offset_extended_sf:
566       reg = addressSpace.getULEB128(p, instructionsEnd);
567       if (reg > kMaxRegisterNumber) {
568         _LIBUNWIND_LOG0(
569             "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big");
570         return false;
571       }
572       offset =
573           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
574       results->savedRegisters[reg].location = kRegisterInCFA;
575       results->savedRegisters[reg].value = offset;
576       _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", "
577                              "offset=%" PRId64 ")\n",
578                              reg, offset);
579       break;
580     case DW_CFA_def_cfa_sf:
581       reg = addressSpace.getULEB128(p, instructionsEnd);
582       offset =
583           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
584       if (reg > kMaxRegisterNumber) {
585         _LIBUNWIND_LOG0(
586                 "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big");
587         return false;
588       }
589       results->cfaRegister = (uint32_t)reg;
590       results->cfaRegisterOffset = (int32_t)offset;
591       _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", "
592                              "offset=%" PRId64 ")\n",
593                              reg, offset);
594       break;
595     case DW_CFA_def_cfa_offset_sf:
596       results->cfaRegisterOffset = (int32_t)
597         (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor);
598       results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
599       _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n",
600                              results->cfaRegisterOffset);
601       break;
602     case DW_CFA_val_offset:
603       reg = addressSpace.getULEB128(p, instructionsEnd);
604       if (reg > kMaxRegisterNumber) {
605         _LIBUNWIND_LOG(
606                 "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64
607                 ") out of range\n",
608                 reg);
609         return false;
610       }
611       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
612                                                     * cieInfo.dataAlignFactor;
613       results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
614       results->savedRegisters[reg].value = offset;
615       _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", "
616                              "offset=%" PRId64 "\n",
617                              reg, offset);
618       break;
619     case DW_CFA_val_offset_sf:
620       reg = addressSpace.getULEB128(p, instructionsEnd);
621       if (reg > kMaxRegisterNumber) {
622         _LIBUNWIND_LOG0(
623                 "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big");
624         return false;
625       }
626       offset =
627           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
628       results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
629       results->savedRegisters[reg].value = offset;
630       _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", "
631                              "offset=%" PRId64 "\n",
632                              reg, offset);
633       break;
634     case DW_CFA_val_expression:
635       reg = addressSpace.getULEB128(p, instructionsEnd);
636       if (reg > kMaxRegisterNumber) {
637         _LIBUNWIND_LOG0(
638                 "malformed DW_CFA_val_expression DWARF unwind, reg too big");
639         return false;
640       }
641       results->savedRegisters[reg].location = kRegisterIsExpression;
642       results->savedRegisters[reg].value = (int64_t)p;
643       length = addressSpace.getULEB128(p, instructionsEnd);
644       assert(length < static_cast<pint_t>(~0) && "pointer overflow");
645       p += static_cast<pint_t>(length);
646       _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", "
647                              "expression=0x%" PRIx64 ", length=%" PRIu64 ")\n",
648                              reg, results->savedRegisters[reg].value, length);
649       break;
650     case DW_CFA_GNU_args_size:
651       length = addressSpace.getULEB128(p, instructionsEnd);
652       results->spExtraArgSize = (uint32_t)length;
653       _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length);
654       break;
655     case DW_CFA_GNU_negative_offset_extended:
656       reg = addressSpace.getULEB128(p, instructionsEnd);
657       if (reg > kMaxRegisterNumber) {
658         _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF "
659                         "unwind, reg too big");
660         return false;
661       }
662       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
663                                                     * cieInfo.dataAlignFactor;
664       results->savedRegisters[reg].location = kRegisterInCFA;
665       results->savedRegisters[reg].value = -offset;
666       _LIBUNWIND_TRACE_DWARF(
667           "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset);
668       break;
669     default:
670       operand = opcode & 0x3F;
671       switch (opcode & 0xC0) {
672       case DW_CFA_offset:
673         reg = operand;
674         if (reg > kMaxRegisterNumber) {
675           _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
676                          ") out of range",
677                   reg);
678           return false;
679         }
680         offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
681                                                     * cieInfo.dataAlignFactor;
682         results->savedRegisters[reg].location = kRegisterInCFA;
683         results->savedRegisters[reg].value = offset;
684         _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n",
685                                operand, offset);
686         break;
687       case DW_CFA_advance_loc:
688         codeOffset += operand * cieInfo.codeAlignFactor;
689         _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n",
690                                static_cast<uint64_t>(codeOffset));
691         break;
692       case DW_CFA_restore:
693         reg = operand;
694         if (reg > kMaxRegisterNumber) {
695           _LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
696                          ") out of range",
697                   reg);
698           return false;
699         }
700         results->savedRegisters[reg] = initialState.savedRegisters[reg];
701         _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n",
702                                static_cast<uint64_t>(operand));
703         break;
704       default:
705         _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode);
706         return false;
707       }
708     }
709   }
710 
711   return true;
712 }
713 
714 } // namespace libunwind
715 
716 #endif // __DWARF_PARSER_HPP__
717