Unwind-EHABI.cpp revision 5fcb7c5bdd98aab09c6a462ca69e61d8e9f42104
1e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert//===--------------------------- Unwind-EHABI.cpp -------------------------===//
2e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert//
3e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert//                     The LLVM Compiler Infrastructure
4e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert//
5e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert// This file is dual licensed under the MIT and the University of Illinois Open
6e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert// Source Licenses. See LICENSE.TXT for details.
7e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert//
8e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert//
9e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert//  Implements ARM zero-cost C++ exceptions
10e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert//
11e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert//===----------------------------------------------------------------------===//
12e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
13e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include <unwind.h>
14e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
15e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include <stdbool.h>
16e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include <stdint.h>
17e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include <stdio.h>
18e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include <stdlib.h>
19e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include <string.h>
20e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
21e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include "config.h"
22e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include "libunwind.h"
232cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert#include "libunwind_ext.h"
24e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include "unwind.h"
25e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include "../private_typeinfo.h"
26e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
27e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if LIBCXXABI_ARM_EHABI
28e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertnamespace {
29e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
30e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert// Strange order: take words in order, but inside word, take from most to least
31e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert// signinficant byte.
322cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albertuint8_t getByte(const uint32_t* data, size_t offset) {
332cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert  const uint8_t* byteData = reinterpret_cast<const uint8_t*>(data);
34e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))];
35e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
36e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
37e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertconst char* getNextWord(const char* data, uint32_t* out) {
38e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  *out = *reinterpret_cast<const uint32_t*>(data);
39e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return data + 4;
40e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
41e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
42e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertconst char* getNextNibble(const char* data, uint32_t* out) {
43e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  *out = *reinterpret_cast<const uint16_t*>(data);
44e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return data + 2;
45e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
46e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
47e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertstatic inline uint32_t signExtendPrel31(uint32_t data) {
48e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return data | ((data & 0x40000000u) << 1);
49e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
50e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
51e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertstruct Descriptor {
52e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert   // See # 9.2
53e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert   typedef enum {
54e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert     SU16 = 0, // Short descriptor, 16-bit entries
55e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert     LU16 = 1, // Long descriptor,  16-bit entries
56e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert     LU32 = 3, // Long descriptor,  32-bit entries
57e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert     RESERVED0 =  4, RESERVED1 =  5, RESERVED2  = 6,  RESERVED3  =  7,
58e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert     RESERVED4 =  8, RESERVED5 =  9, RESERVED6  = 10, RESERVED7  = 11,
59e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert     RESERVED8 = 12, RESERVED9 = 13, RESERVED10 = 14, RESERVED11 = 15
60e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert   } Format;
61e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
62e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert   // See # 9.2
63e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert   typedef enum {
64e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert     CLEANUP = 0x0,
65e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert     FUNC    = 0x1,
66e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert     CATCH   = 0x2,
67e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert     INVALID = 0x4
68e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert   } Kind;
69e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert};
70e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
71e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_Unwind_Reason_Code ProcessDescriptors(
72e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_State state,
73e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Control_Block* ucbp,
74e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    struct _Unwind_Context* context,
75e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    Descriptor::Format format,
76e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    const char* descriptorStart,
77e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uint32_t flags) {
78e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
79e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // EHT is inlined in the index using compact form. No descriptors. #5
80e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (flags & 0x1)
81e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    return _URC_CONTINUE_UNWIND;
82e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
83e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // TODO: We should check the state here, and determine whether we need to
84e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // perform phase1 or phase2 unwinding.
85e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  (void)state;
86e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
87e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  const char* descriptor = descriptorStart;
88e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  uint32_t descriptorWord;
89e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  getNextWord(descriptor, &descriptorWord);
90e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  while (descriptorWord) {
91e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // Read descriptor based on # 9.2.
92e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uint32_t length;
93e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uint32_t offset;
94e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    switch (format) {
95e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case Descriptor::LU32:
96e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        descriptor = getNextWord(descriptor, &length);
97e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        descriptor = getNextWord(descriptor, &offset);
98e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case Descriptor::LU16:
99e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        descriptor = getNextNibble(descriptor, &length);
100e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        descriptor = getNextNibble(descriptor, &offset);
101e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      default:
102e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        assert(false);
103e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _URC_FAILURE;
104e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
105e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
106e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // See # 9.2 table for decoding the kind of descriptor. It's a 2-bit value.
107e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    Descriptor::Kind kind =
108e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        static_cast<Descriptor::Kind>((length & 0x1) | ((offset & 0x1) << 1));
109e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
110e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // Clear off flag from last bit.
111e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    length &= ~1u;
112e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    offset &= ~1u;
113e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uintptr_t scopeStart = ucbp->pr_cache.fnstart + offset;
114e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uintptr_t scopeEnd = scopeStart + length;
115e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uintptr_t pc = _Unwind_GetIP(context);
116e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    bool isInScope = (scopeStart <= pc) && (pc < scopeEnd);
117e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
118e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    switch (kind) {
119e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case Descriptor::CLEANUP: {
120e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // TODO(ajwong): Handle cleanup descriptors.
121e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        break;
122e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
123e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case Descriptor::FUNC: {
124e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // TODO(ajwong): Handle function descriptors.
125e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        break;
126e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
127e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case Descriptor::CATCH: {
128e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // Catch descriptors require gobbling one more word.
129e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        uint32_t landing_pad;
130e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        descriptor = getNextWord(descriptor, &landing_pad);
131e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
132e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        if (isInScope) {
133e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          // TODO(ajwong): This is only phase1 compatible logic. Implement
134e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          // phase2.
135e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          landing_pad = signExtendPrel31(landing_pad & ~0x80000000);
136e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          if (landing_pad == 0xffffffff) {
137e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            return _URC_HANDLER_FOUND;
138e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          } else if (landing_pad == 0xfffffffe ) {
139e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            return _URC_FAILURE;
140e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          } else {
141e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            /*
142e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            bool is_reference_type = landing_pad & 0x80000000;
143e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            void* matched_object;
144e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            if (__cxxabiv1::__cxa_type_match(
145e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                    ucbp, reinterpret_cast<const std::type_info *>(landing_pad),
146e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                    is_reference_type,
147e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                    &matched_object) != __cxxabiv1::ctm_failed)
148e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                return _URC_HANDLER_FOUND;
149e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                */
150e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            _LIBUNWIND_ABORT("Type matching not implemented");
151e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          }
152e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        }
153e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        break;
154e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
155e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      default:
156e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        _LIBUNWIND_ABORT("Invalid descriptor kind found.");
157e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    };
158e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
159e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    getNextWord(descriptor, &descriptorWord);
160e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
161e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
162e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return _URC_CONTINUE_UNWIND;
163e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
164e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
165e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_Unwind_Reason_Code unwindOneFrame(
166e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_State state,
167e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Control_Block* ucbp,
168e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    struct _Unwind_Context* context) {
169e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // Read the compact model EHT entry's header # 6.3
1702cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert  const uint32_t* unwindingData = ucbp->pr_cache.ehtp;
1712cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert  assert((*unwindingData & 0xf0000000) == 0x80000000 && "Must be a compact entry");
172e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  Descriptor::Format format =
1732cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert      static_cast<Descriptor::Format>((*unwindingData & 0x0f000000) >> 24);
174e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  size_t len = 0;
1752cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert  size_t off = 0;
1762cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert  unwindingData = decode_eht_entry(unwindingData, &off, &len);
1772cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert  if (unwindingData == nullptr) {
1782cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert    return _URC_FAILURE;
179e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
180e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
181e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // Handle descriptors before unwinding so they are processed in the context
182e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // of the correct stack frame.
183e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _Unwind_Reason_Code result =
184e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      ProcessDescriptors(
185e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          state, ucbp, context, format,
186e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          reinterpret_cast<const char*>(ucbp->pr_cache.ehtp) + len,
187e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          ucbp->pr_cache.additional);
188e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
189e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (result != _URC_CONTINUE_UNWIND)
190e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    return result;
191e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
1922cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert  return _Unwind_VRS_Interpret(context, unwindingData, off, len);
193e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
194e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
195e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_CORE /
196e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert// _UVRSD_UINT32.
197e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertuint32_t RegisterMask(uint8_t start, uint8_t count_minus_one) {
198e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return ((1U << (count_minus_one + 1)) - 1) << start;
199e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
200e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
201e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_VFP /
202e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert// _UVRSD_DOUBLE.
203e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertuint32_t RegisterRange(uint8_t start, uint8_t count_minus_one) {
204e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return ((uint32_t)start << 16) | ((uint32_t)count_minus_one + 1);
205e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
206e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
207e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert} // end anonymous namespace
208e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
209a146ba05ace62d2bb8c796432d16c994eaff469eDan Albertuintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index) {
210a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert  uintptr_t value = 0;
211a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert  _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
212a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert  return value;
213a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert}
214a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert
215a146ba05ace62d2bb8c796432d16c994eaff469eDan Albertvoid _Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t
216a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert    new_value) {
217a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert  _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index,
218a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert                  _UVRSD_UINT32, &new_value);
219a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert}
220a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert
221a146ba05ace62d2bb8c796432d16c994eaff469eDan Albertuintptr_t _Unwind_GetIP(struct _Unwind_Context* context) {
222a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert  // remove the thumb-bit before returning
223a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert  return (_Unwind_GetGR(context, 15) & (~(uintptr_t)0x1));
224a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert}
225a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert
226a146ba05ace62d2bb8c796432d16c994eaff469eDan Albertvoid _Unwind_SetIP(struct _Unwind_Context* context, uintptr_t new_value) {
227a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert  uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
228a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert  _Unwind_SetGR(context, 15, new_value | thumb_bit);
229a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert}
230a146ba05ace62d2bb8c796432d16c994eaff469eDan Albert
2312cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert/**
2322cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert * Decodes an EHT entry.
2332cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert *
2342cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert * @param data Pointer to EHT.
2352cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert * @param[out] off Offset from return value (in bytes) to begin interpretation.
2362cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert * @param[out] len Number of bytes in unwind code.
2372cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert * @return Pointer to beginning of unwind code.
2382cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert */
2392cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albertextern "C" const uint32_t*
2402cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albertdecode_eht_entry(const uint32_t* data, size_t* off, size_t* len) {
2412cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert  if ((*data & 0x80000000) == 0) {
2422cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert    // 6.2: Generic Model
2435fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert    // EHT entry is a prel31 pointing to the PR, followed by data understood only
2445fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert    // by the personality routine. Since EHABI doesn't guarantee the location or
2455fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert    // availability of the unwind opcodes in the generic model, we have to check
2465fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert    // for them on a case-by-case basis:
2475fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert    _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions,
2485fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert                                             uint64_t exceptionClass,
2495fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert                                             _Unwind_Exception* unwind_exception,
2505fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert                                             _Unwind_Context* context);
2515fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert    void *PR = (void*)signExtendPrel31(*data);
2525fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert    if (PR == &__gxx_personality_v0) {
2535fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert      *off = 1; // First byte is size data.
2545fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert      *len = (((data[1] >> 24) & 0xff) + 1) * 4;
2555fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert    } else
2565fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert      return nullptr;
2572cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert    data++; // Skip the first word, which is the prel31 offset.
2582cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert  } else {
2592cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert    // 6.3: ARM Compact Model
2605fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert    // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded
2615fcb7c5bdd98aab09c6a462ca69e61d8e9f42104Dan Albert    // by format:
2622cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert    Descriptor::Format format =
2632cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert        static_cast<Descriptor::Format>((*data & 0x0f000000) >> 24);
2642cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert    switch (format) {
2652cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert      case Descriptor::SU16:
2662cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert        *len = 4;
2672cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert        *off = 1;
2682cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert        break;
2692cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert      case Descriptor::LU16:
2702cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert      case Descriptor::LU32:
2712cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert        *len = 4 + 4 * ((*data & 0x00ff0000) >> 16);
2722cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert        *off = 2;
2732cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert        break;
2742cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert      default:
2752cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert        return nullptr;
2762cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert    }
2772cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert  }
2782cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert
2792cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert  return data;
2802cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert}
2812cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert
282e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_Unwind_Reason_Code _Unwind_VRS_Interpret(
283e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Context* context,
2842cca07bae053b3ca7dcd558ad416011023ee54f1Dan Albert    const uint32_t* data,
285e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    size_t offset,
286e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    size_t len) {
287e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  bool wrotePC = false;
288e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  bool finish = false;
289e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  while (offset < len && !finish) {
290e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uint8_t byte = getByte(data, offset++);
291e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if ((byte & 0x80) == 0) {
292e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      uint32_t sp;
293e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
294e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (byte & 0x40)
295e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        sp -= (((uint32_t)byte & 0x3f) << 2) + 4;
296e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      else
297e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        sp += ((uint32_t)byte << 2) + 4;
298e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
299e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    } else {
300e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      switch (byte & 0xf0) {
301e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        case 0x80: {
302e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          if (offset >= len)
303e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            return _URC_FAILURE;
304e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          uint32_t registers =
305e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              (((uint32_t)byte & 0x0f) << 12) |
306e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              (((uint32_t)getByte(data, offset++)) << 4);
307e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          if (!registers)
308e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            return _URC_FAILURE;
309e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          if (registers & (1 << 15))
310e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            wrotePC = true;
311e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);
312e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          break;
313e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        }
314e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        case 0x90: {
315e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          uint8_t reg = byte & 0x0f;
316e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          if (reg == 13 || reg == 15)
317e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            return _URC_FAILURE;
318e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          uint32_t sp;
319e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg,
320e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                          _UVRSD_UINT32, &sp);
321e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
322e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                          &sp);
323e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          break;
324e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        }
325e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        case 0xa0: {
326e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          uint32_t registers = RegisterMask(4, byte & 0x07);
327e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          if (byte & 0x08)
328e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            registers |= 1 << 14;
329e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);
330e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          break;
331e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        }
332e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        case 0xb0: {
333e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          switch (byte) {
334e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xb0:
335e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              finish = true;
336e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              break;
337e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xb1: {
338e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              if (offset >= len)
339e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                return _URC_FAILURE;
340e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint8_t registers = getByte(data, offset++);
341e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              if (registers & 0xf0 || !registers)
342e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                return _URC_FAILURE;
343e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);
344e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              break;
345e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            }
346e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xb2: {
347e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint32_t addend = 0;
348e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint32_t shift = 0;
349e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              // This decodes a uleb128 value.
350e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              while (true) {
351e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                if (offset >= len)
352e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                  return _URC_FAILURE;
353e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                uint32_t v = getByte(data, offset++);
354e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                addend |= (v & 0x7f) << shift;
355e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                if ((v & 0x80) == 0)
356e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                  break;
357e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                shift += 7;
358e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              }
359e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint32_t sp;
360e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
361e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                              &sp);
362e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              sp += 0x204 + (addend << 2);
363e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
364e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                              &sp);
365e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              break;
366e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            }
367e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xb3: {
368e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint8_t v = getByte(data, offset++);
369e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              _Unwind_VRS_Pop(context, _UVRSC_VFP,
370e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                              RegisterRange(v >> 4, v & 0x0f), _UVRSD_VFPX);
371e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              break;
372e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            }
373e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xb4:
374e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xb5:
375e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xb6:
376e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xb7:
377e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              return _URC_FAILURE;
378e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            default:
379e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              _Unwind_VRS_Pop(context, _UVRSC_VFP,
380e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                              RegisterRange(8, byte & 0x07), _UVRSD_VFPX);
381e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              break;
382e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          }
383e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          break;
384e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        }
385e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        case 0xc0: {
386e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          switch (byte) {
387e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xc0:
388e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xc1:
389e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xc2:
390e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xc3:
391e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xc4:
392e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xc5:
393e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              _Unwind_VRS_Pop(context, _UVRSC_WMMXD,
394e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                              RegisterRange(10, byte & 0x7), _UVRSD_DOUBLE);
395e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              break;
396e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xc6: {
397e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint8_t v = getByte(data, offset++);
398e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint8_t start = v >> 4;
399e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint8_t count_minus_one = v & 0xf;
400e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              if (start + count_minus_one >= 16)
401e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                return _URC_FAILURE;
402e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              _Unwind_VRS_Pop(context, _UVRSC_WMMXD,
403e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                              RegisterRange(start, count_minus_one),
404e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                              _UVRSD_DOUBLE);
405e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              break;
406e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            }
407e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xc7: {
408e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint8_t v = getByte(data, offset++);
409e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              if (!v || v & 0xf0)
410e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                return _URC_FAILURE;
411e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              _Unwind_VRS_Pop(context, _UVRSC_WMMXC, v, _UVRSD_DOUBLE);
412e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              break;
413e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            }
414e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xc8:
415e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            case 0xc9: {
416e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint8_t v = getByte(data, offset++);
417e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint8_t start = ((byte == 0xc8) ? 16 : 0) + (v >> 4);
418e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              uint8_t count_minus_one = v & 0xf;
419e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              if (start + count_minus_one >= 32)
420e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                return _URC_FAILURE;
421e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              _Unwind_VRS_Pop(context, _UVRSC_VFP,
422e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                              RegisterRange(start, count_minus_one),
423e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                              _UVRSD_DOUBLE);
424e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              break;
425e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            }
426e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            default:
427e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              return _URC_FAILURE;
428e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          }
429e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          break;
430e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        }
431e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        case 0xd0: {
432e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          if (byte & 0x08)
433e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            return _URC_FAILURE;
434e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          _Unwind_VRS_Pop(context, _UVRSC_VFP, RegisterRange(8, byte & 0x7),
435e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                          _UVRSD_DOUBLE);
436e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          break;
437e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        }
438e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        default:
439e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          return _URC_FAILURE;
440e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
441e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
442e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
443e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (!wrotePC) {
444e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uint32_t lr;
445e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr);
446e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr);
447e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
448e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return _URC_CONTINUE_UNWIND;
449e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
450e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
451e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertextern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr0(
452e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_State state,
453e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Control_Block *ucbp,
454e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Context *context) {
455e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return unwindOneFrame(state, ucbp, context);
456e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
457e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
458e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertextern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr1(
459e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_State state,
460e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Control_Block *ucbp,
461e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Context *context) {
462e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return unwindOneFrame(state, ucbp, context);
463e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
464e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
465e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertextern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr2(
466e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_State state,
467e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Control_Block *ucbp,
468e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Context *context) {
469e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return unwindOneFrame(state, ucbp, context);
470e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
471e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
472e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertstatic _Unwind_Reason_Code
473e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertunwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
474e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // EHABI #7.3 discusses preserving the VRS in a "temporary VRS" during
475e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // phase 1 and then restoring it to the "primary VRS" for phase 2. The
476e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // effect is phase 2 doesn't see any of the VRS manipulations from phase 1.
477e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // In this implementation, the phases don't share the VRS backing store.
478e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // Instead, they are passed the original |uc| and they create a new VRS
479e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // from scratch thus achieving the same effect.
480e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_cursor_t cursor1;
481e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_init_local(&cursor1, uc);
482e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
483e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // Walk each frame looking for a place to stop.
484e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  for (bool handlerNotFound = true; handlerNotFound;) {
485e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
486e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // Ask libuwind to get next frame (skip over first which is
487e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // _Unwind_RaiseException).
488e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    int stepResult = unw_step(&cursor1);
489e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (stepResult == 0) {
490e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
491e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            "bottom => _URC_END_OF_STACK\n",
492e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            exception_object);
493e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return _URC_END_OF_STACK;
494e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    } else if (stepResult < 0) {
495e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => "
496e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            "_URC_FATAL_PHASE1_ERROR\n",
497e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            exception_object);
498e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return _URC_FATAL_PHASE1_ERROR;
499e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
500e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
501e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // See if frame has code to run (has personality routine).
502e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    unw_proc_info_t frameInfo;
503e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) {
504e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
505e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            "failed => _URC_FATAL_PHASE1_ERROR\n",
506e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            exception_object);
507e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return _URC_FATAL_PHASE1_ERROR;
508e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
509e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
510e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // When tracing, print state information.
511e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (_LIBUNWIND_TRACING_UNWINDING) {
512e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      char functionName[512];
513e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      unw_word_t offset;
514e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if ((unw_get_proc_name(&cursor1, functionName, 512, &offset) !=
515e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert           UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip))
516e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        strcpy(functionName, ".anonymous.");
517e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      unw_word_t pc;
518e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      unw_get_reg(&cursor1, UNW_REG_IP, &pc);
519e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _LIBUNWIND_TRACE_UNWINDING(
520e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          "unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, "
521e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          "lsda=0x%llX, personality=0x%llX\n",
522e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          exception_object, (long long)pc, (long long)frameInfo.start_ip,
523e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          functionName, (long long)frameInfo.lsda,
524e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          (long long)frameInfo.handler);
525e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
526e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
527e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // If there is a personality routine, ask it if it will want to stop at
528e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // this frame.
529e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (frameInfo.handler != 0) {
530e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      __personality_routine p =
531e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          (__personality_routine)(long)(frameInfo.handler);
532e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _LIBUNWIND_TRACE_UNWINDING(
533e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          "unwind_phase1(ex_ojb=%p): calling personality function %p\n",
534e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          exception_object, p);
535e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      struct _Unwind_Context *context = (struct _Unwind_Context *)(&cursor1);
536e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      exception_object->pr_cache.fnstart = frameInfo.start_ip;
537e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      exception_object->pr_cache.ehtp =
538e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          (_Unwind_EHT_Header *)frameInfo.unwind_info;
539e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      exception_object->pr_cache.additional = frameInfo.flags;
540e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _Unwind_Reason_Code personalityResult =
541e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          (*p)(_US_VIRTUAL_UNWIND_FRAME, exception_object, context);
542e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _LIBUNWIND_TRACE_UNWINDING(
543e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          "unwind_phase1(ex_ojb=%p): personality result %d "
544e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          "start_ip %x ehtp %p additional %x\n",
545e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          exception_object, personalityResult,
546e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          exception_object->pr_cache.fnstart, exception_object->pr_cache.ehtp,
547e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          exception_object->pr_cache.additional);
548e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      switch (personalityResult) {
549e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case _URC_HANDLER_FOUND:
550e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // found a catch clause or locals that need destructing in this frame
551e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // stop search and remember stack pointer at the frame
552e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        handlerNotFound = false;
553e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // p should have initialized barrier_cache. EHABI #7.3.5
554e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
555e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                                   "_URC_HANDLER_FOUND \n",
556e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                                   exception_object);
557e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _URC_NO_REASON;
558e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
559e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case _URC_CONTINUE_UNWIND:
560e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        _LIBUNWIND_TRACE_UNWINDING(
561e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
562e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            exception_object);
563e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // continue unwinding
564e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        break;
565e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
566e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // EHABI #7.3.3
567e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case _URC_FAILURE:
568e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _URC_FAILURE;
569e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
570e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      default:
571e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // something went wrong
572e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        _LIBUNWIND_TRACE_UNWINDING(
573e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
574e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            exception_object);
575e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _URC_FATAL_PHASE1_ERROR;
576e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
577e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
578e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
579e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return _URC_NO_REASON;
580e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
581e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
582e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertstatic _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
583e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                                         _Unwind_Exception *exception_object,
584e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                                         bool resume) {
585e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // See comment at the start of unwind_phase1 regarding VRS integrity.
586e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_cursor_t cursor2;
587e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_init_local(&cursor2, uc);
588e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
589e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object);
590e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  int frame_count = 0;
591e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
592e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // Walk each frame until we reach where search phase said to stop.
593e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  while (true) {
594e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // Ask libuwind to get next frame (skip over first which is
595e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // _Unwind_RaiseException or _Unwind_Resume).
596e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    //
597e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // Resume only ever makes sense for 1 frame.
598e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_State state =
599e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        resume ? _US_UNWIND_FRAME_RESUME : _US_UNWIND_FRAME_STARTING;
600e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (resume && frame_count == 1) {
601e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // On a resume, first unwind the _Unwind_Resume() frame. The next frame
602e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // is now the landing pad for the cleanup from a previous execution of
603e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // phase2. To continue unwindingly correctly, replace VRS[15] with the
604e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // IP of the frame that the previous run of phase2 installed the context
605e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // for. After this, continue unwinding as if normal.
606e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      //
607e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // See #7.4.6 for details.
608e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      unw_set_reg(&cursor2, UNW_REG_IP,
609e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                  exception_object->unwinder_cache.reserved2);
610e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      resume = false;
611e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
612e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
613e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    int stepResult = unw_step(&cursor2);
614e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (stepResult == 0) {
615e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
616e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            "bottom => _URC_END_OF_STACK\n",
617e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            exception_object);
618e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return _URC_END_OF_STACK;
619e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    } else if (stepResult < 0) {
620e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => "
621e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            "_URC_FATAL_PHASE1_ERROR\n",
622e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            exception_object);
623e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return _URC_FATAL_PHASE2_ERROR;
624e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
625e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
626e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // Get info about this frame.
627e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    unw_word_t sp;
628e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    unw_proc_info_t frameInfo;
629e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    unw_get_reg(&cursor2, UNW_REG_SP, &sp);
630e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
631e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
632e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            "failed => _URC_FATAL_PHASE1_ERROR\n",
633e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            exception_object);
634e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return _URC_FATAL_PHASE2_ERROR;
635e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
636e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
637e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // When tracing, print state information.
638e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (_LIBUNWIND_TRACING_UNWINDING) {
639e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      char functionName[512];
640e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      unw_word_t offset;
641e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) !=
642e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert           UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip))
643e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        strcpy(functionName, ".anonymous.");
644e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _LIBUNWIND_TRACE_UNWINDING(
645e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          "unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, "
646e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          "lsda=0x%llX, personality=0x%llX\n",
647e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          exception_object, (long long)frameInfo.start_ip, functionName,
648e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          (long long)sp, (long long)frameInfo.lsda,
649e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          (long long)frameInfo.handler);
650e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
651e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
652e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // If there is a personality routine, tell it we are unwinding.
653e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (frameInfo.handler != 0) {
654e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      __personality_routine p =
655e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          (__personality_routine)(long)(frameInfo.handler);
656e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      struct _Unwind_Context *context = (struct _Unwind_Context *)(&cursor2);
657e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // EHABI #7.2
658e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      exception_object->pr_cache.fnstart = frameInfo.start_ip;
659e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      exception_object->pr_cache.ehtp =
660e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          (_Unwind_EHT_Header *)frameInfo.unwind_info;
661e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      exception_object->pr_cache.additional = frameInfo.flags;
662e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _Unwind_Reason_Code personalityResult =
663e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          (*p)(state, exception_object, context);
664e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      switch (personalityResult) {
665e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case _URC_CONTINUE_UNWIND:
666e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // Continue unwinding
667e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        _LIBUNWIND_TRACE_UNWINDING(
668e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
669e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            exception_object);
670e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // EHABI #7.2
671e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        if (sp == exception_object->barrier_cache.sp) {
672e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          // Phase 1 said we would stop at this frame, but we did not...
673e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          _LIBUNWIND_ABORT("during phase1 personality function said it would "
674e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                           "stop here, but now in phase2 it did not stop here");
675e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        }
676e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        break;
677e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case _URC_INSTALL_CONTEXT:
678e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        _LIBUNWIND_TRACE_UNWINDING(
679e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n",
680e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            exception_object);
681e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // Personality routine says to transfer control to landing pad.
682e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // We may get control back if landing pad calls _Unwind_Resume().
683e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        if (_LIBUNWIND_TRACING_UNWINDING) {
684e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          unw_word_t pc;
685e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          unw_get_reg(&cursor2, UNW_REG_IP, &pc);
686e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          unw_get_reg(&cursor2, UNW_REG_SP, &sp);
687e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering  "
688e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                                     "user code with ip=0x%llX, sp=0x%llX\n",
689e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                                     exception_object, (long long)pc,
690e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                                     (long long)sp);
691e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        }
692e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
693e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        {
694e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          // EHABI #7.4.1 says we need to preserve pc for when _Unwind_Resume
695e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          // is called back, to find this same frame.
696e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          unw_word_t pc;
697e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          unw_get_reg(&cursor2, UNW_REG_IP, &pc);
698e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          exception_object->unwinder_cache.reserved2 = (uint32_t)pc;
699e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        }
700e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        unw_resume(&cursor2);
701e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // unw_resume() only returns if there was an error.
702e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _URC_FATAL_PHASE2_ERROR;
703e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
704e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // # EHABI #7.4.3
705e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case _URC_FAILURE:
706e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        abort();
707e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
708e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      default:
709e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // Personality routine returned an unknown result code.
710e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
711e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                      personalityResult);
712e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _URC_FATAL_PHASE2_ERROR;
713e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
714e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
715e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    frame_count++;
716e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
717e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
718e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // Clean up phase did not resume at the frame that the search phase
719e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // said it would...
720e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return _URC_FATAL_PHASE2_ERROR;
721e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
722e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
723e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// Called by __cxa_throw.  Only returns if there is a fatal error.
724e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_LIBUNWIND_EXPORT _Unwind_Reason_Code
725e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_Unwind_RaiseException(_Unwind_Exception *exception_object) {
726e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n",
727e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                             exception_object);
728e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_context_t uc;
729e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_getcontext(&uc);
730e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
731e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // This field for is for compatibility with GCC to say this isn't a forced
732e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // unwind. EHABI #7.2
733e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  exception_object->unwinder_cache.reserved1 = 0;
734e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
735e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // phase 1: the search phase
736e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object);
737e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (phase1 != _URC_NO_REASON)
738e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    return phase1;
739e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
740e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // phase 2: the clean up phase
741e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return unwind_phase2(&uc, exception_object, false);
742e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
743e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
744e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) {
745e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // This is to be called when exception handling completes to give us a chance
746e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // to perform any housekeeping. EHABI #7.2. But we have nothing to do here.
747e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  (void)exception_object;
748e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
749e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
750e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// When _Unwind_RaiseException() is in phase2, it hands control
751e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// to the personality function at each frame.  The personality
752e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// may force a jump to a landing pad in that function, the landing
753e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// pad code may then call _Unwind_Resume() to continue with the
754e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// unwinding.  Note: the call to _Unwind_Resume() is from compiler
755e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// geneated user code.  All other _Unwind_* routines are called
756e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// by the C++ runtime __cxa_* routines.
757e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert///
758e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// Note: re-throwing an exception (as opposed to continuing the unwind)
759e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// is implemented by having the code call __cxa_rethrow() which
760e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// in turn calls _Unwind_Resume_or_Rethrow().
761e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_LIBUNWIND_EXPORT void
762e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_Unwind_Resume(_Unwind_Exception *exception_object) {
763e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", exception_object);
764e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_context_t uc;
765e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_getcontext(&uc);
766e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
767e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
768e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // which is in the same position as private_1 below.
769e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // TODO(ajwong): Who wronte the above? Why is it true?
770e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unwind_phase2(&uc, exception_object, true);
771e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
772e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
773e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
774e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
775e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
776e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// Called by personality handler during phase 2 to get LSDA for current frame.
777e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_LIBUNWIND_EXPORT uintptr_t
778e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
779e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_cursor_t *cursor = (unw_cursor_t *)context;
780e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_proc_info_t frameInfo;
781e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  uintptr_t result = 0;
782e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
783e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    result = (uintptr_t)frameInfo.lsda;
784e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p)"
785e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                       "=> 0x%llx\n", context, (long long)result);
786e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (result != 0) {
787e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (*((uint8_t *)result) != 0xFF)
788e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _LIBUNWIND_DEBUG_LOG("lsda at 0x%llx does not start with 0xFF\n",
789e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                           (long long)result);
790e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
791e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return result;
792e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
793e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
794e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertstatic uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
795e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                                  void* valuep) {
796e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  uint64_t value = 0;
797e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  switch (representation) {
798e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSD_UINT32:
799e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSD_FLOAT:
800e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      memcpy(&value, valuep, sizeof(uint32_t));
801e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      break;
802e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
803e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSD_VFPX:
804e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSD_UINT64:
805e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSD_DOUBLE:
806e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      memcpy(&value, valuep, sizeof(uint64_t));
807e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      break;
808e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
809e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return value;
810e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
811e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
812e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_Unwind_VRS_Result _Unwind_VRS_Set(
813e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Context *context,
814e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_VRS_RegClass regclass,
815e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uint32_t regno,
816e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_VRS_DataRepresentation representation,
817e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    void *valuep) {
818e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, "
819e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                       "rep=%d, value=0x%llX)\n", context, regclass,
820e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                       regno, representation,
821e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                       ValueAsBitPattern(representation, valuep));
822e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_cursor_t *cursor = (unw_cursor_t *)context;
823e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  switch (regclass) {
824e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_CORE:
825e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation != _UVRSD_UINT32 || regno > 15)
826e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
827e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno),
828e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                         *(unw_word_t *)valuep) == UNW_ESUCCESS
829e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 ? _UVRSR_OK
830e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 : _UVRSR_FAILED;
831e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_WMMXC:
832e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation != _UVRSD_UINT32 || regno > 3)
833e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
834e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
835e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                         *(unw_word_t *)valuep) == UNW_ESUCCESS
836e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 ? _UVRSR_OK
837e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 : _UVRSR_FAILED;
838e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_VFP:
839e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
840e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
841e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation == _UVRSD_VFPX) {
842e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // Can only touch d0-15 with FSTMFDX.
843e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        if (regno > 15)
844e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          return _UVRSR_FAILED;
845e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        unw_save_vfp_as_X(cursor);
846e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      } else {
847e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        if (regno > 31)
848e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          return _UVRSR_FAILED;
849e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
850e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno),
851e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                           *(unw_fpreg_t *)valuep) == UNW_ESUCCESS
852e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 ? _UVRSR_OK
853e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 : _UVRSR_FAILED;
854e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_WMMXD:
855e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation != _UVRSD_DOUBLE || regno > 31)
856e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
857e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno),
858e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                           *(unw_fpreg_t *)valuep) == UNW_ESUCCESS
859e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 ? _UVRSR_OK
860e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 : _UVRSR_FAILED;
861e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
862e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
863e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
864e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertstatic _Unwind_VRS_Result _Unwind_VRS_Get_Internal(
865e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Context *context,
866e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_VRS_RegClass regclass,
867e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uint32_t regno,
868e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_VRS_DataRepresentation representation,
869e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    void *valuep) {
870e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_cursor_t *cursor = (unw_cursor_t *)context;
871e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  switch (regclass) {
872e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_CORE:
873e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation != _UVRSD_UINT32 || regno > 15)
874e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
875e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno),
876e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                         (unw_word_t *)valuep) == UNW_ESUCCESS
877e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 ? _UVRSR_OK
878e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 : _UVRSR_FAILED;
879e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_WMMXC:
880e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation != _UVRSD_UINT32 || regno > 3)
881e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
882e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
883e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                         (unw_word_t *)valuep) == UNW_ESUCCESS
884e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 ? _UVRSR_OK
885e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 : _UVRSR_FAILED;
886e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_VFP:
887e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
888e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
889e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation == _UVRSD_VFPX) {
890e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // Can only touch d0-15 with FSTMFDX.
891e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        if (regno > 15)
892e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          return _UVRSR_FAILED;
893e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        unw_save_vfp_as_X(cursor);
894e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      } else {
895e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        if (regno > 31)
896e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          return _UVRSR_FAILED;
897e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
898e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno),
899e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                           (unw_fpreg_t *)valuep) == UNW_ESUCCESS
900e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 ? _UVRSR_OK
901e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 : _UVRSR_FAILED;
902e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_WMMXD:
903e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation != _UVRSD_DOUBLE || regno > 31)
904e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
905e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno),
906e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                           (unw_fpreg_t *)valuep) == UNW_ESUCCESS
907e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 ? _UVRSR_OK
908e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                 : _UVRSR_FAILED;
909e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
910e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
911e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
912e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_Unwind_VRS_Result _Unwind_VRS_Get(
913e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Context *context,
914e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_VRS_RegClass regclass,
915e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uint32_t regno,
916e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_VRS_DataRepresentation representation,
917e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    void *valuep) {
918e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _Unwind_VRS_Result result =
919e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      _Unwind_VRS_Get_Internal(context, regclass, regno, representation,
920e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                               valuep);
921e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _LIBUNWIND_TRACE_API("_Unwind_VRS_Get(context=%p, regclass=%d, reg=%d, "
922e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                       "rep=%d, value=0x%llX, result = %d)\n",
923e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                       context, regclass, regno, representation,
924e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                       ValueAsBitPattern(representation, valuep), result);
925e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return result;
926e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
927e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
928e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_Unwind_VRS_Result _Unwind_VRS_Pop(
929e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_Context *context,
930e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_VRS_RegClass regclass,
931e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uint32_t discriminator,
932e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_VRS_DataRepresentation representation) {
933e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _LIBUNWIND_TRACE_API("_Unwind_VRS_Pop(context=%p, regclass=%d, "
934e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                       "discriminator=%d, representation=%d)\n",
935e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                        context, regclass, discriminator, representation);
936e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  switch (regclass) {
937e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_CORE:
938e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_WMMXC: {
939e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation != _UVRSD_UINT32)
940e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
941e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // When popping SP from the stack, we don't want to override it from the
942e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // computed new stack location. See EHABI #7.5.4 table 3.
943e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      bool poppedSP = false;
944e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      uint32_t* sp;
945e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP,
946e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                          _UVRSD_UINT32, &sp) != _UVRSR_OK) {
947e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
948e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
949e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      for (uint32_t i = 0; i < 16; ++i) {
950e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        if (!(discriminator & (1 << i)))
951e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          continue;
952e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        uint32_t value = *sp++;
953e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        if (regclass == _UVRSC_CORE && i == 13)
954e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          poppedSP = true;
955e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        if (_Unwind_VRS_Set(context, regclass, i,
956e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                            _UVRSD_UINT32, &value) != _UVRSR_OK) {
957e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          return _UVRSR_FAILED;
958e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        }
959e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
960e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (!poppedSP) {
961e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP,
962e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                               _UVRSD_UINT32, &sp);
963e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
964e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return _UVRSR_OK;
965e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
966e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_VFP:
967e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    case _UVRSC_WMMXD: {
968e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
969e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
970e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      uint32_t first = discriminator >> 16;
971e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      uint32_t count = discriminator & 0xffff;
972e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      uint32_t end = first+count;
973e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      uint32_t* sp;
974e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP,
975e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                          _UVRSD_UINT32, &sp) != _UVRSR_OK) {
976e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return _UVRSR_FAILED;
977e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
978e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // For _UVRSD_VFPX, we're assuming the data is stored in FSTMX "standard
979e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      // format 1", which is equivalent to FSTMD + a padding word.
980e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      for (uint32_t i = first; i < end; ++i) {
981e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        // SP is only 32-bit aligned so don't copy 64-bit at a time.
982e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        uint64_t value = *sp++;
983e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        value |= ((uint64_t)(*sp++)) << 32;
984e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        if (_Unwind_VRS_Set(context, regclass, i, representation, &value) !=
985e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert            _UVRSR_OK)
986e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert          return _UVRSR_FAILED;
987e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
988e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (representation == _UVRSD_VFPX)
989e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        ++sp;
990e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
991e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                             &sp);
992e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
993e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  };
994e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
995e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
996e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// Called by personality handler during phase 2 to find the start of the
997e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// function.
998e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_LIBUNWIND_EXPORT uintptr_t
999e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_Unwind_GetRegionStart(struct _Unwind_Context *context) {
1000e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_cursor_t *cursor = (unw_cursor_t *)context;
1001e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_proc_info_t frameInfo;
1002e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  uintptr_t result = 0;
1003e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
1004e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    result = (uintptr_t)frameInfo.start_ip;
1005e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%llX\n",
1006e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                             context, (long long)result);
1007e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return result;
1008e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
1009e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
1010e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
1011e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert/// Called by personality handler during phase 2 if a foreign exception
1012e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert// is caught.
1013e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_LIBUNWIND_EXPORT void
1014e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert_Unwind_DeleteException(_Unwind_Exception *exception_object) {
1015e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n",
1016e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                              exception_object);
1017e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (exception_object->exception_cleanup != NULL)
1018e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
1019e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                                           exception_object);
1020e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
1021e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
1022e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif  // LIBCXXABI_ARM_EHABI
1023