| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* Copyright (C) 2006-2016 Free Software Foundation, Inc. | 
|  | 2 | This file is part of the GNU C Library. | 
|  | 3 |  | 
|  | 4 | The GNU C Library is free software; you can redistribute it and/or | 
|  | 5 | modify it under the terms of the GNU Lesser General Public | 
|  | 6 | License as published by the Free Software Foundation; either | 
|  | 7 | version 2.1 of the License, or (at your option) any later version. | 
|  | 8 |  | 
|  | 9 | The GNU C Library is distributed in the hope that it will be useful, | 
|  | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | 12 | Lesser General Public License for more details. | 
|  | 13 |  | 
|  | 14 | You should have received a copy of the GNU Lesser General Public | 
|  | 15 | License along with the GNU C Library; if not, see | 
|  | 16 | <http://www.gnu.org/licenses/>.  */ | 
|  | 17 |  | 
|  | 18 | #include <errno.h> | 
|  | 19 | #include <stdlib.h> | 
|  | 20 | #include <stdio.h> | 
|  | 21 | #include <ucontext.h> | 
|  | 22 | #include <assert.h> | 
|  | 23 | #include <unwind.h> | 
|  | 24 | #include <dlfcn.h> | 
|  | 25 | #include <gnu/lib-names.h> | 
|  | 26 |  | 
|  | 27 | ucontext_t ucp; | 
|  | 28 | char st1[16384]; | 
|  | 29 | __thread int thr; | 
|  | 30 |  | 
|  | 31 | int somevar = -76; | 
|  | 32 | long othervar = -78L; | 
|  | 33 |  | 
|  | 34 | struct trace_arg | 
|  | 35 | { | 
|  | 36 | int cnt, size; | 
|  | 37 | }; | 
|  | 38 |  | 
|  | 39 | static _Unwind_Reason_Code | 
|  | 40 | backtrace_helper (struct _Unwind_Context *ctx, void *a) | 
|  | 41 | { | 
|  | 42 | struct trace_arg *arg = a; | 
|  | 43 | if (++arg->cnt == arg->size) | 
|  | 44 | return _URC_END_OF_STACK; | 
|  | 45 | return _URC_NO_REASON; | 
|  | 46 | } | 
|  | 47 |  | 
|  | 48 | void | 
|  | 49 | cf (int i) | 
|  | 50 | { | 
|  | 51 | struct trace_arg arg = { .size = 100, .cnt = -1 }; | 
|  | 52 | void *handle; | 
|  | 53 | _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *); | 
|  | 54 |  | 
|  | 55 | if (i != othervar || thr != 94) | 
|  | 56 | { | 
|  | 57 | printf ("i %d thr %d\n", i, thr); | 
|  | 58 | exit (1); | 
|  | 59 | } | 
|  | 60 |  | 
|  | 61 | /* Test if callback function of _Unwind_Backtrace is not called infinitely | 
|  | 62 | times. See Bug 18508 or gcc bug "Bug 66303 - runtime.Caller() returns | 
|  | 63 | infinitely deep stack frames on s390x.". | 
|  | 64 | The go runtime calls backtrace_full() in | 
|  | 65 | <gcc-src>/libbacktrace/backtrace.c, which uses _Unwind_Backtrace().  */ | 
|  | 66 | handle = dlopen (LIBGCC_S_SO, RTLD_LAZY); | 
|  | 67 | if (handle != NULL) | 
|  | 68 | { | 
|  | 69 | unwind_backtrace = dlsym (handle, "_Unwind_Backtrace"); | 
|  | 70 | if (unwind_backtrace != NULL) | 
|  | 71 | { | 
|  | 72 | unwind_backtrace (backtrace_helper, &arg); | 
|  | 73 | assert (arg.cnt != -1 && arg.cnt < 100); | 
|  | 74 | } | 
|  | 75 | dlclose (handle); | 
|  | 76 | } | 
|  | 77 |  | 
|  | 78 | /* Since uc_link below has been set to NULL, setcontext is supposed to | 
|  | 79 | terminate the process normally after this function returns.  */ | 
|  | 80 | } | 
|  | 81 |  | 
|  | 82 | int | 
|  | 83 | do_test (void) | 
|  | 84 | { | 
|  | 85 | if (getcontext (&ucp) != 0) | 
|  | 86 | { | 
|  | 87 | if (errno == ENOSYS) | 
|  | 88 | { | 
|  | 89 | puts ("context handling not supported"); | 
|  | 90 | return 0; | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 | puts ("getcontext failed"); | 
|  | 94 | return 1; | 
|  | 95 | } | 
|  | 96 | thr = 94; | 
|  | 97 | ucp.uc_link = NULL; | 
|  | 98 | ucp.uc_stack.ss_sp = st1; | 
|  | 99 | ucp.uc_stack.ss_size = sizeof st1; | 
|  | 100 | makecontext (&ucp, (void (*) (void)) cf, 1, somevar - 2); | 
|  | 101 | if (setcontext (&ucp) != 0) | 
|  | 102 | { | 
|  | 103 | puts ("setcontext failed"); | 
|  | 104 | return 1; | 
|  | 105 | } | 
|  | 106 | return 2; | 
|  | 107 | } | 
|  | 108 |  | 
|  | 109 | #define TEST_FUNCTION do_test () | 
|  | 110 | #include "../test-skeleton.c" |