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