Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
0002 /*
0003  * stdlib function definitions for NOLIBC
0004  * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
0005  */
0006 
0007 #ifndef _NOLIBC_STDLIB_H
0008 #define _NOLIBC_STDLIB_H
0009 
0010 #include "std.h"
0011 #include "arch.h"
0012 #include "types.h"
0013 #include "sys.h"
0014 #include "string.h"
0015 
0016 struct nolibc_heap {
0017     size_t  len;
0018     char    user_p[] __attribute__((__aligned__));
0019 };
0020 
0021 /* Buffer used to store int-to-ASCII conversions. Will only be implemented if
0022  * any of the related functions is implemented. The area is large enough to
0023  * store "18446744073709551615" or "-9223372036854775808" and the final zero.
0024  */
0025 static __attribute__((unused)) char itoa_buffer[21];
0026 
0027 /*
0028  * As much as possible, please keep functions alphabetically sorted.
0029  */
0030 
0031 /* must be exported, as it's used by libgcc for various divide functions */
0032 __attribute__((weak,unused,noreturn,section(".text.nolibc_abort")))
0033 void abort(void)
0034 {
0035     sys_kill(sys_getpid(), SIGABRT);
0036     for (;;);
0037 }
0038 
0039 static __attribute__((unused))
0040 long atol(const char *s)
0041 {
0042     unsigned long ret = 0;
0043     unsigned long d;
0044     int neg = 0;
0045 
0046     if (*s == '-') {
0047         neg = 1;
0048         s++;
0049     }
0050 
0051     while (1) {
0052         d = (*s++) - '0';
0053         if (d > 9)
0054             break;
0055         ret *= 10;
0056         ret += d;
0057     }
0058 
0059     return neg ? -ret : ret;
0060 }
0061 
0062 static __attribute__((unused))
0063 int atoi(const char *s)
0064 {
0065     return atol(s);
0066 }
0067 
0068 static __attribute__((unused))
0069 void free(void *ptr)
0070 {
0071     struct nolibc_heap *heap;
0072 
0073     if (!ptr)
0074         return;
0075 
0076     heap = container_of(ptr, struct nolibc_heap, user_p);
0077     munmap(heap, heap->len);
0078 }
0079 
0080 /* getenv() tries to find the environment variable named <name> in the
0081  * environment array pointed to by global variable "environ" which must be
0082  * declared as a char **, and must be terminated by a NULL (it is recommended
0083  * to set this variable to the "envp" argument of main()). If the requested
0084  * environment variable exists its value is returned otherwise NULL is
0085  * returned. getenv() is forcefully inlined so that the reference to "environ"
0086  * will be dropped if unused, even at -O0.
0087  */
0088 static __attribute__((unused))
0089 char *_getenv(const char *name, char **environ)
0090 {
0091     int idx, i;
0092 
0093     if (environ) {
0094         for (idx = 0; environ[idx]; idx++) {
0095             for (i = 0; name[i] && name[i] == environ[idx][i];)
0096                 i++;
0097             if (!name[i] && environ[idx][i] == '=')
0098                 return &environ[idx][i+1];
0099         }
0100     }
0101     return NULL;
0102 }
0103 
0104 static inline __attribute__((unused,always_inline))
0105 char *getenv(const char *name)
0106 {
0107     extern char **environ;
0108     return _getenv(name, environ);
0109 }
0110 
0111 static __attribute__((unused))
0112 void *malloc(size_t len)
0113 {
0114     struct nolibc_heap *heap;
0115 
0116     /* Always allocate memory with size multiple of 4096. */
0117     len  = sizeof(*heap) + len;
0118     len  = (len + 4095UL) & -4096UL;
0119     heap = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,
0120             -1, 0);
0121     if (__builtin_expect(heap == MAP_FAILED, 0))
0122         return NULL;
0123 
0124     heap->len = len;
0125     return heap->user_p;
0126 }
0127 
0128 static __attribute__((unused))
0129 void *calloc(size_t size, size_t nmemb)
0130 {
0131     size_t x = size * nmemb;
0132 
0133     if (__builtin_expect(size && ((x / size) != nmemb), 0)) {
0134         SET_ERRNO(ENOMEM);
0135         return NULL;
0136     }
0137 
0138     /*
0139      * No need to zero the heap, the MAP_ANONYMOUS in malloc()
0140      * already does it.
0141      */
0142     return malloc(x);
0143 }
0144 
0145 static __attribute__((unused))
0146 void *realloc(void *old_ptr, size_t new_size)
0147 {
0148     struct nolibc_heap *heap;
0149     size_t user_p_len;
0150     void *ret;
0151 
0152     if (!old_ptr)
0153         return malloc(new_size);
0154 
0155     heap = container_of(old_ptr, struct nolibc_heap, user_p);
0156     user_p_len = heap->len - sizeof(*heap);
0157     /*
0158      * Don't realloc() if @user_p_len >= @new_size, this block of
0159      * memory is still enough to handle the @new_size. Just return
0160      * the same pointer.
0161      */
0162     if (user_p_len >= new_size)
0163         return old_ptr;
0164 
0165     ret = malloc(new_size);
0166     if (__builtin_expect(!ret, 0))
0167         return NULL;
0168 
0169     memcpy(ret, heap->user_p, heap->len);
0170     munmap(heap, heap->len);
0171     return ret;
0172 }
0173 
0174 /* Converts the unsigned long integer <in> to its hex representation into
0175  * buffer <buffer>, which must be long enough to store the number and the
0176  * trailing zero (17 bytes for "ffffffffffffffff" or 9 for "ffffffff"). The
0177  * buffer is filled from the first byte, and the number of characters emitted
0178  * (not counting the trailing zero) is returned. The function is constructed
0179  * in a way to optimize the code size and avoid any divide that could add a
0180  * dependency on large external functions.
0181  */
0182 static __attribute__((unused))
0183 int utoh_r(unsigned long in, char *buffer)
0184 {
0185     signed char pos = (~0UL > 0xfffffffful) ? 60 : 28;
0186     int digits = 0;
0187     int dig;
0188 
0189     do {
0190         dig = in >> pos;
0191         in -= (uint64_t)dig << pos;
0192         pos -= 4;
0193         if (dig || digits || pos < 0) {
0194             if (dig > 9)
0195                 dig += 'a' - '0' - 10;
0196             buffer[digits++] = '0' + dig;
0197         }
0198     } while (pos >= 0);
0199 
0200     buffer[digits] = 0;
0201     return digits;
0202 }
0203 
0204 /* converts unsigned long <in> to an hex string using the static itoa_buffer
0205  * and returns the pointer to that string.
0206  */
0207 static inline __attribute__((unused))
0208 char *utoh(unsigned long in)
0209 {
0210     utoh_r(in, itoa_buffer);
0211     return itoa_buffer;
0212 }
0213 
0214 /* Converts the unsigned long integer <in> to its string representation into
0215  * buffer <buffer>, which must be long enough to store the number and the
0216  * trailing zero (21 bytes for 18446744073709551615 in 64-bit, 11 for
0217  * 4294967295 in 32-bit). The buffer is filled from the first byte, and the
0218  * number of characters emitted (not counting the trailing zero) is returned.
0219  * The function is constructed in a way to optimize the code size and avoid
0220  * any divide that could add a dependency on large external functions.
0221  */
0222 static __attribute__((unused))
0223 int utoa_r(unsigned long in, char *buffer)
0224 {
0225     unsigned long lim;
0226     int digits = 0;
0227     int pos = (~0UL > 0xfffffffful) ? 19 : 9;
0228     int dig;
0229 
0230     do {
0231         for (dig = 0, lim = 1; dig < pos; dig++)
0232             lim *= 10;
0233 
0234         if (digits || in >= lim || !pos) {
0235             for (dig = 0; in >= lim; dig++)
0236                 in -= lim;
0237             buffer[digits++] = '0' + dig;
0238         }
0239     } while (pos--);
0240 
0241     buffer[digits] = 0;
0242     return digits;
0243 }
0244 
0245 /* Converts the signed long integer <in> to its string representation into
0246  * buffer <buffer>, which must be long enough to store the number and the
0247  * trailing zero (21 bytes for -9223372036854775808 in 64-bit, 12 for
0248  * -2147483648 in 32-bit). The buffer is filled from the first byte, and the
0249  * number of characters emitted (not counting the trailing zero) is returned.
0250  */
0251 static __attribute__((unused))
0252 int itoa_r(long in, char *buffer)
0253 {
0254     char *ptr = buffer;
0255     int len = 0;
0256 
0257     if (in < 0) {
0258         in = -in;
0259         *(ptr++) = '-';
0260         len++;
0261     }
0262     len += utoa_r(in, ptr);
0263     return len;
0264 }
0265 
0266 /* for historical compatibility, same as above but returns the pointer to the
0267  * buffer.
0268  */
0269 static inline __attribute__((unused))
0270 char *ltoa_r(long in, char *buffer)
0271 {
0272     itoa_r(in, buffer);
0273     return buffer;
0274 }
0275 
0276 /* converts long integer <in> to a string using the static itoa_buffer and
0277  * returns the pointer to that string.
0278  */
0279 static inline __attribute__((unused))
0280 char *itoa(long in)
0281 {
0282     itoa_r(in, itoa_buffer);
0283     return itoa_buffer;
0284 }
0285 
0286 /* converts long integer <in> to a string using the static itoa_buffer and
0287  * returns the pointer to that string. Same as above, for compatibility.
0288  */
0289 static inline __attribute__((unused))
0290 char *ltoa(long in)
0291 {
0292     itoa_r(in, itoa_buffer);
0293     return itoa_buffer;
0294 }
0295 
0296 /* converts unsigned long integer <in> to a string using the static itoa_buffer
0297  * and returns the pointer to that string.
0298  */
0299 static inline __attribute__((unused))
0300 char *utoa(unsigned long in)
0301 {
0302     utoa_r(in, itoa_buffer);
0303     return itoa_buffer;
0304 }
0305 
0306 /* Converts the unsigned 64-bit integer <in> to its hex representation into
0307  * buffer <buffer>, which must be long enough to store the number and the
0308  * trailing zero (17 bytes for "ffffffffffffffff"). The buffer is filled from
0309  * the first byte, and the number of characters emitted (not counting the
0310  * trailing zero) is returned. The function is constructed in a way to optimize
0311  * the code size and avoid any divide that could add a dependency on large
0312  * external functions.
0313  */
0314 static __attribute__((unused))
0315 int u64toh_r(uint64_t in, char *buffer)
0316 {
0317     signed char pos = 60;
0318     int digits = 0;
0319     int dig;
0320 
0321     do {
0322         if (sizeof(long) >= 8) {
0323             dig = (in >> pos) & 0xF;
0324         } else {
0325             /* 32-bit platforms: avoid a 64-bit shift */
0326             uint32_t d = (pos >= 32) ? (in >> 32) : in;
0327             dig = (d >> (pos & 31)) & 0xF;
0328         }
0329         if (dig > 9)
0330             dig += 'a' - '0' - 10;
0331         pos -= 4;
0332         if (dig || digits || pos < 0)
0333             buffer[digits++] = '0' + dig;
0334     } while (pos >= 0);
0335 
0336     buffer[digits] = 0;
0337     return digits;
0338 }
0339 
0340 /* converts uint64_t <in> to an hex string using the static itoa_buffer and
0341  * returns the pointer to that string.
0342  */
0343 static inline __attribute__((unused))
0344 char *u64toh(uint64_t in)
0345 {
0346     u64toh_r(in, itoa_buffer);
0347     return itoa_buffer;
0348 }
0349 
0350 /* Converts the unsigned 64-bit integer <in> to its string representation into
0351  * buffer <buffer>, which must be long enough to store the number and the
0352  * trailing zero (21 bytes for 18446744073709551615). The buffer is filled from
0353  * the first byte, and the number of characters emitted (not counting the
0354  * trailing zero) is returned. The function is constructed in a way to optimize
0355  * the code size and avoid any divide that could add a dependency on large
0356  * external functions.
0357  */
0358 static __attribute__((unused))
0359 int u64toa_r(uint64_t in, char *buffer)
0360 {
0361     unsigned long long lim;
0362     int digits = 0;
0363     int pos = 19; /* start with the highest possible digit */
0364     int dig;
0365 
0366     do {
0367         for (dig = 0, lim = 1; dig < pos; dig++)
0368             lim *= 10;
0369 
0370         if (digits || in >= lim || !pos) {
0371             for (dig = 0; in >= lim; dig++)
0372                 in -= lim;
0373             buffer[digits++] = '0' + dig;
0374         }
0375     } while (pos--);
0376 
0377     buffer[digits] = 0;
0378     return digits;
0379 }
0380 
0381 /* Converts the signed 64-bit integer <in> to its string representation into
0382  * buffer <buffer>, which must be long enough to store the number and the
0383  * trailing zero (21 bytes for -9223372036854775808). The buffer is filled from
0384  * the first byte, and the number of characters emitted (not counting the
0385  * trailing zero) is returned.
0386  */
0387 static __attribute__((unused))
0388 int i64toa_r(int64_t in, char *buffer)
0389 {
0390     char *ptr = buffer;
0391     int len = 0;
0392 
0393     if (in < 0) {
0394         in = -in;
0395         *(ptr++) = '-';
0396         len++;
0397     }
0398     len += u64toa_r(in, ptr);
0399     return len;
0400 }
0401 
0402 /* converts int64_t <in> to a string using the static itoa_buffer and returns
0403  * the pointer to that string.
0404  */
0405 static inline __attribute__((unused))
0406 char *i64toa(int64_t in)
0407 {
0408     i64toa_r(in, itoa_buffer);
0409     return itoa_buffer;
0410 }
0411 
0412 /* converts uint64_t <in> to a string using the static itoa_buffer and returns
0413  * the pointer to that string.
0414  */
0415 static inline __attribute__((unused))
0416 char *u64toa(uint64_t in)
0417 {
0418     u64toa_r(in, itoa_buffer);
0419     return itoa_buffer;
0420 }
0421 
0422 #endif /* _NOLIBC_STDLIB_H */