GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcxxabi/../libunwind/src/UnwindLevel1.c Lines: 84 187 44.9 %
Date: 2017-11-13 Branches: 35 153 22.9 %

Line Branch Exec Source
1
//===------------------------- UnwindLevel1.c -----------------------------===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is dual licensed under the MIT and the University of Illinois Open
6
// Source Licenses. See LICENSE.TXT for details.
7
//
8
//
9
// Implements C++ ABI Exception Handling Level 1 as documented at:
10
//      http://mentorembedded.github.io/cxx-abi/abi-eh.html
11
// using libunwind
12
//
13
//===----------------------------------------------------------------------===//
14
15
// ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}().  Thus, we are
16
// defining inline functions to delegate the function calls to
17
// _Unwind_VRS_{Get,Set}().  However, some applications might declare the
18
// function protetype directly (instead of including <unwind.h>), thus we need
19
// to export these functions from libunwind.so as well.
20
#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1
21
22
#include <inttypes.h>
23
#include <stdint.h>
24
#include <stdbool.h>
25
#include <stdlib.h>
26
#include <stdio.h>
27
#include <string.h>
28
29
#include "libunwind.h"
30
#include "unwind.h"
31
#include "config.h"
32
33
#if !_LIBUNWIND_ARM_EHABI
34
35
static _Unwind_Reason_Code
36
unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
37
8
  unw_init_local(cursor, uc);
38
39
  // Walk each frame looking for a place to stop.
40
  bool handlerNotFound = true;
41
16
  while (handlerNotFound) {
42
    // Ask libuwind to get next frame (skip over first which is
43
    // _Unwind_RaiseException).
44
8
    int stepResult = unw_step(cursor);
45
8
    if (stepResult == 0) {
46
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
47
                                 "bottom => _URC_END_OF_STACK\n",
48
                                 (void *)exception_object);
49
      return _URC_END_OF_STACK;
50
8
    } else if (stepResult < 0) {
51
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => "
52
                                 "_URC_FATAL_PHASE1_ERROR\n",
53
                                 (void *)exception_object);
54
      return _URC_FATAL_PHASE1_ERROR;
55
    }
56
57
    // See if frame has code to run (has personality routine).
58
8
    unw_proc_info_t frameInfo;
59
8
    unw_word_t sp;
60
16
    if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
61
8
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
62
                                 "failed => _URC_FATAL_PHASE1_ERROR\n",
63
                                 (void *)exception_object);
64
      return _URC_FATAL_PHASE1_ERROR;
65
    }
66
67
    // When tracing, print state information.
68
8
    if (_LIBUNWIND_TRACING_UNWINDING) {
69
      char functionBuf[512];
70
      const char *functionName = functionBuf;
71
      unw_word_t offset;
72
      if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
73
                             &offset) != UNW_ESUCCESS) ||
74
          (frameInfo.start_ip + offset > frameInfo.end_ip))
75
        functionName = ".anonymous.";
76
      unw_word_t pc;
77
      unw_get_reg(cursor, UNW_REG_IP, &pc);
78
      _LIBUNWIND_TRACE_UNWINDING(
79
          "unwind_phase1(ex_ojb=%p): pc=0x%" PRIx64 ", start_ip=0x%" PRIx64
80
          ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n",
81
          (void *)exception_object, pc, frameInfo.start_ip, functionName,
82
          frameInfo.lsda, frameInfo.handler);
83
    }
84
85
    // If there is a personality routine, ask it if it will want to stop at
86
    // this frame.
