xref: /llvm-project/libunwind/test/forceunwind.pass.cpp (revision fe1301b5d846e96655ae6981789f677de6c7572d)
1db126ae2SDaniel Kiss // -*- C++ -*-
2db126ae2SDaniel Kiss //===----------------------------------------------------------------------===//
3db126ae2SDaniel Kiss //
4db126ae2SDaniel Kiss // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5db126ae2SDaniel Kiss // See https://llvm.org/LICENSE.txt for license information.
6db126ae2SDaniel Kiss // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7db126ae2SDaniel Kiss //
8db126ae2SDaniel Kiss //===----------------------------------------------------------------------===//
9db126ae2SDaniel Kiss 
10b29b6cccSAlex Richardson // REQUIRES: linux
11db126ae2SDaniel Kiss 
12cb055e51SLouis Dionne // TODO: Figure out why this fails with Memory Sanitizer.
13cb055e51SLouis Dionne // XFAIL: msan
14cb055e51SLouis Dionne 
15db126ae2SDaniel Kiss // Basic test for _Unwind_ForcedUnwind.
16db126ae2SDaniel Kiss // See libcxxabi/test/forced_unwind* tests too.
17db126ae2SDaniel Kiss 
18fc6a6ee5SFlorian Mayer #undef NDEBUG
19db126ae2SDaniel Kiss #include <assert.h>
20db126ae2SDaniel Kiss #include <signal.h>
21db126ae2SDaniel Kiss #include <stdint.h>
22db126ae2SDaniel Kiss #include <stdio.h>
23db126ae2SDaniel Kiss #include <stdlib.h>
24db126ae2SDaniel Kiss #include <string.h>
25db126ae2SDaniel Kiss #include <sys/types.h>
26db126ae2SDaniel Kiss #include <unistd.h>
27db126ae2SDaniel Kiss #include <unwind.h>
28db126ae2SDaniel Kiss 
29*fe1301b5SAlastair Houghton // Using __attribute__((section("main_func"))) is Linux specific, but then
30*fe1301b5SAlastair Houghton // this entire test is marked as requiring Linux, so we should be good.
31*fe1301b5SAlastair Houghton //
32*fe1301b5SAlastair Houghton // We don't use dladdr() because on musl it's a no-op when statically linked.
33*fe1301b5SAlastair Houghton extern char __start_main_func;
34*fe1301b5SAlastair Houghton extern char __stop_main_func;
35*fe1301b5SAlastair Houghton 
36db126ae2SDaniel Kiss void foo();
37db126ae2SDaniel Kiss _Unwind_Exception ex;
38db126ae2SDaniel Kiss 
stop(int version,_Unwind_Action actions,_Unwind_Exception_Class exceptionClass,_Unwind_Exception * exceptionObject,struct _Unwind_Context * context,void * stop_parameter)39db126ae2SDaniel Kiss _Unwind_Reason_Code stop(int version, _Unwind_Action actions,
40f5b997e6SDaniel Kiss                          _Unwind_Exception_Class exceptionClass,
41db126ae2SDaniel Kiss                          _Unwind_Exception *exceptionObject,
42db126ae2SDaniel Kiss                          struct _Unwind_Context *context,
43db126ae2SDaniel Kiss                          void *stop_parameter) {
44db126ae2SDaniel Kiss   assert(version == 1);
45db126ae2SDaniel Kiss   assert((actions & _UA_FORCE_UNWIND) != 0);
46db126ae2SDaniel Kiss   (void)exceptionClass;
47db126ae2SDaniel Kiss   assert(exceptionObject == &ex);
48db126ae2SDaniel Kiss   assert(stop_parameter == &foo);
49db126ae2SDaniel Kiss 
50*fe1301b5SAlastair Houghton   // Unwind until the main is reached, above frames depend on the platform and
51db126ae2SDaniel Kiss   // architecture.
52*fe1301b5SAlastair Houghton   uintptr_t ip = _Unwind_GetIP(context);
53*fe1301b5SAlastair Houghton   if (ip >= (uintptr_t)&__start_main_func &&
54*fe1301b5SAlastair Houghton       ip < (uintptr_t)&__stop_main_func) {
55db126ae2SDaniel Kiss     _Exit(0);
56db126ae2SDaniel Kiss   }
57*fe1301b5SAlastair Houghton 
58db126ae2SDaniel Kiss   return _URC_NO_REASON;
59db126ae2SDaniel Kiss }
60db126ae2SDaniel Kiss 
foo()61db126ae2SDaniel Kiss __attribute__((noinline)) void foo() {
62db126ae2SDaniel Kiss 
63db126ae2SDaniel Kiss   // Arm EHABI defines struct _Unwind_Control_Block as exception
64db126ae2SDaniel Kiss   // object. Ensure struct _Unwind_Exception* work there too,
65db126ae2SDaniel Kiss   // because _Unwind_Exception in this case is just an alias.
66db126ae2SDaniel Kiss   struct _Unwind_Exception *e = &ex;
67db126ae2SDaniel Kiss #if defined(_LIBUNWIND_ARM_EHABI)
68db126ae2SDaniel Kiss   // Create a mock exception object.
69db126ae2SDaniel Kiss   memset(e, '\0', sizeof(*e));
70b7a249d2SMichael Kenzel   memcpy(&e->exception_class, "CLNGUNW", sizeof(e->exception_class));
71db126ae2SDaniel Kiss #endif
72db126ae2SDaniel Kiss   _Unwind_ForcedUnwind(e, stop, (void *)&foo);
73db126ae2SDaniel Kiss }
74db126ae2SDaniel Kiss 
main()75*fe1301b5SAlastair Houghton __attribute__((section("main_func"))) int main() {
76db126ae2SDaniel Kiss   foo();
77db126ae2SDaniel Kiss   return -2;
78db126ae2SDaniel Kiss }
79