1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker *
4*8d67ca89SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker *
8*8d67ca89SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker *
10*8d67ca89SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker */
16*8d67ca89SAndroid Build Coastguard Worker
17*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*8d67ca89SAndroid Build Coastguard Worker
19*8d67ca89SAndroid Build Coastguard Worker #include <setjmp.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h>
21*8d67ca89SAndroid Build Coastguard Worker #include <sys/syscall.h>
22*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
23*8d67ca89SAndroid Build Coastguard Worker
24*8d67ca89SAndroid Build Coastguard Worker #include <android-base/silent_death_test.h>
25*8d67ca89SAndroid Build Coastguard Worker #include <android-base/test_utils.h>
26*8d67ca89SAndroid Build Coastguard Worker
27*8d67ca89SAndroid Build Coastguard Worker #include "SignalUtils.h"
28*8d67ca89SAndroid Build Coastguard Worker
29*8d67ca89SAndroid Build Coastguard Worker using setjmp_DeathTest = SilentDeathTest;
30*8d67ca89SAndroid Build Coastguard Worker
TEST(setjmp,setjmp_smoke)31*8d67ca89SAndroid Build Coastguard Worker TEST(setjmp, setjmp_smoke) {
32*8d67ca89SAndroid Build Coastguard Worker int value;
33*8d67ca89SAndroid Build Coastguard Worker jmp_buf jb;
34*8d67ca89SAndroid Build Coastguard Worker if ((value = setjmp(jb)) == 0) {
35*8d67ca89SAndroid Build Coastguard Worker longjmp(jb, 123);
36*8d67ca89SAndroid Build Coastguard Worker FAIL(); // Unreachable.
37*8d67ca89SAndroid Build Coastguard Worker } else {
38*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(123, value);
39*8d67ca89SAndroid Build Coastguard Worker }
40*8d67ca89SAndroid Build Coastguard Worker }
41*8d67ca89SAndroid Build Coastguard Worker
TEST(setjmp,_setjmp_smoke)42*8d67ca89SAndroid Build Coastguard Worker TEST(setjmp, _setjmp_smoke) {
43*8d67ca89SAndroid Build Coastguard Worker int value;
44*8d67ca89SAndroid Build Coastguard Worker jmp_buf jb;
45*8d67ca89SAndroid Build Coastguard Worker if ((value = _setjmp(jb)) == 0) {
46*8d67ca89SAndroid Build Coastguard Worker _longjmp(jb, 456);
47*8d67ca89SAndroid Build Coastguard Worker FAIL(); // Unreachable.
48*8d67ca89SAndroid Build Coastguard Worker } else {
49*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(456, value);
50*8d67ca89SAndroid Build Coastguard Worker }
51*8d67ca89SAndroid Build Coastguard Worker }
52*8d67ca89SAndroid Build Coastguard Worker
TEST(setjmp,sigsetjmp_0_smoke)53*8d67ca89SAndroid Build Coastguard Worker TEST(setjmp, sigsetjmp_0_smoke) {
54*8d67ca89SAndroid Build Coastguard Worker int value;
55*8d67ca89SAndroid Build Coastguard Worker sigjmp_buf jb;
56*8d67ca89SAndroid Build Coastguard Worker if ((value = sigsetjmp(jb, 0)) == 0) {
57*8d67ca89SAndroid Build Coastguard Worker siglongjmp(jb, 789);
58*8d67ca89SAndroid Build Coastguard Worker FAIL(); // Unreachable.
59*8d67ca89SAndroid Build Coastguard Worker } else {
60*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(789, value);
61*8d67ca89SAndroid Build Coastguard Worker }
62*8d67ca89SAndroid Build Coastguard Worker }
63*8d67ca89SAndroid Build Coastguard Worker
TEST(setjmp,sigsetjmp_1_smoke)64*8d67ca89SAndroid Build Coastguard Worker TEST(setjmp, sigsetjmp_1_smoke) {
65*8d67ca89SAndroid Build Coastguard Worker int value;
66*8d67ca89SAndroid Build Coastguard Worker sigjmp_buf jb;
67*8d67ca89SAndroid Build Coastguard Worker if ((value = sigsetjmp(jb, 0)) == 0) {
68*8d67ca89SAndroid Build Coastguard Worker siglongjmp(jb, 0xabc);
69*8d67ca89SAndroid Build Coastguard Worker FAIL(); // Unreachable.
70*8d67ca89SAndroid Build Coastguard Worker } else {
71*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0xabc, value);
72*8d67ca89SAndroid Build Coastguard Worker }
73*8d67ca89SAndroid Build Coastguard Worker }
74*8d67ca89SAndroid Build Coastguard Worker
75*8d67ca89SAndroid Build Coastguard Worker // Two distinct signal sets.
76*8d67ca89SAndroid Build Coastguard Worker struct SigSets {
SigSetsSigSets77*8d67ca89SAndroid Build Coastguard Worker SigSets() : one(MakeSigSet(0)), two(MakeSigSet(1)) {
78*8d67ca89SAndroid Build Coastguard Worker }
79*8d67ca89SAndroid Build Coastguard Worker
MakeSigSetSigSets80*8d67ca89SAndroid Build Coastguard Worker static sigset64_t MakeSigSet(int offset) {
81*8d67ca89SAndroid Build Coastguard Worker sigset64_t ss;
82*8d67ca89SAndroid Build Coastguard Worker sigemptyset64(&ss);
83*8d67ca89SAndroid Build Coastguard Worker sigaddset64(&ss, SIGUSR1 + offset);
84*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
85*8d67ca89SAndroid Build Coastguard Worker // TIMER_SIGNAL.
86*8d67ca89SAndroid Build Coastguard Worker sigaddset64(&ss, __SIGRTMIN);
87*8d67ca89SAndroid Build Coastguard Worker #endif
88*8d67ca89SAndroid Build Coastguard Worker sigaddset64(&ss, SIGRTMIN + offset);
89*8d67ca89SAndroid Build Coastguard Worker return ss;
90*8d67ca89SAndroid Build Coastguard Worker }
91*8d67ca89SAndroid Build Coastguard Worker
92*8d67ca89SAndroid Build Coastguard Worker sigset64_t one;
93*8d67ca89SAndroid Build Coastguard Worker sigset64_t two;
94*8d67ca89SAndroid Build Coastguard Worker };
95*8d67ca89SAndroid Build Coastguard Worker
AssertSigmaskEquals(const sigset64_t & expected)96*8d67ca89SAndroid Build Coastguard Worker void AssertSigmaskEquals(const sigset64_t& expected) {
97*8d67ca89SAndroid Build Coastguard Worker sigset64_t actual;
98*8d67ca89SAndroid Build Coastguard Worker sigprocmask64(SIG_SETMASK, nullptr, &actual);
99*8d67ca89SAndroid Build Coastguard Worker size_t end = sizeof(expected) * 8;
100*8d67ca89SAndroid Build Coastguard Worker for (size_t i = 1; i <= end; ++i) {
101*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(sigismember64(&expected, i), sigismember64(&actual, i)) << i;
102*8d67ca89SAndroid Build Coastguard Worker }
103*8d67ca89SAndroid Build Coastguard Worker }
104*8d67ca89SAndroid Build Coastguard Worker
TEST(setjmp,_setjmp_signal_mask)105*8d67ca89SAndroid Build Coastguard Worker TEST(setjmp, _setjmp_signal_mask) {
106*8d67ca89SAndroid Build Coastguard Worker SignalMaskRestorer smr;
107*8d67ca89SAndroid Build Coastguard Worker
108*8d67ca89SAndroid Build Coastguard Worker // _setjmp/_longjmp do not save/restore the signal mask.
109*8d67ca89SAndroid Build Coastguard Worker SigSets ss;
110*8d67ca89SAndroid Build Coastguard Worker sigprocmask64(SIG_SETMASK, &ss.one, nullptr);
111*8d67ca89SAndroid Build Coastguard Worker jmp_buf jb;
112*8d67ca89SAndroid Build Coastguard Worker if (_setjmp(jb) == 0) {
113*8d67ca89SAndroid Build Coastguard Worker sigprocmask64(SIG_SETMASK, &ss.two, nullptr);
114*8d67ca89SAndroid Build Coastguard Worker _longjmp(jb, 1);
115*8d67ca89SAndroid Build Coastguard Worker FAIL(); // Unreachable.
116*8d67ca89SAndroid Build Coastguard Worker } else {
117*8d67ca89SAndroid Build Coastguard Worker AssertSigmaskEquals(ss.two);
118*8d67ca89SAndroid Build Coastguard Worker }
119*8d67ca89SAndroid Build Coastguard Worker }
120*8d67ca89SAndroid Build Coastguard Worker
TEST(setjmp,setjmp_signal_mask)121*8d67ca89SAndroid Build Coastguard Worker TEST(setjmp, setjmp_signal_mask) {
122*8d67ca89SAndroid Build Coastguard Worker SignalMaskRestorer smr;
123*8d67ca89SAndroid Build Coastguard Worker
124*8d67ca89SAndroid Build Coastguard Worker // setjmp/longjmp do save/restore the signal mask on bionic, but not on glibc.
125*8d67ca89SAndroid Build Coastguard Worker // This is a BSD versus System V historical accident. POSIX leaves the
126*8d67ca89SAndroid Build Coastguard Worker // behavior unspecified, so any code that cares needs to use sigsetjmp.
127*8d67ca89SAndroid Build Coastguard Worker SigSets ss;
128*8d67ca89SAndroid Build Coastguard Worker sigprocmask64(SIG_SETMASK, &ss.one, nullptr);
129*8d67ca89SAndroid Build Coastguard Worker jmp_buf jb;
130*8d67ca89SAndroid Build Coastguard Worker if (setjmp(jb) == 0) {
131*8d67ca89SAndroid Build Coastguard Worker sigprocmask64(SIG_SETMASK, &ss.two, nullptr);
132*8d67ca89SAndroid Build Coastguard Worker longjmp(jb, 1);
133*8d67ca89SAndroid Build Coastguard Worker FAIL(); // Unreachable.
134*8d67ca89SAndroid Build Coastguard Worker } else {
135*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
136*8d67ca89SAndroid Build Coastguard Worker // bionic behaves like BSD and does save/restore the signal mask.
137*8d67ca89SAndroid Build Coastguard Worker AssertSigmaskEquals(ss.one);
138*8d67ca89SAndroid Build Coastguard Worker #else
139*8d67ca89SAndroid Build Coastguard Worker // glibc behaves like System V and doesn't save/restore the signal mask.
140*8d67ca89SAndroid Build Coastguard Worker AssertSigmaskEquals(ss.two);
141*8d67ca89SAndroid Build Coastguard Worker #endif
142*8d67ca89SAndroid Build Coastguard Worker }
143*8d67ca89SAndroid Build Coastguard Worker }
144*8d67ca89SAndroid Build Coastguard Worker
TEST(setjmp,sigsetjmp_0_signal_mask)145*8d67ca89SAndroid Build Coastguard Worker TEST(setjmp, sigsetjmp_0_signal_mask) {
146*8d67ca89SAndroid Build Coastguard Worker SignalMaskRestorer smr;
147*8d67ca89SAndroid Build Coastguard Worker
148*8d67ca89SAndroid Build Coastguard Worker // sigsetjmp(0)/siglongjmp do not save/restore the signal mask.
149*8d67ca89SAndroid Build Coastguard Worker SigSets ss;
150*8d67ca89SAndroid Build Coastguard Worker sigprocmask64(SIG_SETMASK, &ss.one, nullptr);
151*8d67ca89SAndroid Build Coastguard Worker sigjmp_buf sjb;
152*8d67ca89SAndroid Build Coastguard Worker if (sigsetjmp(sjb, 0) == 0) {
153*8d67ca89SAndroid Build Coastguard Worker sigprocmask64(SIG_SETMASK, &ss.two, nullptr);
154*8d67ca89SAndroid Build Coastguard Worker siglongjmp(sjb, 1);
155*8d67ca89SAndroid Build Coastguard Worker FAIL(); // Unreachable.
156*8d67ca89SAndroid Build Coastguard Worker } else {
157*8d67ca89SAndroid Build Coastguard Worker AssertSigmaskEquals(ss.two);
158*8d67ca89SAndroid Build Coastguard Worker }
159*8d67ca89SAndroid Build Coastguard Worker }
160*8d67ca89SAndroid Build Coastguard Worker
TEST(setjmp,sigsetjmp_1_signal_mask)161*8d67ca89SAndroid Build Coastguard Worker TEST(setjmp, sigsetjmp_1_signal_mask) {
162*8d67ca89SAndroid Build Coastguard Worker SignalMaskRestorer smr;
163*8d67ca89SAndroid Build Coastguard Worker
164*8d67ca89SAndroid Build Coastguard Worker // sigsetjmp(1)/siglongjmp does save/restore the signal mask.
165*8d67ca89SAndroid Build Coastguard Worker SigSets ss;
166*8d67ca89SAndroid Build Coastguard Worker sigprocmask64(SIG_SETMASK, &ss.one, nullptr);
167*8d67ca89SAndroid Build Coastguard Worker sigjmp_buf sjb;
168*8d67ca89SAndroid Build Coastguard Worker if (sigsetjmp(sjb, 1) == 0) {
169*8d67ca89SAndroid Build Coastguard Worker sigprocmask64(SIG_SETMASK, &ss.two, nullptr);
170*8d67ca89SAndroid Build Coastguard Worker siglongjmp(sjb, 1);
171*8d67ca89SAndroid Build Coastguard Worker FAIL(); // Unreachable.
172*8d67ca89SAndroid Build Coastguard Worker } else {
173*8d67ca89SAndroid Build Coastguard Worker AssertSigmaskEquals(ss.one);
174*8d67ca89SAndroid Build Coastguard Worker }
175*8d67ca89SAndroid Build Coastguard Worker }
176*8d67ca89SAndroid Build Coastguard Worker
177*8d67ca89SAndroid Build Coastguard Worker #if defined(__arm__) || defined(__aarch64__)
178*8d67ca89SAndroid Build Coastguard Worker // arm and arm64 have the same callee save fp registers (8-15),
179*8d67ca89SAndroid Build Coastguard Worker // but use different instructions for accessing them.
180*8d67ca89SAndroid Build Coastguard Worker #if defined(__arm__)
181*8d67ca89SAndroid Build Coastguard Worker #define SET_FREG(n, v) asm volatile("vmov.f64 d"#n ", #"#v : : : "d"#n)
182*8d67ca89SAndroid Build Coastguard Worker #define GET_FREG(n) ({ double _r; asm volatile("fcpyd %P0, d"#n : "=w"(_r) : :); _r;})
183*8d67ca89SAndroid Build Coastguard Worker #define CLEAR_FREG(n) asm volatile("vmov.i64 d"#n ", #0x0" : : : "d"#n)
184*8d67ca89SAndroid Build Coastguard Worker #elif defined(__aarch64__)
185*8d67ca89SAndroid Build Coastguard Worker #define SET_FREG(n, v) asm volatile("fmov d"#n ", "#v : : : "d"#n)
186*8d67ca89SAndroid Build Coastguard Worker #define GET_FREG(n) ({ double _r; asm volatile("fmov %0, d"#n : "=r"(_r) : :); _r; })
187*8d67ca89SAndroid Build Coastguard Worker #define CLEAR_FREG(n) asm volatile("fmov d"#n ", xzr" : : : "d"#n)
188*8d67ca89SAndroid Build Coastguard Worker #endif
189*8d67ca89SAndroid Build Coastguard Worker #define SET_FREGS \
190*8d67ca89SAndroid Build Coastguard Worker SET_FREG(8, 8.0); SET_FREG(9, 9.0); SET_FREG(10, 10.0); SET_FREG(11, 11.0); \
191*8d67ca89SAndroid Build Coastguard Worker SET_FREG(12, 12.0); SET_FREG(13, 13.0); SET_FREG(14, 14.0); SET_FREG(15, 15.0)
192*8d67ca89SAndroid Build Coastguard Worker #define CLEAR_FREGS \
193*8d67ca89SAndroid Build Coastguard Worker CLEAR_FREG(8); CLEAR_FREG(9); CLEAR_FREG(10); CLEAR_FREG(11); \
194*8d67ca89SAndroid Build Coastguard Worker CLEAR_FREG(12); CLEAR_FREG(13); CLEAR_FREG(14); CLEAR_FREG(15)
195*8d67ca89SAndroid Build Coastguard Worker #define CHECK_FREGS \
196*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(8.0, GET_FREG(8)); EXPECT_EQ(9.0, GET_FREG(9)); \
197*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(10.0, GET_FREG(10)); EXPECT_EQ(11.0, GET_FREG(11)); \
198*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(12.0, GET_FREG(12)); EXPECT_EQ(13.0, GET_FREG(13)); \
199*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(14.0, GET_FREG(14)); EXPECT_EQ(15.0, GET_FREG(15))
200*8d67ca89SAndroid Build Coastguard Worker
201*8d67ca89SAndroid Build Coastguard Worker #elif defined(__riscv)
202*8d67ca89SAndroid Build Coastguard Worker // riscv64 has callee save registers fs0-fs11.
203*8d67ca89SAndroid Build Coastguard Worker // TODO: use Zfa to get 1.0 rather than the one_p trick.
204*8d67ca89SAndroid Build Coastguard Worker #define SET_FREGS \
205*8d67ca89SAndroid Build Coastguard Worker double one = 1, *one_p = &one; \
206*8d67ca89SAndroid Build Coastguard Worker asm volatile("fmv.d.x fs0, zero ; fld fs1, (%0) ; \
207*8d67ca89SAndroid Build Coastguard Worker fadd.d fs2, fs1, fs1 ; fadd.d fs3, fs2, fs1 ; \
208*8d67ca89SAndroid Build Coastguard Worker fadd.d fs4, fs3, fs1 ; fadd.d fs5, fs4, fs1 ; \
209*8d67ca89SAndroid Build Coastguard Worker fadd.d fs6, fs5, fs1 ; fadd.d fs7, fs6, fs1 ; \
210*8d67ca89SAndroid Build Coastguard Worker fadd.d fs8, fs7, fs1 ; fadd.d fs9, fs8, fs1 ; \
211*8d67ca89SAndroid Build Coastguard Worker fadd.d fs10, fs9, fs1 ; fadd.d fs11, fs10, fs1" \
212*8d67ca89SAndroid Build Coastguard Worker : \
213*8d67ca89SAndroid Build Coastguard Worker : "r"(one_p) \
214*8d67ca89SAndroid Build Coastguard Worker : "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", \
215*8d67ca89SAndroid Build Coastguard Worker "fs6", "fs7", "fs8", "fs9", "fs10", "fs11")
216*8d67ca89SAndroid Build Coastguard Worker #define CLEAR_FREGS \
217*8d67ca89SAndroid Build Coastguard Worker asm volatile("fmv.d.x fs0, zero ; fmv.d.x fs1, zero ; \
218*8d67ca89SAndroid Build Coastguard Worker fmv.d.x fs2, zero ; fmv.d.x fs3, zero ; \
219*8d67ca89SAndroid Build Coastguard Worker fmv.d.x fs4, zero ; fmv.d.x fs5, zero ; \
220*8d67ca89SAndroid Build Coastguard Worker fmv.d.x fs6, zero ; fmv.d.x fs7, zero ; \
221*8d67ca89SAndroid Build Coastguard Worker fmv.d.x fs8, zero ; fmv.d.x fs9, zero ; \
222*8d67ca89SAndroid Build Coastguard Worker fmv.d.x fs10, zero ; fmv.d.x fs11, zero" \
223*8d67ca89SAndroid Build Coastguard Worker : : : "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", \
224*8d67ca89SAndroid Build Coastguard Worker "fs6", "fs7", "fs8", "fs9", "fs10", "fs11")
225*8d67ca89SAndroid Build Coastguard Worker #define GET_FREG(n) ({ double _r; asm volatile("fmv.d %0, fs"#n : "=f"(_r) : :); _r; })
226*8d67ca89SAndroid Build Coastguard Worker #define CHECK_FREGS \
227*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(0.0, GET_FREG(0)); EXPECT_EQ(1.0, GET_FREG(1)); \
228*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(2.0, GET_FREG(2)); EXPECT_EQ(3.0, GET_FREG(3)); \
229*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(4.0, GET_FREG(4)); EXPECT_EQ(5.0, GET_FREG(5)); \
230*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(6.0, GET_FREG(6)); EXPECT_EQ(7.0, GET_FREG(7)); \
231*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(8.0, GET_FREG(8)); EXPECT_EQ(9.0, GET_FREG(9)); \
232*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(10.0, GET_FREG(10)); EXPECT_EQ(11.0, GET_FREG(11))
233*8d67ca89SAndroid Build Coastguard Worker
234*8d67ca89SAndroid Build Coastguard Worker #else
235*8d67ca89SAndroid Build Coastguard Worker // x86 and x86-64 don't save/restore fp registers.
236*8d67ca89SAndroid Build Coastguard Worker #define SET_FREGS
237*8d67ca89SAndroid Build Coastguard Worker #define CLEAR_FREGS
238*8d67ca89SAndroid Build Coastguard Worker #define CHECK_FREGS
239*8d67ca89SAndroid Build Coastguard Worker #endif
240*8d67ca89SAndroid Build Coastguard Worker
TEST(setjmp,setjmp_fp_registers)241*8d67ca89SAndroid Build Coastguard Worker TEST(setjmp, setjmp_fp_registers) {
242*8d67ca89SAndroid Build Coastguard Worker int value;
243*8d67ca89SAndroid Build Coastguard Worker jmp_buf jb;
244*8d67ca89SAndroid Build Coastguard Worker SET_FREGS;
245*8d67ca89SAndroid Build Coastguard Worker if ((value = setjmp(jb)) == 0) {
246*8d67ca89SAndroid Build Coastguard Worker CLEAR_FREGS;
247*8d67ca89SAndroid Build Coastguard Worker longjmp(jb, 123);
248*8d67ca89SAndroid Build Coastguard Worker FAIL(); // Unreachable.
249*8d67ca89SAndroid Build Coastguard Worker } else {
250*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(123, value);
251*8d67ca89SAndroid Build Coastguard Worker CHECK_FREGS;
252*8d67ca89SAndroid Build Coastguard Worker }
253*8d67ca89SAndroid Build Coastguard Worker }
254*8d67ca89SAndroid Build Coastguard Worker
255*8d67ca89SAndroid Build Coastguard Worker #if defined(__arm__)
256*8d67ca89SAndroid Build Coastguard Worker #define JB_SIGFLAG_OFFSET 0
257*8d67ca89SAndroid Build Coastguard Worker #elif defined(__aarch64__)
258*8d67ca89SAndroid Build Coastguard Worker #define JB_SIGFLAG_OFFSET 0
259*8d67ca89SAndroid Build Coastguard Worker #elif defined(__i386__)
260*8d67ca89SAndroid Build Coastguard Worker #define JB_SIGFLAG_OFFSET 8
261*8d67ca89SAndroid Build Coastguard Worker #elif defined(__riscv)
262*8d67ca89SAndroid Build Coastguard Worker #define JB_SIGFLAG_OFFSET 0
263*8d67ca89SAndroid Build Coastguard Worker #elif defined(__x86_64)
264*8d67ca89SAndroid Build Coastguard Worker #define JB_SIGFLAG_OFFSET 8
265*8d67ca89SAndroid Build Coastguard Worker #endif
266*8d67ca89SAndroid Build Coastguard Worker
TEST_F(setjmp_DeathTest,setjmp_cookie)267*8d67ca89SAndroid Build Coastguard Worker TEST_F(setjmp_DeathTest, setjmp_cookie) {
268*8d67ca89SAndroid Build Coastguard Worker jmp_buf jb;
269*8d67ca89SAndroid Build Coastguard Worker int value = setjmp(jb);
270*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, value);
271*8d67ca89SAndroid Build Coastguard Worker
272*8d67ca89SAndroid Build Coastguard Worker long* sigflag = reinterpret_cast<long*>(jb) + JB_SIGFLAG_OFFSET;
273*8d67ca89SAndroid Build Coastguard Worker
274*8d67ca89SAndroid Build Coastguard Worker // Make sure there's actually a cookie.
275*8d67ca89SAndroid Build Coastguard Worker EXPECT_NE(0, *sigflag & ~1);
276*8d67ca89SAndroid Build Coastguard Worker
277*8d67ca89SAndroid Build Coastguard Worker // Wipe it out
278*8d67ca89SAndroid Build Coastguard Worker *sigflag &= 1;
279*8d67ca89SAndroid Build Coastguard Worker EXPECT_DEATH(longjmp(jb, 0), "");
280*8d67ca89SAndroid Build Coastguard Worker }
281*8d67ca89SAndroid Build Coastguard Worker
TEST_F(setjmp_DeathTest,setjmp_cookie_checksum)282*8d67ca89SAndroid Build Coastguard Worker TEST_F(setjmp_DeathTest, setjmp_cookie_checksum) {
283*8d67ca89SAndroid Build Coastguard Worker jmp_buf jb;
284*8d67ca89SAndroid Build Coastguard Worker int value = setjmp(jb);
285*8d67ca89SAndroid Build Coastguard Worker
286*8d67ca89SAndroid Build Coastguard Worker if (value == 0) {
287*8d67ca89SAndroid Build Coastguard Worker // Flip a bit.
288*8d67ca89SAndroid Build Coastguard Worker reinterpret_cast<long*>(jb)[1] ^= 1;
289*8d67ca89SAndroid Build Coastguard Worker
290*8d67ca89SAndroid Build Coastguard Worker EXPECT_DEATH(longjmp(jb, 1), "checksum mismatch");
291*8d67ca89SAndroid Build Coastguard Worker } else {
292*8d67ca89SAndroid Build Coastguard Worker fprintf(stderr, "setjmp_cookie_checksum: longjmp succeeded?");
293*8d67ca89SAndroid Build Coastguard Worker }
294*8d67ca89SAndroid Build Coastguard Worker }
295*8d67ca89SAndroid Build Coastguard Worker
call_longjmp(jmp_buf buf)296*8d67ca89SAndroid Build Coastguard Worker __attribute__((noinline)) void call_longjmp(jmp_buf buf) {
297*8d67ca89SAndroid Build Coastguard Worker longjmp(buf, 123);
298*8d67ca89SAndroid Build Coastguard Worker }
299*8d67ca89SAndroid Build Coastguard Worker
TEST(setjmp,setjmp_stack)300*8d67ca89SAndroid Build Coastguard Worker TEST(setjmp, setjmp_stack) {
301*8d67ca89SAndroid Build Coastguard Worker jmp_buf buf;
302*8d67ca89SAndroid Build Coastguard Worker int value = setjmp(buf);
303*8d67ca89SAndroid Build Coastguard Worker if (value == 0) call_longjmp(buf);
304*8d67ca89SAndroid Build Coastguard Worker EXPECT_EQ(123, value);
305*8d67ca89SAndroid Build Coastguard Worker }
306*8d67ca89SAndroid Build Coastguard Worker
TEST(setjmp,bug_152210274)307*8d67ca89SAndroid Build Coastguard Worker TEST(setjmp, bug_152210274) {
308*8d67ca89SAndroid Build Coastguard Worker // Ensure that we never have a mangled value in the stack pointer.
309*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
310*8d67ca89SAndroid Build Coastguard Worker struct sigaction sa = {.sa_flags = SA_SIGINFO, .sa_sigaction = [](int, siginfo_t*, void*) {}};
311*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, sigaction(SIGPROF, &sa, 0));
312*8d67ca89SAndroid Build Coastguard Worker
313*8d67ca89SAndroid Build Coastguard Worker constexpr size_t kNumThreads = 20;
314*8d67ca89SAndroid Build Coastguard Worker
315*8d67ca89SAndroid Build Coastguard Worker // Start a bunch of threads calling setjmp/longjmp.
316*8d67ca89SAndroid Build Coastguard Worker auto jumper = [](void* arg) -> void* {
317*8d67ca89SAndroid Build Coastguard Worker sigset_t set;
318*8d67ca89SAndroid Build Coastguard Worker sigemptyset(&set);
319*8d67ca89SAndroid Build Coastguard Worker sigaddset(&set, SIGPROF);
320*8d67ca89SAndroid Build Coastguard Worker pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
321*8d67ca89SAndroid Build Coastguard Worker
322*8d67ca89SAndroid Build Coastguard Worker jmp_buf buf;
323*8d67ca89SAndroid Build Coastguard Worker for (size_t count = 0; count < 100000; ++count) {
324*8d67ca89SAndroid Build Coastguard Worker if (setjmp(buf) != 0) {
325*8d67ca89SAndroid Build Coastguard Worker perror("setjmp");
326*8d67ca89SAndroid Build Coastguard Worker abort();
327*8d67ca89SAndroid Build Coastguard Worker }
328*8d67ca89SAndroid Build Coastguard Worker // This will never be true, but the compiler doesn't know that, so the
329*8d67ca89SAndroid Build Coastguard Worker // setjmp won't be removed by DCE. With HWASan/MTE this also acts as a
330*8d67ca89SAndroid Build Coastguard Worker // kind of enforcement that the threads are done before leaving the test.
331*8d67ca89SAndroid Build Coastguard Worker if (*static_cast<size_t*>(arg) != 123) longjmp(buf, 1);
332*8d67ca89SAndroid Build Coastguard Worker }
333*8d67ca89SAndroid Build Coastguard Worker return nullptr;
334*8d67ca89SAndroid Build Coastguard Worker };
335*8d67ca89SAndroid Build Coastguard Worker pthread_t threads[kNumThreads];
336*8d67ca89SAndroid Build Coastguard Worker pid_t tids[kNumThreads] = {};
337*8d67ca89SAndroid Build Coastguard Worker size_t var = 123;
338*8d67ca89SAndroid Build Coastguard Worker for (size_t i = 0; i < kNumThreads; ++i) {
339*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, pthread_create(&threads[i], nullptr, jumper, &var));
340*8d67ca89SAndroid Build Coastguard Worker tids[i] = pthread_gettid_np(threads[i]);
341*8d67ca89SAndroid Build Coastguard Worker }
342*8d67ca89SAndroid Build Coastguard Worker
343*8d67ca89SAndroid Build Coastguard Worker // Start the interrupter thread.
344*8d67ca89SAndroid Build Coastguard Worker auto interrupter = [](void* arg) -> void* {
345*8d67ca89SAndroid Build Coastguard Worker pid_t* tids = static_cast<pid_t*>(arg);
346*8d67ca89SAndroid Build Coastguard Worker for (size_t count = 0; count < 1000; ++count) {
347*8d67ca89SAndroid Build Coastguard Worker for (size_t i = 0; i < kNumThreads; i++) {
348*8d67ca89SAndroid Build Coastguard Worker if (tgkill(getpid(), tids[i], SIGPROF) == -1 && errno != ESRCH) {
349*8d67ca89SAndroid Build Coastguard Worker perror("tgkill failed");
350*8d67ca89SAndroid Build Coastguard Worker abort();
351*8d67ca89SAndroid Build Coastguard Worker }
352*8d67ca89SAndroid Build Coastguard Worker }
353*8d67ca89SAndroid Build Coastguard Worker usleep(100);
354*8d67ca89SAndroid Build Coastguard Worker }
355*8d67ca89SAndroid Build Coastguard Worker return nullptr;
356*8d67ca89SAndroid Build Coastguard Worker };
357*8d67ca89SAndroid Build Coastguard Worker pthread_t t;
358*8d67ca89SAndroid Build Coastguard Worker ASSERT_EQ(0, pthread_create(&t, nullptr, interrupter, tids));
359*8d67ca89SAndroid Build Coastguard Worker pthread_join(t, nullptr);
360*8d67ca89SAndroid Build Coastguard Worker for (size_t i = 0; i < kNumThreads; i++) {
361*8d67ca89SAndroid Build Coastguard Worker pthread_join(threads[i], nullptr);
362*8d67ca89SAndroid Build Coastguard Worker }
363*8d67ca89SAndroid Build Coastguard Worker #else
364*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "tests uses functions not in glibc";
365*8d67ca89SAndroid Build Coastguard Worker #endif
366*8d67ca89SAndroid Build Coastguard Worker }
367