152baab9e384c3de410c9be38906be3677bfd99b
[platform/framework/web/crosswalk.git] / src / third_party / libc++abi / trunk / src / Unwind / DwarfParser.hpp
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 <stdint.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19
20 #include <vector>
21
22 #include "libunwind.h"
23 #include "dwarf2.h"
24
25 #include "AddressSpace.hpp"
26
27 namespace libunwind {
28
29 /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
30 /// See Dwarf Spec for details:
31 ///    http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
32 ///
33 template <typename A>
34 class CFI_Parser {
35 public:
36   typedef typename A::pint_t pint_t;
37
38   /// Information encoded in a CIE (Common Information Entry)
39   struct CIE_Info {
40     pint_t    cieStart;
41     pint_t    cieLength;
42     pint_t    cieInstructions;
43     uint8_t   pointerEncoding;
44     uint8_t   lsdaEncoding;
45     uint8_t   personalityEncoding;
46     uint8_t   personalityOffsetInCIE;
47     pint_t    personality;
48     uint32_t  codeAlignFactor;
49     int       dataAlignFactor;
50     bool      isSignalFrame;
51     bool      fdesHaveAugmentationData;
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 = 120
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];
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 != 0) {
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 != 0) {
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 = 0;
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   addressSpace.getULEB128(p, cieContentEnd);
299   // parse augmentation data based on augmentation string
300   const char *result = NULL;
301   if (addressSpace.get8(strStart) == 'z') {
302     // parse augmentation data length
303     addressSpace.getULEB128(p, cieContentEnd);
304     for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
305       switch (addressSpace.get8(s)) {
306       case 'z':
307         cieInfo->fdesHaveAugmentationData = true;
308         break;
309       case 'P':
310         cieInfo->personalityEncoding = addressSpace.get8(p);
311         ++p;
312         cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
313         cieInfo->personality = addressSpace
314             .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
315         break;
316       case 'L':
317         cieInfo->lsdaEncoding = addressSpace.get8(p);
318         ++p;
319         break;
320       case 'R':
321         cieInfo->pointerEncoding = addressSpace.get8(p);
322         ++p;
323         break;
324       case 'S':
325         cieInfo->isSignalFrame = true;
326         break;
327       default:
328         // ignore unknown letters
329         break;
330       }
331     }
332   }
333   cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
334   cieInfo->cieInstructions = p;
335   return result;
336 }
337
338
339 /// "run" the dwarf instructions and create the abstact PrologInfo for an FDE
340 template <typename A>
341 bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
342                                          const FDE_Info &fdeInfo,
343                                          const CIE_Info &cieInfo, pint_t upToPC,
344                                          PrologInfo *results) {
345   // clear results
346   bzero(results, sizeof(PrologInfo));
347   PrologInfoStackEntry *rememberStack = NULL;
348
349   // parse CIE then FDE instructions
350   return parseInstructions(addressSpace, cieInfo.cieInstructions,
351                            cieInfo.cieStart + cieInfo.cieLength, cieInfo,
352                            (pint_t)(-1), rememberStack, results) &&
353          parseInstructions(addressSpace, fdeInfo.fdeInstructions,
354                            fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
355                            upToPC - fdeInfo.pcStart, rememberStack, results);
356 }
357
358 /// "run" the dwarf instructions
359 template <typename A>
360 bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
361                                       pint_t instructionsEnd,
362                                       const CIE_Info &cieInfo, pint_t pcoffset,
363                                       PrologInfoStackEntry *&rememberStack,
364                                       PrologInfo *results) {
365   const bool logDwarf = false;
366   pint_t p = instructions;
367   pint_t codeOffset = 0;
368   PrologInfo initialState = *results;
369   if (logDwarf)
370     fprintf(stderr, "parseInstructions(instructions=0x%0llX)\n",
371             (uint64_t) instructionsEnd);
372
373   // see Dwarf Spec, section 6.4.2 for details on unwind opcodes
374   while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
375     uint64_t reg;
376     uint64_t reg2;
377     int64_t offset;
378     uint64_t length;
379     uint8_t opcode = addressSpace.get8(p);
380     uint8_t operand;
381     PrologInfoStackEntry *entry;
382     ++p;
383     switch (opcode) {
384     case DW_CFA_nop:
385       if (logDwarf)
386         fprintf(stderr, "DW_CFA_nop\n");
387       break;
388     case DW_CFA_set_loc:
389       codeOffset =
390           addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
391       if (logDwarf)
392         fprintf(stderr, "DW_CFA_set_loc\n");
393       break;
394     case DW_CFA_advance_loc1:
395       codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
396       p += 1;
397       if (logDwarf)
398         fprintf(stderr, "DW_CFA_advance_loc1: new offset=%llu\n",
399                         (uint64_t)codeOffset);
400       break;
401     case DW_CFA_advance_loc2:
402       codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
403       p += 2;
404       if (logDwarf)
405         fprintf(stderr, "DW_CFA_advance_loc2: new offset=%llu\n",
406                         (uint64_t)codeOffset);
407       break;
408     case DW_CFA_advance_loc4:
409       codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
410       p += 4;
411       if (logDwarf)
412         fprintf(stderr, "DW_CFA_advance_loc4: new offset=%llu\n",
413                         (uint64_t)codeOffset);
414       break;
415     case DW_CFA_offset_extended:
416       reg = addressSpace.getULEB128(p, instructionsEnd);
417       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
418                                                   * cieInfo.dataAlignFactor;
419       if (reg > kMaxRegisterNumber) {
420         fprintf(stderr,
421                 "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n");
422         return false;
423       }
424       results->savedRegisters[reg].location = kRegisterInCFA;
425       results->savedRegisters[reg].value = offset;
426       if (logDwarf)
427         fprintf(stderr, "DW_CFA_offset_extended(reg=%lld, offset=%lld)\n", reg,
428                 offset);
429       break;
430     case DW_CFA_restore_extended:
431       reg = addressSpace.getULEB128(p, instructionsEnd);
432       ;
433       if (reg > kMaxRegisterNumber) {
434         fprintf(
435             stderr,
436             "malformed DW_CFA_restore_extended dwarf unwind, reg too big\n");
437         return false;
438       }
439       results->savedRegisters[reg] = initialState.savedRegisters[reg];
440       if (logDwarf)
441         fprintf(stderr, "DW_CFA_restore_extended(reg=%lld)\n", reg);
442       break;
443     case DW_CFA_undefined:
444       reg = addressSpace.getULEB128(p, instructionsEnd);
445       if (reg > kMaxRegisterNumber) {
446         fprintf(stderr,
447                 "malformed DW_CFA_undefined dwarf unwind, reg too big\n");
448         return false;
449       }
450       results->savedRegisters[reg].location = kRegisterUnused;
451       if (logDwarf)
452         fprintf(stderr, "DW_CFA_undefined(reg=%lld)\n", reg);
453       break;
454     case DW_CFA_same_value:
455       reg = addressSpace.getULEB128(p, instructionsEnd);
456       if (reg > kMaxRegisterNumber) {
457         fprintf(stderr,
458                 "malformed DW_CFA_same_value dwarf unwind, reg too big\n");
459         return false;
460       }
461       // <rdar://problem/8456377> DW_CFA_same_value unsupported
462       // "same value" means register was stored in frame, but its current
463       // value has not changed, so no need to restore from frame.
464       // We model this as if the register was never saved.
465       results->savedRegisters[reg].location = kRegisterUnused;
466       // set flag to disable conversion to compact unwind
467       results->sameValueUsed = true;
468       if (logDwarf)
469         fprintf(stderr, "DW_CFA_same_value(reg=%lld)\n", reg);
470       break;
471     case DW_CFA_register:
472       reg = addressSpace.getULEB128(p, instructionsEnd);
473       reg2 = addressSpace.getULEB128(p, instructionsEnd);
474       if (reg > kMaxRegisterNumber) {
475         fprintf(stderr,
476                 "malformed DW_CFA_register dwarf unwind, reg too big\n");
477         return false;
478       }
479       if (reg2 > kMaxRegisterNumber) {
480         fprintf(stderr,
481                 "malformed DW_CFA_register dwarf unwind, reg2 too big\n");
482         return false;
483       }
484       results->savedRegisters[reg].location = kRegisterInRegister;
485       results->savedRegisters[reg].value = (int64_t)reg2;
486       // set flag to disable conversion to compact unwind
487       results->registersInOtherRegisters = true;
488       if (logDwarf)
489         fprintf(stderr, "DW_CFA_register(reg=%lld, reg2=%lld)\n", reg, reg2);
490       break;
491     case DW_CFA_remember_state:
492       // avoid operator new, because that would be an upward dependency
493       entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
494       if (entry != NULL) {
495         entry->next = rememberStack;
496         entry->info = *results;
497         rememberStack = entry;
498       } else {
499         return false;
500       }
501       if (logDwarf)
502         fprintf(stderr, "DW_CFA_remember_state\n");
503       break;
504     case DW_CFA_restore_state:
505       if (rememberStack != NULL) {
506         PrologInfoStackEntry *top = rememberStack;
507         *results = top->info;
508         rememberStack = top->next;
509         free((char *)top);
510       } else {
511         return false;
512       }
513       if (logDwarf)
514         fprintf(stderr, "DW_CFA_restore_state\n");
515       break;
516     case DW_CFA_def_cfa:
517       reg = addressSpace.getULEB128(p, instructionsEnd);
518       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
519       if (reg > kMaxRegisterNumber) {
520         fprintf(stderr, "malformed DW_CFA_def_cfa dwarf unwind, reg too big\n");
521         return false;
522       }
523       results->cfaRegister = (uint32_t)reg;
524       results->cfaRegisterOffset = (int32_t)offset;
525       if (logDwarf)
526         fprintf(stderr, "DW_CFA_def_cfa(reg=%lld, offset=%lld)\n", reg, offset);
527       break;
528     case DW_CFA_def_cfa_register:
529       reg = addressSpace.getULEB128(p, instructionsEnd);
530       if (reg > kMaxRegisterNumber) {
531         fprintf(
532             stderr,
533             "malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n");
534         return false;
535       }
536       results->cfaRegister = (uint32_t)reg;
537       if (logDwarf)
538         fprintf(stderr, "DW_CFA_def_cfa_register(%lld)\n", reg);
539       break;
540     case DW_CFA_def_cfa_offset:
541       results->cfaRegisterOffset = (int32_t)
542                                   addressSpace.getULEB128(p, instructionsEnd);
543       results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
544       if (logDwarf)
545         fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n",
546                 results->cfaRegisterOffset);
547       break;
548     case DW_CFA_def_cfa_expression:
549       results->cfaRegister = 0;
550       results->cfaExpression = (int64_t)p;
551       length = addressSpace.getULEB128(p, instructionsEnd);
552       p += length;
553       if (logDwarf)
554         fprintf(stderr,
555                 "DW_CFA_def_cfa_expression(expression=0x%llX, length=%llu)\n",
556                 results->cfaExpression, length);
557       break;
558     case DW_CFA_expression:
559       reg = addressSpace.getULEB128(p, instructionsEnd);
560       if (reg > kMaxRegisterNumber) {
561         fprintf(stderr,
562                 "malformed DW_CFA_expression dwarf unwind, reg too big\n");
563         return false;
564       }
565       results->savedRegisters[reg].location = kRegisterAtExpression;
566       results->savedRegisters[reg].value = (int64_t)p;
567       length = addressSpace.getULEB128(p, instructionsEnd);
568       p += length;
569       if (logDwarf)
570         fprintf(stderr,
571                 "DW_CFA_expression(reg=%lld, expression=0x%llX, length=%llu)\n",
572                 reg, results->savedRegisters[reg].value, length);
573       break;
574     case DW_CFA_offset_extended_sf:
575       reg = addressSpace.getULEB128(p, instructionsEnd);
576       if (reg > kMaxRegisterNumber) {
577         fprintf(
578             stderr,
579             "malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n");
580         return false;
581       }
582       offset =
583           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
584       results->savedRegisters[reg].location = kRegisterInCFA;
585       results->savedRegisters[reg].value = offset;
586       if (logDwarf)
587         fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%lld, offset=%lld)\n",
588                 reg, offset);
589       break;
590     case DW_CFA_def_cfa_sf:
591       reg = addressSpace.getULEB128(p, instructionsEnd);
592       offset =
593           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
594       if (reg > kMaxRegisterNumber) {
595         fprintf(stderr,
596                 "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n");
597         return false;
598       }
599       results->cfaRegister = (uint32_t)reg;
600       results->cfaRegisterOffset = (int32_t)offset;
601       if (logDwarf)
602         fprintf(stderr, "DW_CFA_def_cfa_sf(reg=%lld, offset=%lld)\n", reg,
603                 offset);
604       break;
605     case DW_CFA_def_cfa_offset_sf:
606       results->cfaRegisterOffset = (int32_t)
607         (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor);
608       results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
609       if (logDwarf)
610         fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n",
611                 results->cfaRegisterOffset);
612       break;
613     case DW_CFA_val_offset:
614       reg = addressSpace.getULEB128(p, instructionsEnd);
615       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
616                                                     * cieInfo.dataAlignFactor;
617       results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
618       results->savedRegisters[reg].value = offset;
619       if (logDwarf)
620         fprintf(stderr, "DW_CFA_val_offset(reg=%lld, offset=%lld\n", reg,
621                 offset);
622       break;
623     case DW_CFA_val_offset_sf:
624       reg = addressSpace.getULEB128(p, instructionsEnd);
625       if (reg > kMaxRegisterNumber) {
626         fprintf(stderr,
627                 "malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n");
628         return false;
629       }
630       offset =
631           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
632       results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
633       results->savedRegisters[reg].value = offset;
634       if (logDwarf)
635         fprintf(stderr, "DW_CFA_val_offset_sf(reg=%lld, offset=%lld\n", reg,
636                 offset);
637       break;
638     case DW_CFA_val_expression:
639       reg = addressSpace.getULEB128(p, instructionsEnd);
640       if (reg > kMaxRegisterNumber) {
641         fprintf(stderr,
642                 "malformed DW_CFA_val_expression dwarf unwind, reg too big\n");
643         return false;
644       }
645       results->savedRegisters[reg].location = kRegisterIsExpression;
646       results->savedRegisters[reg].value = (int64_t)p;
647       length = addressSpace.getULEB128(p, instructionsEnd);
648       p += length;
649       if (logDwarf)
650         fprintf(
651             stderr,
652             "DW_CFA_val_expression(reg=%lld, expression=0x%llX, length=%lld)\n",
653             reg, results->savedRegisters[reg].value, length);
654       break;
655     case DW_CFA_GNU_args_size:
656       length = addressSpace.getULEB128(p, instructionsEnd);
657       results->spExtraArgSize = (uint32_t)length;
658       if (logDwarf)
659         fprintf(stderr, "DW_CFA_GNU_args_size(%lld)\n", length);
660       break;
661     case DW_CFA_GNU_negative_offset_extended:
662       reg = addressSpace.getULEB128(p, instructionsEnd);
663       if (reg > kMaxRegisterNumber) {
664         fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended dwarf "
665                         "unwind, reg too big\n");
666         return false;
667       }
668       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
669                                                     * cieInfo.dataAlignFactor;
670       results->savedRegisters[reg].location = kRegisterInCFA;
671       results->savedRegisters[reg].value = -offset;
672       if (logDwarf)
673         fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%lld)\n", offset);
674       break;
675     default:
676       operand = opcode & 0x3F;
677       switch (opcode & 0xC0) {
678       case DW_CFA_offset:
679         reg = operand;
680         offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
681                                                     * cieInfo.dataAlignFactor;
682         results->savedRegisters[reg].location = kRegisterInCFA;
683         results->savedRegisters[reg].value = offset;
684         if (logDwarf)
685           fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%lld)\n", operand,
686                   offset);
687         break;
688       case DW_CFA_advance_loc:
689         codeOffset += operand * cieInfo.codeAlignFactor;
690         if (logDwarf)
691           fprintf(stderr, "DW_CFA_advance_loc: new offset=%llu\n",
692                                                       (uint64_t)codeOffset);
693         break;
694       case DW_CFA_restore:
695         reg = operand;
696         results->savedRegisters[reg] = initialState.savedRegisters[reg];
697         if (logDwarf)
698           fprintf(stderr, "DW_CFA_restore(reg=%lld)\n", reg);
699         break;
700       default:
701         if (logDwarf)
702           fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode);
703         return false;
704       }
705     }
706   }
707
708   return true;
709 }
710
711 } // namespace libunwind
712
713 #endif // __DWARF_PARSER_HPP__