xref: /freebsd/contrib/llvm-project/libunwind/src/DwarfParser.hpp (revision 18054d0220cfc8df9c9568c437bd6fbb59d53c3c)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //
8 //  Parses DWARF CFIs (FDEs and CIEs).
9 //
10 //===----------------------------------------------------------------------===//
11 
12 #ifndef __DWARF_PARSER_HPP__
13 #define __DWARF_PARSER_HPP__
14 
15 #include <inttypes.h>
16 #include <stdint.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 
20 #include "libunwind.h"
21 #include "dwarf2.h"
22 #include "Registers.hpp"
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 #if defined(_LIBUNWIND_TARGET_AARCH64)
53     bool      addressesSignedWithBKey;
54 #endif
55   };
56 
57   /// Information about an FDE (Frame Description Entry)
58   struct FDE_Info {
59     pint_t  fdeStart;
60     pint_t  fdeLength;
61     pint_t  fdeInstructions;
62     pint_t  pcStart;
63     pint_t  pcEnd;
64     pint_t  lsda;
65   };
66 
67   enum {
68     kMaxRegisterNumber = _LIBUNWIND_HIGHEST_DWARF_REGISTER
69   };
70   enum RegisterSavedWhere {
71     kRegisterUnused,
72     kRegisterInCFA,
73     kRegisterInCFADecrypt, // sparc64 specific
74     kRegisterOffsetFromCFA,
75     kRegisterInRegister,
76     kRegisterAtExpression,
77     kRegisterIsExpression
78   };
79   struct RegisterLocation {
80     RegisterSavedWhere location;
81     bool initialStateSaved;
82     int64_t value;
83   };
84   /// Information about a frame layout and registers saved determined
85   /// by "running" the DWARF FDE "instructions"
86   struct PrologInfo {
87     uint32_t          cfaRegister;
88     int32_t           cfaRegisterOffset;  // CFA = (cfaRegister)+cfaRegisterOffset
89     int64_t           cfaExpression;      // CFA = expression
90     uint32_t          spExtraArgSize;
91     RegisterLocation  savedRegisters[kMaxRegisterNumber + 1];
92     enum class InitializeTime { kLazy, kNormal };
93 
94     // When saving registers, this data structure is lazily initialized.
95     PrologInfo(InitializeTime IT = InitializeTime::kNormal) {
96       if (IT == InitializeTime::kNormal)
97         memset(this, 0, sizeof(*this));
98     }
99     void checkSaveRegister(uint64_t reg, PrologInfo &initialState) {
100       if (!savedRegisters[reg].initialStateSaved) {
101         initialState.savedRegisters[reg] = savedRegisters[reg];
102         savedRegisters[reg].initialStateSaved = true;
103       }
104     }
105     void setRegister(uint64_t reg, RegisterSavedWhere newLocation,
106                      int64_t newValue, PrologInfo &initialState) {
107       checkSaveRegister(reg, initialState);
108       savedRegisters[reg].location = newLocation;
109       savedRegisters[reg].value = newValue;
110     }
111     void setRegisterLocation(uint64_t reg, RegisterSavedWhere newLocation,
112                              PrologInfo &initialState) {
113       checkSaveRegister(reg, initialState);
114       savedRegisters[reg].location = newLocation;
115     }
116     void setRegisterValue(uint64_t reg, int64_t newValue,
117                           PrologInfo &initialState) {
118       checkSaveRegister(reg, initialState);
119       savedRegisters[reg].value = newValue;
120     }
121     void restoreRegisterToInitialState(uint64_t reg, PrologInfo &initialState) {
122       if (savedRegisters[reg].initialStateSaved)
123         savedRegisters[reg] = initialState.savedRegisters[reg];
124       // else the register still holds its initial state
125     }
126   };
127 
128   struct PrologInfoStackEntry {
129     PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
130         : next(n), info(i) {}
131     PrologInfoStackEntry *next;
132     PrologInfo info;
133   };
134 
135   struct RememberStack {
136     PrologInfoStackEntry *entry;
137     RememberStack() : entry(nullptr) {}
138     ~RememberStack() {
139 #if defined(_LIBUNWIND_REMEMBER_CLEANUP_NEEDED)
140       // Clean up rememberStack. Even in the case where every
141       // DW_CFA_remember_state is paired with a DW_CFA_restore_state,
142       // parseInstructions can skip restore opcodes if it reaches the target PC
143       // and stops interpreting, so we have to make sure we don't leak memory.
144       while (entry) {
145         PrologInfoStackEntry *next = entry->next;
146         _LIBUNWIND_REMEMBER_FREE(entry);
147         entry = next;
148       }
149 #endif
150     }
151   };
152 
153   static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
154                       size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
155                       CIE_Info *cieInfo);
156   static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
157                                FDE_Info *fdeInfo, CIE_Info *cieInfo,
158                                bool useCIEInfo = false);
159   static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
160                                    const CIE_Info &cieInfo, pint_t upToPC,
161                                    int arch, PrologInfo *results);
162 
163   static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
164 };
165 
166 /// Parse a FDE into a CIE_Info and an FDE_Info. If useCIEInfo is
167 /// true, treat cieInfo as already-parsed CIE_Info (whose start offset
168 /// must match the one specified by the FDE) rather than parsing the
169 /// one indicated within the FDE.
170 template <typename A>
171 const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
172                                      FDE_Info *fdeInfo, CIE_Info *cieInfo,
173                                      bool useCIEInfo) {
174   pint_t p = fdeStart;
175   pint_t cfiLength = (pint_t)addressSpace.get32(p);
176   p += 4;
177   if (cfiLength == 0xffffffff) {
178     // 0xffffffff means length is really next 8 bytes
179     cfiLength = (pint_t)addressSpace.get64(p);
180     p += 8;
181   }
182   if (cfiLength == 0)
183     return "FDE has zero length"; // zero terminator
184   uint32_t ciePointer = addressSpace.get32(p);
185   if (ciePointer == 0)
186     return "FDE is really a CIE"; // this is a CIE not an FDE
187   pint_t nextCFI = p + cfiLength;
188   pint_t cieStart = p - ciePointer;
189   if (useCIEInfo) {
190     if (cieInfo->cieStart != cieStart)
191       return "CIE start does not match";
192   } else {
193     const char *err = parseCIE(addressSpace, cieStart, cieInfo);
194     if (err != NULL)
195       return err;
196   }
197   p += 4;
198   // Parse pc begin and range.
199   pint_t pcStart =
200       addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
201   pint_t pcRange =
202       addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
203   // Parse rest of info.
204   fdeInfo->lsda = 0;
205   // Check for augmentation length.
206   if (cieInfo->fdesHaveAugmentationData) {
207     pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
208     pint_t endOfAug = p + augLen;
209     if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
210       // Peek at value (without indirection).  Zero means no LSDA.
211       pint_t lsdaStart = p;
212       if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) !=
213           0) {
214         // Reset pointer and re-parse LSDA address.
215         p = lsdaStart;
216         fdeInfo->lsda =
217             addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
218       }
219     }
220     p = endOfAug;
221   }
222   fdeInfo->fdeStart = fdeStart;
223   fdeInfo->fdeLength = nextCFI - fdeStart;
224   fdeInfo->fdeInstructions = p;
225   fdeInfo->pcStart = pcStart;
226   fdeInfo->pcEnd = pcStart + pcRange;
227   return NULL; // success
228 }
229 
230 /// Scan an eh_frame section to find an FDE for a pc
231 template <typename A>
232 bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
233                             size_t sectionLength, pint_t fdeHint,
234                             FDE_Info *fdeInfo, CIE_Info *cieInfo) {
235   //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
236   pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
237   const pint_t ehSectionEnd = (sectionLength == SIZE_MAX)
238                                   ? static_cast<pint_t>(-1)
239                                   : (ehSectionStart + sectionLength);
240   while (p < ehSectionEnd) {
241     pint_t currentCFI = p;
242     //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
243     pint_t cfiLength = addressSpace.get32(p);
244     p += 4;
245     if (cfiLength == 0xffffffff) {
246       // 0xffffffff means length is really next 8 bytes
247       cfiLength = (pint_t)addressSpace.get64(p);
248       p += 8;
249     }
250     if (cfiLength == 0)
251       return false; // zero terminator
252     uint32_t id = addressSpace.get32(p);
253     if (id == 0) {
254       // Skip over CIEs.
255       p += cfiLength;
256     } else {
257       // Process FDE to see if it covers pc.
258       pint_t nextCFI = p + cfiLength;
259       uint32_t ciePointer = addressSpace.get32(p);
260       pint_t cieStart = p - ciePointer;
261       // Validate pointer to CIE is within section.
262       if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) {
263         if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) {
264           p += 4;
265           // Parse pc begin and range.
266           pint_t pcStart =
267               addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
268           pint_t pcRange = addressSpace.getEncodedP(
269               p, nextCFI, cieInfo->pointerEncoding & 0x0F);
270           // Test if pc is within the function this FDE covers.
271           if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
272             // parse rest of info
273             fdeInfo->lsda = 0;
274             // check for augmentation length
275             if (cieInfo->fdesHaveAugmentationData) {
276               pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
277               pint_t endOfAug = p + augLen;
278               if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
279                 // Peek at value (without indirection).  Zero means no LSDA.
280                 pint_t lsdaStart = p;
281                 if (addressSpace.getEncodedP(
282                         p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) {
283                   // Reset pointer and re-parse LSDA address.
284                   p = lsdaStart;
285                   fdeInfo->lsda = addressSpace
286                       .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
287                 }
288               }
289               p = endOfAug;
290             }
291             fdeInfo->fdeStart = currentCFI;
292             fdeInfo->fdeLength = nextCFI - currentCFI;
293             fdeInfo->fdeInstructions = p;
294             fdeInfo->pcStart = pcStart;
295             fdeInfo->pcEnd = pcStart + pcRange;
296             return true;
297           } else {
298             // pc is not in begin/range, skip this FDE
299           }
300         } else {
301           // Malformed CIE, now augmentation describing pc range encoding.
302         }
303       } else {
304         // malformed FDE.  CIE is bad
305       }
306       p = nextCFI;
307     }
308   }
309   return false;
310 }
311 
312 /// Extract info from a CIE
313 template <typename A>
314 const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
315                                     CIE_Info *cieInfo) {
316   cieInfo->pointerEncoding = 0;
317   cieInfo->lsdaEncoding = DW_EH_PE_omit;
318   cieInfo->personalityEncoding = 0;
319   cieInfo->personalityOffsetInCIE = 0;
320   cieInfo->personality = 0;
321   cieInfo->codeAlignFactor = 0;
322   cieInfo->dataAlignFactor = 0;
323   cieInfo->isSignalFrame = false;
324   cieInfo->fdesHaveAugmentationData = false;
325 #if defined(_LIBUNWIND_TARGET_AARCH64)
326   cieInfo->addressesSignedWithBKey = false;
327 #endif
328   cieInfo->cieStart = cie;
329   pint_t p = cie;
330   pint_t cieLength = (pint_t)addressSpace.get32(p);
331   p += 4;
332   pint_t cieContentEnd = p + cieLength;
333   if (cieLength == 0xffffffff) {
334     // 0xffffffff means length is really next 8 bytes
335     cieLength = (pint_t)addressSpace.get64(p);
336     p += 8;
337     cieContentEnd = p + cieLength;
338   }
339   if (cieLength == 0)
340     return NULL;
341   // CIE ID is always 0
342   if (addressSpace.get32(p) != 0)
343     return "CIE ID is not zero";
344   p += 4;
345   // Version is always 1 or 3
346   uint8_t version = addressSpace.get8(p);
347   if ((version != 1) && (version != 3))
348     return "CIE version is not 1 or 3";
349   ++p;
350   // save start of augmentation string and find end
351   pint_t strStart = p;
352   while (addressSpace.get8(p) != 0)
353     ++p;
354   ++p;
355   // parse code aligment factor
356   cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd);
357   // parse data alignment factor
358   cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
359   // parse return address register
360   uint64_t raReg = (version == 1) ? addressSpace.get8(p++)
361                                   : addressSpace.getULEB128(p, cieContentEnd);
362   assert(raReg < 255 && "return address register too large");
363   cieInfo->returnAddressRegister = (uint8_t)raReg;
364   // parse augmentation data based on augmentation string
365   const char *result = NULL;
366   if (addressSpace.get8(strStart) == 'z') {
367     // parse augmentation data length
368     addressSpace.getULEB128(p, cieContentEnd);
369     for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
370       switch (addressSpace.get8(s)) {
371       case 'z':
372         cieInfo->fdesHaveAugmentationData = true;
373         break;
374       case 'P':
375         cieInfo->personalityEncoding = addressSpace.get8(p);
376         ++p;
377         cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
378         cieInfo->personality = addressSpace
379             .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
380         break;
381       case 'L':
382         cieInfo->lsdaEncoding = addressSpace.get8(p);
383         ++p;
384         break;
385       case 'R':
386         cieInfo->pointerEncoding = addressSpace.get8(p);
387         ++p;
388         break;
389       case 'S':
390         cieInfo->isSignalFrame = true;
391         break;
392 #if defined(_LIBUNWIND_TARGET_AARCH64)
393       case 'B':
394         cieInfo->addressesSignedWithBKey = true;
395         break;
396 #endif
397       default:
398         // ignore unknown letters
399         break;
400       }
401     }
402   }
403   cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
404   cieInfo->cieInstructions = p;
405   return result;
406 }
407 
408 
409 /// "run" the DWARF instructions and create the abstact PrologInfo for an FDE
410 template <typename A>
411 bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
412                                          const FDE_Info &fdeInfo,
413                                          const CIE_Info &cieInfo, pint_t upToPC,
414                                          int arch, PrologInfo *results) {
415   // Alloca is used for the allocation of the rememberStack entries. It removes
416   // the dependency on new/malloc but the below for loop can not be refactored
417   // into functions. Entry could be saved during the processing of a CIE and
418   // restored by an FDE.
419   RememberStack rememberStack;
420 
421   struct ParseInfo {
422     pint_t instructions;
423     pint_t instructionsEnd;
424     pint_t pcoffset;
425   };
426 
427   ParseInfo parseInfoArray[] = {
428       {cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength,
429        (pint_t)(-1)},
430       {fdeInfo.fdeInstructions, fdeInfo.fdeStart + fdeInfo.fdeLength,
431        upToPC - fdeInfo.pcStart}};
432 
433   for (const auto &info : parseInfoArray) {
434     pint_t p = info.instructions;
435     pint_t instructionsEnd = info.instructionsEnd;
436     pint_t pcoffset = info.pcoffset;
437     pint_t codeOffset = 0;
438 
439     // initialState initialized as registers in results are modified. Use
440     // PrologInfo accessor functions to avoid reading uninitialized data.
441     PrologInfo initialState(PrologInfo::InitializeTime::kLazy);
442 
443     _LIBUNWIND_TRACE_DWARF("parseFDEInstructions(instructions=0x%0" PRIx64
444                            ")\n",
445                            static_cast<uint64_t>(instructionsEnd));
446 
447     // see DWARF Spec, section 6.4.2 for details on unwind opcodes
448     while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
449       uint64_t reg;
450       uint64_t reg2;
451       int64_t offset;
452       uint64_t length;
453       uint8_t opcode = addressSpace.get8(p);
454       uint8_t operand;
455 
456       ++p;
457       switch (opcode) {
458       case DW_CFA_nop:
459         _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n");
460         break;
461       case DW_CFA_set_loc:
462         codeOffset = addressSpace.getEncodedP(p, instructionsEnd,
463                                               cieInfo.pointerEncoding);
464         _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n");
465         break;
466       case DW_CFA_advance_loc1:
467         codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
468         p += 1;
469         _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n",
470                                static_cast<uint64_t>(codeOffset));
471         break;
472       case DW_CFA_advance_loc2:
473         codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
474         p += 2;
475         _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n",
476                                static_cast<uint64_t>(codeOffset));
477         break;
478       case DW_CFA_advance_loc4:
479         codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
480         p += 4;
481         _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n",
482                                static_cast<uint64_t>(codeOffset));
483         break;
484       case DW_CFA_offset_extended:
485         reg = addressSpace.getULEB128(p, instructionsEnd);
486         offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) *
487                  cieInfo.dataAlignFactor;
488         if (reg > kMaxRegisterNumber) {
489           _LIBUNWIND_LOG0(
490               "malformed DW_CFA_offset_extended DWARF unwind, reg too big");
491           return false;
492         }
493         results->setRegister(reg, kRegisterInCFA, offset, initialState);
494         _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", "
495                                "offset=%" PRId64 ")\n",
496                                reg, offset);
497         break;
498       case DW_CFA_restore_extended:
499         reg = addressSpace.getULEB128(p, instructionsEnd);
500         if (reg > kMaxRegisterNumber) {
501           _LIBUNWIND_LOG0(
502               "malformed DW_CFA_restore_extended DWARF unwind, reg too big");
503           return false;
504         }
505         results->restoreRegisterToInitialState(reg, initialState);
506         _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n",
507                                reg);
508         break;
509       case DW_CFA_undefined:
510         reg = addressSpace.getULEB128(p, instructionsEnd);
511         if (reg > kMaxRegisterNumber) {
512           _LIBUNWIND_LOG0(
513               "malformed DW_CFA_undefined DWARF unwind, reg too big");
514           return false;
515         }
516         results->setRegisterLocation(reg, kRegisterUnused, initialState);
517         _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg);
518         break;
519       case DW_CFA_same_value:
520         reg = addressSpace.getULEB128(p, instructionsEnd);
521         if (reg > kMaxRegisterNumber) {
522           _LIBUNWIND_LOG0(
523               "malformed DW_CFA_same_value DWARF unwind, reg too big");
524           return false;
525         }
526         // <rdar://problem/8456377> DW_CFA_same_value unsupported
527         // "same value" means register was stored in frame, but its current
528         // value has not changed, so no need to restore from frame.
529         // We model this as if the register was never saved.
530         results->setRegisterLocation(reg, kRegisterUnused, initialState);
531         _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg);
532         break;
533       case DW_CFA_register:
534         reg = addressSpace.getULEB128(p, instructionsEnd);
535         reg2 = addressSpace.getULEB128(p, instructionsEnd);
536         if (reg > kMaxRegisterNumber) {
537           _LIBUNWIND_LOG0(
538               "malformed DW_CFA_register DWARF unwind, reg too big");
539           return false;
540         }
541         if (reg2 > kMaxRegisterNumber) {
542           _LIBUNWIND_LOG0(
543               "malformed DW_CFA_register DWARF unwind, reg2 too big");
544           return false;
545         }
546         results->setRegister(reg, kRegisterInRegister, (int64_t)reg2,
547                              initialState);
548         _LIBUNWIND_TRACE_DWARF(
549             "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2);
550         break;
551       case DW_CFA_remember_state: {
552         // Avoid operator new because that would be an upward dependency.
553         // Avoid malloc because it needs heap allocation.
554         PrologInfoStackEntry *entry =
555             (PrologInfoStackEntry *)_LIBUNWIND_REMEMBER_ALLOC(
556                 sizeof(PrologInfoStackEntry));
557         if (entry != NULL) {
558           entry->next = rememberStack.entry;
559           entry->info = *results;
560           rememberStack.entry = entry;
561         } else {
562           return false;
563         }
564         _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n");
565         break;
566       }
567       case DW_CFA_restore_state:
568         if (rememberStack.entry != NULL) {
569           PrologInfoStackEntry *top = rememberStack.entry;
570           *results = top->info;
571           rememberStack.entry = top->next;
572           _LIBUNWIND_REMEMBER_FREE(top);
573         } else {
574           return false;
575         }
576         _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n");
577         break;
578       case DW_CFA_def_cfa:
579         reg = addressSpace.getULEB128(p, instructionsEnd);
580         offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
581         if (reg > kMaxRegisterNumber) {
582           _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big");
583           return false;
584         }
585         results->cfaRegister = (uint32_t)reg;
586         results->cfaRegisterOffset = (int32_t)offset;
587         _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64
588                                ")\n",
589                                reg, offset);
590         break;
591       case DW_CFA_def_cfa_register:
592         reg = addressSpace.getULEB128(p, instructionsEnd);
593         if (reg > kMaxRegisterNumber) {
594           _LIBUNWIND_LOG0(
595               "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big");
596           return false;
597         }
598         results->cfaRegister = (uint32_t)reg;
599         _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg);
600         break;
601       case DW_CFA_def_cfa_offset:
602         results->cfaRegisterOffset =
603             (int32_t)addressSpace.getULEB128(p, instructionsEnd);
604         _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n",
605                                results->cfaRegisterOffset);
606         break;
607       case DW_CFA_def_cfa_expression:
608         results->cfaRegister = 0;
609         results->cfaExpression = (int64_t)p;
610         length = addressSpace.getULEB128(p, instructionsEnd);
611         assert(length < static_cast<pint_t>(~0) && "pointer overflow");
612         p += static_cast<pint_t>(length);
613         _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64
614                                ", length=%" PRIu64 ")\n",
615                                results->cfaExpression, length);
616         break;
617       case DW_CFA_expression:
618         reg = addressSpace.getULEB128(p, instructionsEnd);
619         if (reg > kMaxRegisterNumber) {
620           _LIBUNWIND_LOG0(
621               "malformed DW_CFA_expression DWARF unwind, reg too big");
622           return false;
623         }
624         results->setRegister(reg, kRegisterAtExpression, (int64_t)p,
625                              initialState);
626         length = addressSpace.getULEB128(p, instructionsEnd);
627         assert(length < static_cast<pint_t>(~0) && "pointer overflow");
628         p += static_cast<pint_t>(length);
629         _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", "
630                                "expression=0x%" PRIx64 ", "
631                                "length=%" PRIu64 ")\n",
632                                reg, results->savedRegisters[reg].value, length);
633         break;
634       case DW_CFA_offset_extended_sf:
635         reg = addressSpace.getULEB128(p, instructionsEnd);
636         if (reg > kMaxRegisterNumber) {
637           _LIBUNWIND_LOG0(
638               "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big");
639           return false;
640         }
641         offset = addressSpace.getSLEB128(p, instructionsEnd) *
642                  cieInfo.dataAlignFactor;
643         results->setRegister(reg, kRegisterInCFA, offset, initialState);
644         _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", "
645                                "offset=%" PRId64 ")\n",
646                                reg, offset);
647         break;
648       case DW_CFA_def_cfa_sf:
649         reg = addressSpace.getULEB128(p, instructionsEnd);
650         offset = addressSpace.getSLEB128(p, instructionsEnd) *
651                  cieInfo.dataAlignFactor;
652         if (reg > kMaxRegisterNumber) {
653           _LIBUNWIND_LOG0(
654               "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big");
655           return false;
656         }
657         results->cfaRegister = (uint32_t)reg;
658         results->cfaRegisterOffset = (int32_t)offset;
659         _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", "
660                                "offset=%" PRId64 ")\n",
661                                reg, offset);
662         break;
663       case DW_CFA_def_cfa_offset_sf:
664         results->cfaRegisterOffset =
665             (int32_t)(addressSpace.getSLEB128(p, instructionsEnd) *
666                       cieInfo.dataAlignFactor);
667         _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n",
668                                results->cfaRegisterOffset);
669         break;
670       case DW_CFA_val_offset:
671         reg = addressSpace.getULEB128(p, instructionsEnd);
672         if (reg > kMaxRegisterNumber) {
673           _LIBUNWIND_LOG(
674               "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64
675               ") out of range\n",
676               reg);
677           return false;
678         }
679         offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) *
680                  cieInfo.dataAlignFactor;
681         results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState);
682         _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", "
683                                "offset=%" PRId64 "\n",
684                                reg, offset);
685         break;
686       case DW_CFA_val_offset_sf:
687         reg = addressSpace.getULEB128(p, instructionsEnd);
688         if (reg > kMaxRegisterNumber) {
689           _LIBUNWIND_LOG0(
690               "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big");
691           return false;
692         }
693         offset = addressSpace.getSLEB128(p, instructionsEnd) *
694                  cieInfo.dataAlignFactor;
695         results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState);
696         _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", "
697                                "offset=%" PRId64 "\n",
698                                reg, offset);
699         break;
700       case DW_CFA_val_expression:
701         reg = addressSpace.getULEB128(p, instructionsEnd);
702         if (reg > kMaxRegisterNumber) {
703           _LIBUNWIND_LOG0(
704               "malformed DW_CFA_val_expression DWARF unwind, reg too big");
705           return false;
706         }
707         results->setRegister(reg, kRegisterIsExpression, (int64_t)p,
708                              initialState);
709         length = addressSpace.getULEB128(p, instructionsEnd);
710         assert(length < static_cast<pint_t>(~0) && "pointer overflow");
711         p += static_cast<pint_t>(length);
712         _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", "
713                                "expression=0x%" PRIx64 ", length=%" PRIu64
714                                ")\n",
715                                reg, results->savedRegisters[reg].value, length);
716         break;
717       case DW_CFA_GNU_args_size:
718         length = addressSpace.getULEB128(p, instructionsEnd);
719         results->spExtraArgSize = (uint32_t)length;
720         _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length);
721         break;
722       case DW_CFA_GNU_negative_offset_extended:
723         reg = addressSpace.getULEB128(p, instructionsEnd);
724         if (reg > kMaxRegisterNumber) {
725           _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF "
726                           "unwind, reg too big");
727           return false;
728         }
729         offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) *
730                  cieInfo.dataAlignFactor;
731         results->setRegister(reg, kRegisterInCFA, -offset, initialState);
732         _LIBUNWIND_TRACE_DWARF(
733             "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset);
734         break;
735 
736 #if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) || \
737     defined(_LIBUNWIND_TARGET_SPARC64)
738         // The same constant is used to represent different instructions on
739         // AArch64 (negate_ra_state) and SPARC (window_save).
740         static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save,
741                       "uses the same constant");
742       case DW_CFA_AARCH64_negate_ra_state:
743         switch (arch) {
744 #if defined(_LIBUNWIND_TARGET_AARCH64)
745         case REGISTERS_ARM64: {
746           int64_t value =
747               results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x1;
748           results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value,
749                                     initialState);
750           _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n");
751         } break;
752 #endif
753 
754 #if defined(_LIBUNWIND_TARGET_SPARC)
755         // case DW_CFA_GNU_window_save:
756         case REGISTERS_SPARC:
757           _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n");
758           for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) {
759             results->setRegister(reg, kRegisterInRegister,
760                                  ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0,
761                                  initialState);
762           }
763 
764           for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
765             results->setRegister(reg, kRegisterInCFA,
766                                  ((int64_t)reg - UNW_SPARC_L0) * 4,
767                                  initialState);
768           }
769           break;
770 #endif
771 
772 #if defined(_LIBUNWIND_TARGET_SPARC64)
773         // case DW_CFA_GNU_window_save:
774         case REGISTERS_SPARC64:
775           // Don't save %o0-%o7 on sparc64.
776           // https://reviews.llvm.org/D32450#736405
777 
778           for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
779             if (reg == UNW_SPARC_I7)
780               results->setRegister(
781                   reg, kRegisterInCFADecrypt,
782                   static_cast<int64_t>((reg - UNW_SPARC_L0) * sizeof(pint_t)),
783                   initialState);
784             else
785               results->setRegister(
786                   reg, kRegisterInCFA,
787                   static_cast<int64_t>((reg - UNW_SPARC_L0) * sizeof(pint_t)),
788                   initialState);
789           }
790           _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save\n");
791           break;
792 #endif
793         }
794         break;
795 
796 #else
797         (void)arch;
798 #endif
799 
800       default:
801         operand = opcode & 0x3F;
802         switch (opcode & 0xC0) {
803         case DW_CFA_offset:
804           reg = operand;
805           if (reg > kMaxRegisterNumber) {
806             _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
807                            ") out of range",
808                            reg);
809             return false;
810           }
811           offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) *
812                    cieInfo.dataAlignFactor;
813           results->setRegister(reg, kRegisterInCFA, offset, initialState);
814           _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n",
815                                  operand, offset);
816           break;
817         case DW_CFA_advance_loc:
818           codeOffset += operand * cieInfo.codeAlignFactor;
819           _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n",
820                                  static_cast<uint64_t>(codeOffset));
821           break;
822         case DW_CFA_restore:
823           reg = operand;
824           if (reg > kMaxRegisterNumber) {
825             _LIBUNWIND_LOG(
826                 "malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
827                 ") out of range",
828                 reg);
829             return false;
830           }
831           results->restoreRegisterToInitialState(reg, initialState);
832           _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n",
833                                  static_cast<uint64_t>(operand));
834           break;
835         default:
836           _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode);
837           return false;
838         }
839       }
840     }
841   }
842   return true;
843 }
844 
845 } // namespace libunwind
846 
847 #endif // __DWARF_PARSER_HPP__
848