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