1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License, Version 1.0 only
7 * (the "License"). You may not use this file except in compliance
8 * with the License.
9 *
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or https://opensource.org/licenses/CDDL-1.0.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
20 *
21 * CDDL HEADER END
22 */
23 /*
24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 #include_next <assert.h>
29
30 #ifndef _LIBSPL_ASSERT_H
31 #define _LIBSPL_ASSERT_H
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <sys/types.h>
37
38 /* Workaround for non-Clang compilers */
39 #ifndef __has_feature
40 #define __has_feature(x) 0
41 #endif
42
43 /* We need to workaround libspl_set_assert_ok() that we have for zdb */
44 #if __has_feature(attribute_analyzer_noreturn) || defined(__COVERITY__)
45 #define NORETURN __attribute__((__noreturn__))
46 #else
47 #define NORETURN
48 #endif
49
50 /* Set to non-zero to avoid abort()ing on an assertion failure */
51 extern void libspl_set_assert_ok(boolean_t val);
52
53 /* printf version of libspl_assert */
54 extern void libspl_assertf(const char *file, const char *func, int line,
55 const char *format, ...) NORETURN __attribute__((format(printf, 4, 5)));
56
57 static inline int
libspl_assert(const char * buf,const char * file,const char * func,int line)58 libspl_assert(const char *buf, const char *file, const char *func, int line)
59 {
60 libspl_assertf(file, func, line, "%s", buf);
61 return (0);
62 }
63
64 #ifdef verify
65 #undef verify
66 #endif
67
68 #define PANIC(fmt, a...) \
69 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, fmt, ## a)
70
71 #define VERIFY(cond) \
72 (void) ((!(cond)) && \
73 libspl_assert(#cond, __FILE__, __FUNCTION__, __LINE__))
74
75 #define VERIFYF(cond, STR, ...) \
76 do { \
77 if (!(cond)) \
78 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
79 "%s " STR, #cond, \
80 __VA_ARGS__); \
81 } while (0)
82
83 #define verify(cond) \
84 (void) ((!(cond)) && \
85 libspl_assert(#cond, __FILE__, __FUNCTION__, __LINE__))
86
87 #define VERIFY3B(LEFT, OP, RIGHT) \
88 do { \
89 const boolean_t __left = (boolean_t)!!(LEFT); \
90 const boolean_t __right = (boolean_t)!!(RIGHT); \
91 if (!(__left OP __right)) \
92 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
93 "VERIFY3B(%s, %s, %s) failed " \
94 "(%d %s %d)", #LEFT, #OP, #RIGHT, \
95 __left, #OP, __right); \
96 } while (0)
97
98 #define VERIFY3S(LEFT, OP, RIGHT) \
99 do { \
100 const int64_t __left = (int64_t)(LEFT); \
101 const int64_t __right = (int64_t)(RIGHT); \
102 if (!(__left OP __right)) \
103 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
104 "VERIFY3S(%s, %s, %s) failed " \
105 "(%lld %s 0x%lld)", #LEFT, #OP, #RIGHT, \
106 (longlong_t)__left, #OP, (longlong_t)__right); \
107 } while (0)
108
109 #define VERIFY3U(LEFT, OP, RIGHT) \
110 do { \
111 const uint64_t __left = (uint64_t)(LEFT); \
112 const uint64_t __right = (uint64_t)(RIGHT); \
113 if (!(__left OP __right)) \
114 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
115 "VERIFY3U(%s, %s, %s) failed " \
116 "(%llu %s %llu)", #LEFT, #OP, #RIGHT, \
117 (u_longlong_t)__left, #OP, (u_longlong_t)__right); \
118 } while (0)
119
120 #define VERIFY3P(LEFT, OP, RIGHT) \
121 do { \
122 const uintptr_t __left = (uintptr_t)(LEFT); \
123 const uintptr_t __right = (uintptr_t)(RIGHT); \
124 if (!(__left OP __right)) \
125 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
126 "VERIFY3P(%s, %s, %s) failed " \
127 "(%p %s %p)", #LEFT, #OP, #RIGHT, \
128 (void *)__left, #OP, (void *)__right); \
129 } while (0)
130
131 #define VERIFY0(LEFT) \
132 do { \
133 const uint64_t __left = (uint64_t)(LEFT); \
134 if (!(__left == 0)) \
135 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
136 "VERIFY0(%s) failed (%lld)", #LEFT, \
137 (u_longlong_t)__left); \
138 } while (0)
139
140 #define VERIFY0P(LEFT) \
141 do { \
142 const uintptr_t __left = (uintptr_t)(LEFT); \
143 if (!(__left == 0)) \
144 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
145 "VERIFY0P(%s) failed (%p)", #LEFT, \
146 (void *)__left); \
147 } while (0)
148
149 /*
150 * This is just here because cstyle gets upset about #LEFT
151 * on a newline.
152 */
153
154 /* BEGIN CSTYLED */
155 #define VERIFY3BF(LEFT, OP, RIGHT, STR, ...) \
156 do { \
157 const boolean_t __left = (boolean_t)!!(LEFT); \
158 const boolean_t __right = (boolean_t)!!(RIGHT); \
159 if (!(__left OP __right)) \
160 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
161 "VERIFY3B(%s, %s, %s) failed " \
162 "(%d %s %d) " STR, #LEFT, #OP, #RIGHT, \
163 __left, #OP, __right, \
164 __VA_ARGS__); \
165 } while (0)
166
167 #define VERIFY3SF(LEFT, OP, RIGHT, STR, ...) \
168 do { \
169 const int64_t __left = (int64_t)(LEFT); \
170 const int64_t __right = (int64_t)(RIGHT); \
171 if (!(__left OP __right)) \
172 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
173 "VERIFY3S(%s, %s, %s) failed " \
174 "(%lld %s %lld) " STR, #LEFT, #OP, #RIGHT, \
175 (longlong_t)__left, #OP, (longlong_t)__right, \
176 __VA_ARGS__); \
177 } while (0)
178
179 #define VERIFY3UF(LEFT, OP, RIGHT, STR, ...) \
180 do { \
181 const uint64_t __left = (uint64_t)(LEFT); \
182 const uint64_t __right = (uint64_t)(RIGHT); \
183 if (!(__left OP __right)) \
184 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
185 "VERIFY3U(%s, %s, %s) failed " \
186 "(%llu %s %llu) " STR, #LEFT, #OP, #RIGHT, \
187 (u_longlong_t)__left, #OP, (u_longlong_t)__right, \
188 __VA_ARGS__); \
189 } while (0)
190
191 #define VERIFY3PF(LEFT, OP, RIGHT, STR, ...) \
192 do { \
193 const uintptr_t __left = (uintptr_t)(LEFT); \
194 const uintptr_t __right = (uintptr_t)(RIGHT); \
195 if (!(__left OP __right)) \
196 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
197 "VERIFY3P(%s, %s, %s) failed " \
198 "(%p %s %p) " STR, #LEFT, #OP, #RIGHT, \
199 (void *)__left, #OP, (void *)__right, \
200 __VA_ARGS__); \
201 } while (0)
202 /* END CSTYLED */
203
204 #define VERIFY0F(LEFT, STR, ...) \
205 do { \
206 const int64_t __left = (int64_t)(LEFT); \
207 if (!(__left == 0)) \
208 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
209 "VERIFY0(%s) failed (%lld) " STR, #LEFT, \
210 (longlong_t)__left, __VA_ARGS__); \
211 } while (0)
212
213 #define VERIFY0PF(LEFT, STR, ...) \
214 do { \
215 const uintptr_t __left = (uintptr_t)(LEFT); \
216 if (!(__left == 0)) \
217 libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
218 "VERIFY0P(%s) failed (%p) " STR, #LEFT, \
219 (void *)__left, __VA_ARGS__); \
220 } while (0)
221
222 #ifdef assert
223 #undef assert
224 #endif
225
226 #ifdef NDEBUG
227 #define ASSERT3B(x, y, z) \
228 ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
229 #define ASSERT3S(x, y, z) \
230 ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
231 #define ASSERT3U(x, y, z) \
232 ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
233 #define ASSERT3P(x, y, z) \
234 ((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
235 #define ASSERT0(x) ((void) sizeof ((uintptr_t)(x)))
236 #define ASSERT0P(x) ((void) sizeof ((uintptr_t)(x)))
237 #define ASSERT3BF(x, y, z, str, ...) ASSERT3B(x, y, z)
238 #define ASSERT3SF(x, y, z, str, ...) ASSERT3S(x, y, z)
239 #define ASSERT3UF(x, y, z, str, ...) ASSERT3U(x, y, z)
240 #define ASSERT3PF(x, y, z, str, ...) ASSERT3P(x, y, z)
241 #define ASSERT0P(x) ((void) sizeof ((uintptr_t)(x)))
242 #define ASSERT0PF(x, str, ...) ASSERT0P(x)
243 #define ASSERT0F(x, str, ...) ASSERT0(x)
244 #define ASSERT(x) ((void) sizeof ((uintptr_t)(x)))
245 #define ASSERTF(x, str, ...) ASSERT(x)
246 #define assert(x) ((void) sizeof ((uintptr_t)(x)))
247 #define IMPLY(A, B) \
248 ((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B)))
249 #define EQUIV(A, B) \
250 ((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B)))
251 #else
252 #define ASSERT3B VERIFY3B
253 #define ASSERT3S VERIFY3S
254 #define ASSERT3U VERIFY3U
255 #define ASSERT3P VERIFY3P
256 #define ASSERT0 VERIFY0
257 #define ASSERT0P VERIFY0P
258 #define ASSERT3BF VERIFY3BF
259 #define ASSERT3SF VERIFY3SF
260 #define ASSERT3UF VERIFY3UF
261 #define ASSERT3PF VERIFY3PF
262 #define ASSERT0PF VERIFY0PF
263 #define ASSERT0F VERIFY0F
264 #define ASSERT VERIFY
265 #define ASSERTF VERIFYF
266 #define assert VERIFY
267 #define IMPLY(A, B) \
268 ((void)(((!(A)) || (B)) || \
269 libspl_assert("(" #A ") implies (" #B ")", \
270 __FILE__, __FUNCTION__, __LINE__)))
271 #define EQUIV(A, B) VERIFY3B(A, ==, B)
272
273 #endif /* NDEBUG */
274
275 #endif /* _LIBSPL_ASSERT_H */
276