87
8
    if (frameInfo.handler != 0) {
88
      __personality_routine p =
89
4
          (__personality_routine)(long)(frameInfo.handler);
90
4
      _LIBUNWIND_TRACE_UNWINDING(
91
          "unwind_phase1(ex_ojb=%p): calling personality function %p\n",
92
          (void *)exception_object, (void *)(uintptr_t)p);
93
      _Unwind_Reason_Code personalityResult =
94
8
          (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
95
4
               exception_object, (struct _Unwind_Context *)(cursor));
96
4
      switch (personalityResult) {
97
      case _URC_HANDLER_FOUND:
98
        // found a catch clause or locals that need destructing in this frame
99
        // stop search and remember stack pointer at the frame
100
        handlerNotFound = false;
101
4
        unw_get_reg(cursor, UNW_REG_SP, &sp);
102
4
        exception_object->private_2 = (uintptr_t)sp;
103
4
        _LIBUNWIND_TRACE_UNWINDING(
104
            "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n",
105
            (void *)exception_object);
106
4
        return _URC_NO_REASON;
107
108
      case _URC_CONTINUE_UNWIND:
109
        _LIBUNWIND_TRACE_UNWINDING(
110
            "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
111
            (void *)exception_object);
112
        // continue unwinding
113
        break;
114
115
      default:
116
        // something went wrong
117
        _LIBUNWIND_TRACE_UNWINDING(
118
            "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
119
            (void *)exception_object);
120
        return _URC_FATAL_PHASE1_ERROR;
121
      }
122
    }
123
12
  }
124
  return _URC_NO_REASON;
125
4
}
126
127
128
static _Unwind_Reason_Code
129
unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
130
8
  unw_init_local(cursor, uc);
131
132
4
  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n",
133
                             (void *)exception_object);
134
135
  // Walk each frame until we reach where search phase said to stop.
136
8
  while (true) {
137
138
    // Ask libuwind to get next frame (skip over first which is
139
    // _Unwind_RaiseException).
140
8
    int stepResult = unw_step(cursor);
141
8
    if (stepResult == 0) {
142
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
143
                                 "bottom => _URC_END_OF_STACK\n",
144
                                 (void *)exception_object);
145
      return _URC_END_OF_STACK;
146
8
    } else if (stepResult < 0) {
147
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => "
148
                                 "_URC_FATAL_PHASE1_ERROR\n",
149
                                 (void *)exception_object);
150
      return _URC_FATAL_PHASE2_ERROR;
151
    }
152
153
    // Get info about this frame.
154
8
    unw_word_t sp;
155
8
    unw_proc_info_t frameInfo;
156
8
    unw_get_reg(cursor, UNW_REG_SP, &sp);
157
16
    if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
158
8
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
159
                                 "failed => _URC_FATAL_PHASE1_ERROR\n",
160
                                 (void *)exception_object);
161
      return _URC_FATAL_PHASE2_ERROR;
162
    }
163
164
    // When tracing, print state information.
165
8
    if (_LIBUNWIND_TRACING_UNWINDING) {
166
      char functionBuf[512];
167
      const char *functionName = functionBuf;
168
      unw_word_t offset;
169
      if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
170
                             &offset) != UNW_ESUCCESS) ||
171
          (frameInfo.start_ip + offset > frameInfo.end_ip))
172
        functionName = ".anonymous.";
173
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIx64
174
                                 ", func=%s, sp=0x%" PRIx64 ", lsda=0x%" PRIx64
175
                                 ", personality=0x%" PRIx64 "\n",
176
                                 (void *)exception_object, frameInfo.start_ip,
177
                                 functionName, sp, frameInfo.lsda,
178
                                 frameInfo.handler);
179
    }
180
181
    // If there is a personality routine, tell it we are unwinding.
