1 /* Check setjmp/longjmp between user contexts.
2 Copyright (C) 2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
23 #include <stackinfo.h>
25 static ucontext_t uctx_main
, uctx_func1
, uctx_func2
;
26 const char *str1
= "\e[31mswapcontext(&uctx_func1, &uctx_main)\e[0m";
27 const char *str2
= "\e[34mswapcontext(&uctx_func2, &uctx_main)\e[0m";
28 const char *fmt1
= "\e[31m";
29 const char *fmt2
= "\e[34m";
30 static jmp_buf jmpbuf
;
32 #define handle_error(msg) \
33 do { perror(msg); exit(EXIT_FAILURE); } while (0)
35 __attribute__((noinline
, noclone
))
37 func4(ucontext_t
*uocp
, ucontext_t
*ucp
, const char *str
, const char *fmt
)
39 printf(" %sfunc4: %s\e[0m\n", fmt
, str
);
40 if (swapcontext(uocp
, ucp
) == -1)
41 handle_error("swapcontext");
42 printf(" %sfunc4: returning\e[0m\n", fmt
);
45 __attribute__((noinline
, noclone
))
47 func3(ucontext_t
*uocp
, ucontext_t
*ucp
, const char *str
, const char *fmt
)
49 printf(" %sfunc3: func4(uocp, ucp, str)\e[0m\n", fmt
);
50 func4(uocp
, ucp
, str
, fmt
);
51 printf(" %sfunc3: returning\e[0m\n", fmt
);
54 __attribute__((noinline
, noclone
))
60 printf(" \e[31mfunc1: func3(&uctx_func1, &uctx_main, str1)\e[0m\n");
61 if (setjmp (jmpbuf
) != 0)
63 printf(" %sfunc1: from longjmp\e[0m\n", fmt1
);
66 func3( &uctx_func1
, &uctx_main
, str1
, fmt1
);
70 __attribute__((noinline
, noclone
))
76 printf(" \e[34mfunc2: func3(&uctx_func2, &uctx_main, str2)\e[0m\n");
77 func3(&uctx_func2
, &uctx_main
, str2
, fmt2
);
78 printf(" %sfunc2: calling longjmp\e[0m\n", fmt2
);
86 /* ____longjmp_chk has */
88 #ifdef _STACK_GROWS_DOWN
89 #define called_from(this, saved) ((this) < (saved))
91 #define called_from(this, saved) ((this) > (saved))
94 /* If "env" is from a frame that called us, we're all set. */
95 if (called_from(this_frame
, saved_frame
))
98 /* Arrange stacks for uctx_func1 and uctx_func2 so that called_from
99 is true when setjmp is called from uctx_func1 and longjmp is called
101 #ifdef _STACK_GROWS_DOWN
102 # define UCTX_FUNC1_STACK 1
103 # define UCTX_FUNC2_STACK 0
105 # define UCTX_FUNC1_STACK 0
106 # define UCTX_FUNC2_STACK 1
108 char func_stack
[2][16384];
111 if (getcontext(&uctx_func1
) == -1)
112 handle_error("getcontext");
113 uctx_func1
.uc_stack
.ss_sp
= func_stack
[UCTX_FUNC1_STACK
];
114 uctx_func1
.uc_stack
.ss_size
= sizeof (func_stack
[UCTX_FUNC1_STACK
]);
115 uctx_func1
.uc_link
= &uctx_main
;
116 makecontext(&uctx_func1
, func1
, 0);
118 if (getcontext(&uctx_func2
) == -1)
119 handle_error("getcontext");
120 uctx_func2
.uc_stack
.ss_sp
= func_stack
[UCTX_FUNC2_STACK
];
121 uctx_func2
.uc_stack
.ss_size
= sizeof (func_stack
[UCTX_FUNC2_STACK
]);
122 uctx_func2
.uc_link
= &uctx_func1
;
123 makecontext(&uctx_func2
, func2
, 0);
125 for ( i
= 0; i
< 2; i
++ )
127 if (swapcontext(&uctx_main
, &uctx_func1
) == -1)
128 handle_error("swapcontext");
129 printf(" \e[35mmain: swapcontext(&uctx_main, &uctx_func2)\n\e[0m");
130 if (swapcontext(&uctx_main
, &uctx_func2
) == -1)
131 handle_error("swapcontext");
132 printf(" \e[35mmain: swapcontext(&uctx_main, &uctx_func1)\n\e[0m");
138 #include <support/test-driver.c>