xref: /aosp_15_r20/external/elfutils/lib/system.h (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1 /* Declarations for common convenience functions.
2    Copyright (C) 2006-2011 Red Hat, Inc.
3    Copyright (C) 2022 Mark J. Wielaard <[email protected]>
4    Copyright (C) 2023 Khem Raj.
5    This file is part of elfutils.
6 
7    This file is free software; you can redistribute it and/or modify
8    it under the terms of either
9 
10      * the GNU Lesser General Public License as published by the Free
11        Software Foundation; either version 3 of the License, or (at
12        your option) any later version
13 
14    or
15 
16      * the GNU General Public License as published by the Free
17        Software Foundation; either version 2 of the License, or (at
18        your option) any later version
19 
20    or both in parallel, as here.
21 
22    elfutils is distributed in the hope that it will be useful, but
23    WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25    General Public License for more details.
26 
27    You should have received copies of the GNU General Public License and
28    the GNU Lesser General Public License along with this program.  If
29    not, see <http://www.gnu.org/licenses/>.  */
30 
31 #ifndef LIB_SYSTEM_H
32 #define LIB_SYSTEM_H	1
33 
34 #include <config.h>
35 
36 #include <errno.h>
37 #include <stddef.h>
38 #include <stdint.h>
39 #include <string.h>
40 #include <stdarg.h>
41 #include <stdlib.h>
42 
43 /* System dependent headers */
44 #include <byteswap.h>
45 #include <endian.h>
46 #include <sys/mman.h>
47 #include <sys/param.h>
48 #include <unistd.h>
49 
50 #if defined(HAVE_ERROR_H)
51 #include <error.h>
52 #elif defined(HAVE_ERR_H)
53 extern int error_message_count;
54 void error(int status, int errnum, const char *format, ...);
55 #else
56 #error "err.h or error.h must be available"
57 #endif
58 
59 /* error (EXIT_FAILURE, ...) should be noreturn but on some systems it
60    isn't.  This may cause warnings about code that should not be reachable.
61    So have an explicit error_exit wrapper that is noreturn (because it
62    calls exit explicitly).  */
63 #define error_exit(errnum,...) do { \
64     error (EXIT_FAILURE,errnum,__VA_ARGS__); \
65     exit (EXIT_FAILURE); \
66   } while (0)
67 
68 #if BYTE_ORDER == LITTLE_ENDIAN
69 # define LE32(n)	(n)
70 # define LE64(n)	(n)
71 # define BE32(n)	bswap_32 (n)
72 # define BE64(n)	bswap_64 (n)
73 #elif BYTE_ORDER == BIG_ENDIAN
74 # define BE32(n)	(n)
75 # define BE64(n)	(n)
76 # define LE32(n)	bswap_32 (n)
77 # define LE64(n)	bswap_64 (n)
78 #else
79 # error "Unknown byte order"
80 #endif
81 
82 #ifndef MAX
83 #define MAX(m, n) ((m) < (n) ? (n) : (m))
84 #endif
85 
86 #ifndef MIN
87 #define MIN(m, n) ((m) < (n) ? (m) : (n))
88 #endif
89 
90 #if !HAVE_DECL_POWEROF2
91 #define powerof2(x) (((x) & ((x) - 1)) == 0)
92 #endif
93 
94 #if !HAVE_DECL_MEMPCPY
95 #define mempcpy(dest, src, n) \
96     ((void *) ((char *) memcpy (dest, src, n) + (size_t) n))
97 #endif
98 
99 #if !HAVE_DECL_REALLOCARRAY
100 static inline void *
reallocarray(void * ptr,size_t nmemb,size_t size)101 reallocarray (void *ptr, size_t nmemb, size_t size)
102 {
103   if (size > 0 && nmemb > SIZE_MAX / size)
104     {
105       errno = ENOMEM;
106       return NULL;
107     }
108   return realloc (ptr, nmemb * size);
109 }
110 #endif
111 
112 /* Return TRUE if the start of STR matches PREFIX, FALSE otherwise.  */
113 
114 static inline int
startswith(const char * str,const char * prefix)115 startswith (const char *str, const char *prefix)
116 {
117   return strncmp (str, prefix, strlen (prefix)) == 0;
118 }
119 
120 /* A special gettext function we use if the strings are too short.  */
121 #define sgettext(Str) \
122   ({ const char *__res = strrchr (_(Str), '|');			      \
123      __res ? __res + 1 : Str; })
124 
125 #define gettext_noop(Str) Str
126 
127 #ifndef TEMP_FAILURE_RETRY
128 #define TEMP_FAILURE_RETRY(expression) \
129   ({ ssize_t __res; \
130      do \
131        __res = expression; \
132      while (__res == -1 && errno == EINTR); \
133      __res; })
134 #endif
135 
136 #ifndef ACCESSPERMS
137 #define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO) /* 0777 */
138 #endif
139 
140 #ifndef ALLPERMS
141 #define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) /* 07777 */
142 #endif
143 
144 #ifndef DEFFILEMODE
145 #define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)/* 0666 */
146 #endif
147 
148 static inline ssize_t __attribute__ ((unused))
pwrite_retry(int fd,const void * buf,size_t len,off_t off)149 pwrite_retry (int fd, const void *buf, size_t len, off_t off)
150 {
151   ssize_t recvd = 0;
152 
153   do
154     {
155       ssize_t ret = TEMP_FAILURE_RETRY (pwrite (fd, ((char *)buf) + recvd, len - recvd,
156 						off + recvd));
157       if (ret <= 0)
158 	return ret < 0 ? ret : recvd;
159 
160       recvd += ret;
161     }
162   while ((size_t) recvd < len);
163 
164   return recvd;
165 }
166 
167 static inline ssize_t __attribute__ ((unused))
write_retry(int fd,const void * buf,size_t len)168 write_retry (int fd, const void *buf, size_t len)
169 {
170   ssize_t recvd = 0;
171 
172   do
173     {
174       ssize_t ret = TEMP_FAILURE_RETRY (write (fd, ((char *)buf) + recvd, len - recvd));
175       if (ret <= 0)
176 	return ret < 0 ? ret : recvd;
177 
178       recvd += ret;
179     }
180   while ((size_t) recvd < len);
181 
182   return recvd;
183 }
184 
185 static inline ssize_t __attribute__ ((unused))
pread_retry(int fd,void * buf,size_t len,off_t off)186 pread_retry (int fd, void *buf, size_t len, off_t off)
187 {
188   ssize_t recvd = 0;
189 
190   do
191     {
192       ssize_t ret = TEMP_FAILURE_RETRY (pread (fd, ((char *)buf) + recvd, len - recvd,
193 					       off + recvd));
194       if (ret <= 0)
195 	return ret < 0 ? ret : recvd;
196 
197       recvd += ret;
198     }
199   while ((size_t) recvd < len);
200 
201   return recvd;
202 }
203 
204 /* The demangler from libstdc++.  */
205 extern char *__cxa_demangle (const char *mangled_name, char *output_buffer,
206 			     size_t *length, int *status);
207 
208 /* A static assertion.  This will cause a compile-time error if EXPR,
209    which must be a compile-time constant, is false.  */
210 
211 #define eu_static_assert(expr)						\
212   extern int never_defined_just_used_for_checking[(expr) ? 1 : -1]	\
213     __attribute__ ((unused))
214 
215 /* We really want a basename implementation that doesn't modify the
216    input argument.  Normally you get that from string.h with _GNU_SOURCE
217    define.  But some libc implementations don't define it and other
218    define it, but provide an implementation that still modifies the
219    argument.  So define our own and poison a bare basename symbol.  */
220 static inline const char *
xbasename(const char * s)221 xbasename(const char *s)
222 {
223   const char *p = strrchr(s, '/');
224   return p ? p+1 : s;
225 }
226 #pragma GCC poison basename
227 
228 #endif /* system.h */
229