182
8
    if (frameInfo.handler != 0) {
183
      __personality_routine p =
184
4
          (__personality_routine)(long)(frameInfo.handler);
185
      _Unwind_Action action = _UA_CLEANUP_PHASE;
186
4
      if (sp == exception_object->private_2) {
187
        // Tell personality this was the frame it marked in phase 1.
188
        action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
189
      }
190
       _Unwind_Reason_Code personalityResult =
191
8
          (*p)(1, action, exception_object->exception_class, exception_object,
192
4
               (struct _Unwind_Context *)(cursor));
193
4
      switch (personalityResult) {
194
      case _URC_CONTINUE_UNWIND:
195
        // Continue unwinding
196
        _LIBUNWIND_TRACE_UNWINDING(
197
            "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
198
            (void *)exception_object);
199
        if (sp == exception_object->private_2) {
200
          // Phase 1 said we would stop at this frame, but we did not...
201
          _LIBUNWIND_ABORT("during phase1 personality function said it would "
202
                           "stop here, but now in phase2 it did not stop here");
203
        }
204
        break;
205
      case _URC_INSTALL_CONTEXT:
206
4
        _LIBUNWIND_TRACE_UNWINDING(
207
            "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n",
208
            (void *)exception_object);
209
        // Personality routine says to transfer control to landing pad.
210
        // We may get control back if landing pad calls _Unwind_Resume().
211
4
        if (_LIBUNWIND_TRACING_UNWINDING) {
212
          unw_word_t pc;
213
          unw_get_reg(cursor, UNW_REG_IP, &pc);
214
          unw_get_reg(cursor, UNW_REG_SP, &sp);
215
          _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
216
                                     "user code with ip=0x%" PRIx64
217
                                     ", sp=0x%" PRIx64 "\n",
218
                                     (void *)exception_object, pc, sp);
219
        }
220
4
        unw_resume(cursor);
221
        // unw_resume() only returns if there was an error.
222
4
        return _URC_FATAL_PHASE2_ERROR;
223
      default:
224
        // Personality routine returned an unknown result code.
225
        _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
226
                             personalityResult);
227
        return _URC_FATAL_PHASE2_ERROR;
228
      }
229
    }
230
8
  }
231
232
  // Clean up phase did not resume at the frame that the search phase
233
  // said it would...
234
  return _URC_FATAL_PHASE2_ERROR;
235
}
236
237
static _Unwind_Reason_Code
238
unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
239
                     _Unwind_Exception *exception_object,
240
                     _Unwind_Stop_Fn stop, void *stop_parameter) {
241
  unw_init_local(cursor, uc);
242
243
  // Walk each frame until we reach where search phase said to stop
244
  while (unw_step(cursor) > 0) {
245
246
    // Update info about this frame.
247
    unw_proc_info_t frameInfo;
248
    if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
249
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
250
                                 "failed => _URC_END_OF_STACK\n",
251
                                 (void *)exception_object);
252
      return _URC_FATAL_PHASE2_ERROR;
253
    }
254
255
    // When tracing, print state information.
256
    if (_LIBUNWIND_TRACING_UNWINDING) {
257
      char functionBuf[512];
258
      const char *functionName = functionBuf;
259
      unw_word_t offset;
260
      if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
261
                             &offset) != UNW_ESUCCESS) ||
262
          (frameInfo.start_ip + offset > frameInfo.end_ip))
263
        functionName = ".anonymous.";
264
      _LIBUNWIND_TRACE_UNWINDING(
265
          "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64
266
          ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n",
267
          (void *)exception_object, frameInfo.start_ip, functionName,
268
          frameInfo.lsda, frameInfo.handler);
269
    }
270
271
    // Call stop function at each frame.
272
    _Unwind_Action action =
273
        (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
274
    _Unwind_Reason_Code stopResult =
275
        (*stop)(1, action, exception_object->exception_class, exception_object,
276
                (struct _Unwind_Context *)(cursor), stop_parameter);
277
    _LIBUNWIND_TRACE_UNWINDING(
278
        "unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n",
279
        (void *)exception_object, stopResult);
280
    if (stopResult != _URC_NO_REASON) {
281
      _LIBUNWIND_TRACE_UNWINDING(
282
          "unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n",
283
          (void *)exception_object);
284
      return _URC_FATAL_PHASE2_ERROR;
285
    }
286
287
    // If there is a personality routine, tell it we are unwinding.
288
    if (frameInfo.handler != 0) {
289
      __personality_routine p =
290
          (__personality_routine)(long)(frameInfo.handler);
291
      _LIBUNWIND_TRACE_UNWINDING(
292
          "unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n",
293
          (void *)exception_object, (void *)(uintptr_t)p);
294
      _Unwind_Reason_Code personalityResult =
295
          (*p)(1, action, exception_object->exception_class, exception_object,
296
               (struct _Unwind_Context *)(cursor));
297
      switch (personalityResult) {
298
      case _URC_CONTINUE_UNWIND:
299
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
300
                                   "personality returned "
301
                                   "_URC_CONTINUE_UNWIND\n",
302
                                   (void *)exception_object);
303
        // Destructors called, continue unwinding
304
        break;
305
      case _URC_INSTALL_CONTEXT:
306
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
307
                                   "personality returned "
308
                                   "_URC_INSTALL_CONTEXT\n",
309
                                   (void *)exception_object);
310
        // We may get control back if landing pad calls _Unwind_Resume().
311
        unw_resume(cursor);
312
        break;
313
      default:
314
        // Personality routine returned an unknown result code.
315
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
316
                                   "personality returned %d, "
317
                                   "_URC_FATAL_PHASE2_ERROR\n",
318
                                   (void *)exception_object, personalityResult);
