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