1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2 /*
3 * stdlib function definitions for NOLIBC
4 * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
5 */
6
7 #ifndef _NOLIBC_STDLIB_H
8 #define _NOLIBC_STDLIB_H
9
10 #include "std.h"
11 #include "arch.h"
12 #include "types.h"
13 #include "sys.h"
14 #include "string.h"
15 #include <linux/auxvec.h>
16
17 struct nolibc_heap {
18 size_t len;
19 char user_p[] __attribute__((__aligned__));
20 };
21
22 /* Buffer used to store int-to-ASCII conversions. Will only be implemented if
23 * any of the related functions is implemented. The area is large enough to
24 * store "18446744073709551615" or "-9223372036854775808" and the final zero.
25 */
26 static __attribute__((unused)) char itoa_buffer[21];
27
28 /*
29 * As much as possible, please keep functions alphabetically sorted.
30 */
31
32 /* must be exported, as it's used by libgcc for various divide functions */
33 void abort(void);
34 __attribute__((weak,unused,noreturn,section(".text.nolibc_abort")))
abort(void)35 void abort(void)
36 {
37 sys_kill(sys_getpid(), SIGABRT);
38 for (;;);
39 }
40
41 static __attribute__((unused))
atol(const char * s)42 long atol(const char *s)
43 {
44 unsigned long ret = 0;
45 unsigned long d;
46 int neg = 0;
47
48 if (*s == '-') {
49 neg = 1;
50 s++;
51 }
52
53 while (1) {
54 d = (*s++) - '0';
55 if (d > 9)
56 break;
57 ret *= 10;
58 ret += d;
59 }
60
61 return neg ? -ret : ret;
62 }
63
64 static __attribute__((unused))
atoi(const char * s)65 int atoi(const char *s)
66 {
67 return atol(s);
68 }
69
70 static __attribute__((unused))
free(void * ptr)71 void free(void *ptr)
72 {
73 struct nolibc_heap *heap;
74
75 if (!ptr)
76 return;
77
78 heap = container_of(ptr, struct nolibc_heap, user_p);
79 munmap(heap, heap->len);
80 }
81
82 /* getenv() tries to find the environment variable named <name> in the
83 * environment array pointed to by global variable "environ" which must be
84 * declared as a char **, and must be terminated by a NULL (it is recommended
85 * to set this variable to the "envp" argument of main()). If the requested
86 * environment variable exists its value is returned otherwise NULL is
87 * returned.
88 */
89 static __attribute__((unused))
getenv(const char * name)90 char *getenv(const char *name)
91 {
92 int idx, i;
93
94 if (environ) {
95 for (idx = 0; environ[idx]; idx++) {
96 for (i = 0; name[i] && name[i] == environ[idx][i];)
97 i++;
98 if (!name[i] && environ[idx][i] == '=')
99 return &environ[idx][i+1];
100 }
101 }
102 return NULL;
103 }
104
105 static __attribute__((unused))
getauxval(unsigned long type)106 unsigned long getauxval(unsigned long type)
107 {
108 const unsigned long *auxv = _auxv;
109 unsigned long ret;
110
111 if (!auxv)
112 return 0;
113
114 while (1) {
115 if (!auxv[0] && !auxv[1]) {
116 ret = 0;
117 break;
118 }
119
120 if (auxv[0] == type) {
121 ret = auxv[1];
122 break;
123 }
124
125 auxv += 2;
126 }
127
128 return ret;
129 }
130
131 static __attribute__((unused))
malloc(size_t len)132 void *malloc(size_t len)
133 {
134 struct nolibc_heap *heap;
135
136 /* Always allocate memory with size multiple of 4096. */
137 len = sizeof(*heap) + len;
138 len = (len + 4095UL) & -4096UL;
139 heap = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,
140 -1, 0);
141 if (__builtin_expect(heap == MAP_FAILED, 0))
142 return NULL;
143
144 heap->len = len;
145 return heap->user_p;
146 }
147
148 static __attribute__((unused))
calloc(size_t size,size_t nmemb)149 void *calloc(size_t size, size_t nmemb)
150 {
151 size_t x = size * nmemb;
152
153 if (__builtin_expect(size && ((x / size) != nmemb), 0)) {
154 SET_ERRNO(ENOMEM);
155 return NULL;
156 }
157
158 /*
159 * No need to zero the heap, the MAP_ANONYMOUS in malloc()
160 * already does it.
161 */
162 return malloc(x);
163 }
164
165 static __attribute__((unused))
realloc(void * old_ptr,size_t new_size)166 void *realloc(void *old_ptr, size_t new_size)
167 {
168 struct nolibc_heap *heap;
169 size_t user_p_len;
170 void *ret;
171
172 if (!old_ptr)
173 return malloc(new_size);
174
175 heap = container_of(old_ptr, struct nolibc_heap, user_p);
176 user_p_len = heap->len - sizeof(*heap);
177 /*
178 * Don't realloc() if @user_p_len >= @new_size, this block of
179 * memory is still enough to handle the @new_size. Just return
180 * the same pointer.
181 */
182 if (user_p_len >= new_size)
183 return old_ptr;
184
185 ret = malloc(new_size);
186 if (__builtin_expect(!ret, 0))
187 return NULL;
188
189 memcpy(ret, heap->user_p, user_p_len);
190 munmap(heap, heap->len);
191 return ret;
192 }
193
194 /* Converts the unsigned long integer <in> to its hex representation into
195 * buffer <buffer>, which must be long enough to store the number and the
196 * trailing zero (17 bytes for "ffffffffffffffff" or 9 for "ffffffff"). The
197 * buffer is filled from the first byte, and the number of characters emitted
198 * (not counting the trailing zero) is returned. The function is constructed
199 * in a way to optimize the code size and avoid any divide that could add a
200 * dependency on large external functions.
201 */
202 static __attribute__((unused))
utoh_r(unsigned long in,char * buffer)203 int utoh_r(unsigned long in, char *buffer)
204 {
205 signed char pos = (~0UL > 0xfffffffful) ? 60 : 28;
206 int digits = 0;
207 int dig;
208
209 do {
210 dig = in >> pos;
211 in -= (uint64_t)dig << pos;
212 pos -= 4;
213 if (dig || digits || pos < 0) {
214 if (dig > 9)
215 dig += 'a' - '0' - 10;
216 buffer[digits++] = '0' + dig;
217 }
218 } while (pos >= 0);
219
220 buffer[digits] = 0;
221 return digits;
222 }
223
224 /* converts unsigned long <in> to an hex string using the static itoa_buffer
225 * and returns the pointer to that string.
226 */
227 static __inline__ __attribute__((unused))
utoh(unsigned long in)228 char *utoh(unsigned long in)
229 {
230 utoh_r(in, itoa_buffer);
231 return itoa_buffer;
232 }
233
234 /* Converts the unsigned long integer <in> to its string representation into
235 * buffer <buffer>, which must be long enough to store the number and the
236 * trailing zero (21 bytes for 18446744073709551615 in 64-bit, 11 for
237 * 4294967295 in 32-bit). The buffer is filled from the first byte, and the
238 * number of characters emitted (not counting the trailing zero) is returned.
239 * The function is constructed in a way to optimize the code size and avoid
240 * any divide that could add a dependency on large external functions.
241 */
242 static __attribute__((unused))
utoa_r(unsigned long in,char * buffer)243 int utoa_r(unsigned long in, char *buffer)
244 {
245 unsigned long lim;
246 int digits = 0;
247 int pos = (~0UL > 0xfffffffful) ? 19 : 9;
248 int dig;
249
250 do {
251 for (dig = 0, lim = 1; dig < pos; dig++)
252 lim *= 10;
253
254 if (digits || in >= lim || !pos) {
255 for (dig = 0; in >= lim; dig++)
256 in -= lim;
257 buffer[digits++] = '0' + dig;
258 }
259 } while (pos--);
260
261 buffer[digits] = 0;
262 return digits;
263 }
264
265 /* Converts the signed long integer <in> to its string representation into
266 * buffer <buffer>, which must be long enough to store the number and the
267 * trailing zero (21 bytes for -9223372036854775808 in 64-bit, 12 for
268 * -2147483648 in 32-bit). The buffer is filled from the first byte, and the
269 * number of characters emitted (not counting the trailing zero) is returned.
270 */
271 static __attribute__((unused))
itoa_r(long in,char * buffer)272 int itoa_r(long in, char *buffer)
273 {
274 char *ptr = buffer;
275 int len = 0;
276
277 if (in < 0) {
278 in = -in;
279 *(ptr++) = '-';
280 len++;
281 }
282 len += utoa_r(in, ptr);
283 return len;
284 }
285
286 /* for historical compatibility, same as above but returns the pointer to the
287 * buffer.
288 */
289 static __inline__ __attribute__((unused))
ltoa_r(long in,char * buffer)290 char *ltoa_r(long in, char *buffer)
291 {
292 itoa_r(in, buffer);
293 return buffer;
294 }
295
296 /* converts long integer <in> to a string using the static itoa_buffer and
297 * returns the pointer to that string.
298 */
299 static __inline__ __attribute__((unused))
itoa(long in)300 char *itoa(long in)
301 {
302 itoa_r(in, itoa_buffer);
303 return itoa_buffer;
304 }
305
306 /* converts long integer <in> to a string using the static itoa_buffer and
307 * returns the pointer to that string. Same as above, for compatibility.
308 */
309 static __inline__ __attribute__((unused))
ltoa(long in)310 char *ltoa(long in)
311 {
312 itoa_r(in, itoa_buffer);
313 return itoa_buffer;
314 }
315
316 /* converts unsigned long integer <in> to a string using the static itoa_buffer
317 * and returns the pointer to that string.
318 */
319 static __inline__ __attribute__((unused))
utoa(unsigned long in)320 char *utoa(unsigned long in)
321 {
322 utoa_r(in, itoa_buffer);
323 return itoa_buffer;
324 }
325
326 /* Converts the unsigned 64-bit integer <in> to its hex representation into
327 * buffer <buffer>, which must be long enough to store the number and the
328 * trailing zero (17 bytes for "ffffffffffffffff"). The buffer is filled from
329 * the first byte, and the number of characters emitted (not counting the
330 * trailing zero) is returned. The function is constructed in a way to optimize
331 * the code size and avoid any divide that could add a dependency on large
332 * external functions.
333 */
334 static __attribute__((unused))
u64toh_r(uint64_t in,char * buffer)335 int u64toh_r(uint64_t in, char *buffer)
336 {
337 signed char pos = 60;
338 int digits = 0;
339 int dig;
340
341 do {
342 if (sizeof(long) >= 8) {
343 dig = (in >> pos) & 0xF;
344 } else {
345 /* 32-bit platforms: avoid a 64-bit shift */
346 uint32_t d = (pos >= 32) ? (in >> 32) : in;
347 dig = (d >> (pos & 31)) & 0xF;
348 }
349 if (dig > 9)
350 dig += 'a' - '0' - 10;
351 pos -= 4;
352 if (dig || digits || pos < 0)
353 buffer[digits++] = '0' + dig;
354 } while (pos >= 0);
355
356 buffer[digits] = 0;
357 return digits;
358 }
359
360 /* converts uint64_t <in> to an hex string using the static itoa_buffer and
361 * returns the pointer to that string.
362 */
363 static __inline__ __attribute__((unused))
u64toh(uint64_t in)364 char *u64toh(uint64_t in)
365 {
366 u64toh_r(in, itoa_buffer);
367 return itoa_buffer;
368 }
369
370 /* Converts the unsigned 64-bit integer <in> to its string representation into
371 * buffer <buffer>, which must be long enough to store the number and the
372 * trailing zero (21 bytes for 18446744073709551615). The buffer is filled from
373 * the first byte, and the number of characters emitted (not counting the
374 * trailing zero) is returned. The function is constructed in a way to optimize
375 * the code size and avoid any divide that could add a dependency on large
376 * external functions.
377 */
378 static __attribute__((unused))
u64toa_r(uint64_t in,char * buffer)379 int u64toa_r(uint64_t in, char *buffer)
380 {
381 unsigned long long lim;
382 int digits = 0;
383 int pos = 19; /* start with the highest possible digit */
384 int dig;
385
386 do {
387 for (dig = 0, lim = 1; dig < pos; dig++)
388 lim *= 10;
389
390 if (digits || in >= lim || !pos) {
391 for (dig = 0; in >= lim; dig++)
392 in -= lim;
393 buffer[digits++] = '0' + dig;
394 }
395 } while (pos--);
396
397 buffer[digits] = 0;
398 return digits;
399 }
400
401 /* Converts the signed 64-bit integer <in> to its string representation into
402 * buffer <buffer>, which must be long enough to store the number and the
403 * trailing zero (21 bytes for -9223372036854775808). The buffer is filled from
404 * the first byte, and the number of characters emitted (not counting the
405 * trailing zero) is returned.
406 */
407 static __attribute__((unused))
i64toa_r(int64_t in,char * buffer)408 int i64toa_r(int64_t in, char *buffer)
409 {
410 char *ptr = buffer;
411 int len = 0;
412
413 if (in < 0) {
414 in = -in;
415 *(ptr++) = '-';
416 len++;
417 }
418 len += u64toa_r(in, ptr);
419 return len;
420 }
421
422 /* converts int64_t <in> to a string using the static itoa_buffer and returns
423 * the pointer to that string.
424 */
425 static __inline__ __attribute__((unused))
i64toa(int64_t in)426 char *i64toa(int64_t in)
427 {
428 i64toa_r(in, itoa_buffer);
429 return itoa_buffer;
430 }
431
432 /* converts uint64_t <in> to a string using the static itoa_buffer and returns
433 * the pointer to that string.
434 */
435 static __inline__ __attribute__((unused))
u64toa(uint64_t in)436 char *u64toa(uint64_t in)
437 {
438 u64toa_r(in, itoa_buffer);
439 return itoa_buffer;
440 }
441
442 static __attribute__((unused))
__strtox(const char * nptr,char ** endptr,int base,intmax_t lower_limit,uintmax_t upper_limit)443 uintmax_t __strtox(const char *nptr, char **endptr, int base, intmax_t lower_limit, uintmax_t upper_limit)
444 {
445 const char signed_ = lower_limit != 0;
446 unsigned char neg = 0, overflow = 0;
447 uintmax_t val = 0, limit, old_val;
448 char c;
449
450 if (base < 0 || base > 36) {
451 SET_ERRNO(EINVAL);
452 goto out;
453 }
454
455 while (isspace(*nptr))
456 nptr++;
457
458 if (*nptr == '+') {
459 nptr++;
460 } else if (*nptr == '-') {
461 neg = 1;
462 nptr++;
463 }
464
465 if (signed_ && neg)
466 limit = -(uintmax_t)lower_limit;
467 else
468 limit = upper_limit;
469
470 if ((base == 0 || base == 16) &&
471 (strncmp(nptr, "0x", 2) == 0 || strncmp(nptr, "0X", 2) == 0)) {
472 base = 16;
473 nptr += 2;
474 } else if (base == 0 && strncmp(nptr, "0", 1) == 0) {
475 base = 8;
476 nptr += 1;
477 } else if (base == 0) {
478 base = 10;
479 }
480
481 while (*nptr) {
482 c = *nptr;
483
484 if (c >= '0' && c <= '9')
485 c -= '0';
486 else if (c >= 'a' && c <= 'z')
487 c = c - 'a' + 10;
488 else if (c >= 'A' && c <= 'Z')
489 c = c - 'A' + 10;
490 else
491 goto out;
492
493 if (c >= base)
494 goto out;
495
496 nptr++;
497 old_val = val;
498 val *= base;
499 val += c;
500
501 if (val > limit || val < old_val)
502 overflow = 1;
503 }
504
505 out:
506 if (overflow) {
507 SET_ERRNO(ERANGE);
508 val = limit;
509 }
510 if (endptr)
511 *endptr = (char *)nptr;
512 return neg ? -val : val;
513 }
514
515 static __attribute__((unused))
strtol(const char * nptr,char ** endptr,int base)516 long strtol(const char *nptr, char **endptr, int base)
517 {
518 return __strtox(nptr, endptr, base, LONG_MIN, LONG_MAX);
519 }
520
521 static __attribute__((unused))
strtoul(const char * nptr,char ** endptr,int base)522 unsigned long strtoul(const char *nptr, char **endptr, int base)
523 {
524 return __strtox(nptr, endptr, base, 0, ULONG_MAX);
525 }
526
527 static __attribute__((unused))
strtoll(const char * nptr,char ** endptr,int base)528 long long strtoll(const char *nptr, char **endptr, int base)
529 {
530 return __strtox(nptr, endptr, base, LLONG_MIN, LLONG_MAX);
531 }
532
533 static __attribute__((unused))
strtoull(const char * nptr,char ** endptr,int base)534 unsigned long long strtoull(const char *nptr, char **endptr, int base)
535 {
536 return __strtox(nptr, endptr, base, 0, ULLONG_MAX);
537 }
538
539 static __attribute__((unused))
strtoimax(const char * nptr,char ** endptr,int base)540 intmax_t strtoimax(const char *nptr, char **endptr, int base)
541 {
542 return __strtox(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX);
543 }
544
545 static __attribute__((unused))
strtoumax(const char * nptr,char ** endptr,int base)546 uintmax_t strtoumax(const char *nptr, char **endptr, int base)
547 {
548 return __strtox(nptr, endptr, base, 0, UINTMAX_MAX);
549 }
550
551 /* make sure to include all global symbols */
552 #include "nolibc.h"
553
554 #endif /* _NOLIBC_STDLIB_H */
555