319
        return _URC_FATAL_PHASE2_ERROR;
320
      }
321
    }
322
  }
323
324
  // Call stop function one last time and tell it we've reached the end
325
  // of the stack.
326
  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
327
                             "function with _UA_END_OF_STACK\n",
328
                             (void *)exception_object);
329
  _Unwind_Action lastAction =
330
      (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
331
  (*stop)(1, lastAction, exception_object->exception_class, exception_object,
332
          (struct _Unwind_Context *)(cursor), stop_parameter);
333
334
  // Clean up phase did not resume at the frame that the search phase said it
335
  // would.
336
  return _URC_FATAL_PHASE2_ERROR;
337
}
338
339
340
/// Called by __cxa_throw.  Only returns if there is a fatal error.
341
_LIBUNWIND_EXPORT _Unwind_Reason_Code
342
_Unwind_RaiseException(_Unwind_Exception *exception_object) {
343
8
  _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n",
344
                       (void *)exception_object);
345
4
  unw_context_t uc;
346
4
  unw_cursor_t cursor;
347
4
  unw_getcontext(&uc);
348
349
  // Mark that this is a non-forced unwind, so _Unwind_Resume()
350
  // can do the right thing.
351
4
  exception_object->private_1 = 0;
352
4
  exception_object->private_2 = 0;
353
354
  // phase 1: the search phase
355
4
  _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);
356
4
  if (phase1 != _URC_NO_REASON)
357
    return phase1;
358
359
  // phase 2: the clean up phase
360
4
  return unwind_phase2(&uc, &cursor, exception_object);
361
}
362
363
364
365
/// When _Unwind_RaiseException() is in phase2, it hands control
366
/// to the personality function at each frame.  The personality
367
/// may force a jump to a landing pad in that function, the landing
368
/// pad code may then call _Unwind_Resume() to continue with the
369
/// unwinding.  Note: the call to _Unwind_Resume() is from compiler
370
/// geneated user code.  All other _Unwind_* routines are called
371
/// by the C++ runtime __cxa_* routines.
372
///
373
/// Note: re-throwing an exception (as opposed to continuing the unwind)
374
/// is implemented by having the code call __cxa_rethrow() which
375
/// in turn calls _Unwind_Resume_or_Rethrow().
376
_LIBUNWIND_EXPORT void
377
_Unwind_Resume(_Unwind_Exception *exception_object) {
378
  _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", (void *)exception_object);
379
  unw_context_t uc;
380
  unw_cursor_t cursor;
381
  unw_getcontext(&uc);
382
383
  if (exception_object->private_1 != 0)
384
    unwind_phase2_forced(&uc, &cursor, exception_object,
385
                         (_Unwind_Stop_Fn) exception_object->private_1,
386
                         (void *)exception_object->private_2);
387
  else
388
    unwind_phase2(&uc, &cursor, exception_object);
389
390
  // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
391
  _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
392
}
393
394
395
396
/// Not used by C++.
397
/// Unwinds stack, calling "stop" function at each frame.
398
/// Could be used to implement longjmp().
399
_LIBUNWIND_EXPORT _Unwind_Reason_Code
400
_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
401
                     _Unwind_Stop_Fn stop, void *stop_parameter) {
402
  _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n",
403
                       (void *)exception_object, (void *)(uintptr_t)stop);
