1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2017 Jason King
14  * Copyright 2019 Joyent, Inc.
15  */
16 #ifndef _DEMANGLE_INT_H
17 #define	_DEMANGLE_INT_H
18 
19 #include <inttypes.h>
20 #include <stdio.h>
21 #include <sys/byteorder.h>
22 #include <sys/ctype.h> /* Use ASCII ISXXXX() macros */
23 #include <sys/debug.h>
24 #include <sys/sysmacros.h>
25 #include <sys/isa_defs.h>
26 #include "demangle-sys.h"
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 #ifdef __CHECKER__
33 /*
34  * smatch seems to have a bug which chokes on the builtins, so
35  * we just have it fallback to the non-builtin definitions
36  */
37 #elif __GNUC__ >= 5 && __GNUC_MINOR__ > 1
38 #define	USE_BUILTIN_OVERFLOW
39 #elif defined(__clang__)
40 #define	USE_BUILTIN_OVERFLOW
41 #endif
42 
43 #ifdef USE_BUILTIN_OVERFLOW
44 static inline boolean_t
mul_overflow(uint64_t a,uint64_t b,uint64_t * v)45 mul_overflow(uint64_t a, uint64_t b, uint64_t *v)
46 {
47 	return (__builtin_mul_overflow(a, b, v));
48 }
49 
50 static inline boolean_t
add_overflow(uint64_t a,uint64_t b,uint64_t * v)51 add_overflow(uint64_t a, uint64_t b, uint64_t *v)
52 {
53 	return (__builtin_add_overflow(a, b, v));
54 }
55 
56 static inline boolean_t
sub_overflow(uint64_t a,uint64_t b,uint64_t * v)57 sub_overflow(uint64_t a, uint64_t b, uint64_t *v)
58 {
59 	return (__builtin_sub_overflow(a, b, v));
60 }
61 #else
62 static inline boolean_t
63 mul_overflow(uint64_t a, uint64_t b, uint64_t *v)
64 {
65 	uint64_t val = a * b;
66 
67 	if (a != 0 && val / a != b)
68 		return (B_TRUE);
69 	*v = val;
70 	return (B_FALSE);
71 }
72 
73 static inline boolean_t
74 add_overflow(uint64_t a, uint64_t b, uint64_t *v)
75 {
76 	uint64_t val = a + b;
77 
78 	if (val < a || val < b)
79 		return (B_TRUE);
80 	*v = val;
81 	return (B_FALSE);
82 }
83 
84 static inline boolean_t
85 sub_overflow(uint64_t a, uint64_t b, uint64_t *v)
86 {
87 	uint64_t val = a - b;
88 
89 	if (val > a)
90 		return (B_TRUE);
91 	*v = val;
92 	return (B_FALSE);
93 }
94 #endif
95 
96 extern sysdem_ops_t *sysdem_ops_default;
97 
98 char *cpp_demangle(const char *, size_t, sysdem_ops_t *);
99 char *rust_demangle(const char *, size_t, sysdem_ops_t *);
100 
101 struct custr_alloc;
102 
103 void *zalloc(sysdem_ops_t *, size_t);
104 void *xcalloc(sysdem_ops_t *, size_t, size_t);
105 void *xrealloc(sysdem_ops_t *, void *, size_t, size_t);
106 void xfree(sysdem_ops_t *, void *, size_t);
107 char *xstrdup(sysdem_ops_t *, const char *);
108 
109 extern volatile boolean_t demangle_debug;
110 
111 /*
112  * gcc seems to get unhappy with the ASSERT() style definition (also borrowed
113  * for the DEMDEBUG macro unless demdebug() is returns a non-void value
114  * (despite the return value never being used).
115  */
116 int demdebug(const char *, ...);
117 
118 #define	DEMDEBUG(s, ...) \
119 	((void)(demangle_debug && demdebug(s, ## __VA_ARGS__)))
120 
121 #ifdef __cplusplus
122 }
123 #endif
124 
125 #endif /* _DEMANGLE_INT_H */
126