404
  unw_context_t uc;
405
  unw_cursor_t cursor;
406
  unw_getcontext(&uc);
407
408
  // Mark that this is a forced unwind, so _Unwind_Resume() can do
409
  // the right thing.
410
  exception_object->private_1 = (uintptr_t) stop;
411
  exception_object->private_2 = (uintptr_t) stop_parameter;
412
413
  // do it
414
  return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter);
415
}
416
417
418
/// Called by personality handler during phase 2 to get LSDA for current frame.
419
_LIBUNWIND_EXPORT uintptr_t
420
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
421
8
  unw_cursor_t *cursor = (unw_cursor_t *)context;
422
4
  unw_proc_info_t frameInfo;
423
  uintptr_t result = 0;
424
4
  if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
425
4
    result = (uintptr_t)frameInfo.lsda;
426
4
  _LIBUNWIND_TRACE_API(
427
      "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR "\n",
428
      (void *)context, result);
429
4
  if (result != 0) {
430
4
    if (*((uint8_t *)result) != 0xFF)
431
      _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF\n",
432
                           result);
433
  }
434
4
  return result;
435
4
}
436
437
438
/// Called by personality handler during phase 2 to find the start of the
439
/// function.
440
_LIBUNWIND_EXPORT uintptr_t
441
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
442
8
  unw_cursor_t *cursor = (unw_cursor_t *)context;
443
4
  unw_proc_info_t frameInfo;
444
  uintptr_t result = 0;
445
4
  if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
446
4
    result = (uintptr_t)frameInfo.start_ip;
447
4
  _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR "\n",
448
                       (void *)context, result);
449
4
  return result;
450
4
}
451
452
453
/// Called by personality handler during phase 2 if a foreign exception
454
// is caught.
455
_LIBUNWIND_EXPORT void
456
_Unwind_DeleteException(_Unwind_Exception *exception_object) {
457
  _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n",
458
                       (void *)exception_object);
459
  if (exception_object->exception_cleanup != NULL)
460
    (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
461
                                           exception_object);
462
}
463
464
/// Called by personality handler during phase 2 to get register values.
465
_LIBUNWIND_EXPORT uintptr_t
466
_Unwind_GetGR(struct _Unwind_Context *context, int index) {
467
  unw_cursor_t *cursor = (unw_cursor_t *)context;
468
  unw_word_t result;
469
  unw_get_reg(cursor, index, &result);
470
  _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64 "\n",
471
                       (void *)context, index, (uint64_t)result);
472
  return (uintptr_t)result;
473
}
474
475
/// Called by personality handler during phase 2 to alter register values.
476
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
477
                                     uintptr_t value) {
478
16
  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIx64
479
                       ")\n",
480
                       (void *)context, index, (uint64_t)value);
481
8
  unw_cursor_t *cursor = (unw_cursor_t *)context;
482
8
  unw_set_reg(cursor, index, value);
483
8
}
484
485
/// Called by personality handler during phase 2 to get instruction pointer.
486
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
487
8
  unw_cursor_t *cursor = (unw_cursor_t *)context;
488
4
  unw_word_t result;
489
4
  unw_get_reg(cursor, UNW_REG_IP, &result);
490
4
  _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIx64 "\n",
491
                       (void *)context, (uint64_t)result);
492
8
  return (uintptr_t)result;
493
4
}
494
495
/// Called by personality handler during phase 2 to alter instruction pointer,
496
/// such as setting where the landing pad is, so _Unwind_Resume() will
497
/// start executing in the landing pad.
498
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
499
                                     uintptr_t value) {
500
8
  _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIx64 ")\n",
501
                       (void *)context, (uint64_t)value);
502
4
  unw_cursor_t *cursor = (unw_cursor_t *)context;
503
4
  unw_set_reg(cursor, UNW_REG_IP, value);
504
4
}
505
506
#endif // !_LIBUNWIND_ARM_EHABI