stdlib.h (10609B)
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 16struct nolibc_heap { 17 size_t len; 18 char user_p[] __attribute__((__aligned__)); 19}; 20 21/* Buffer used to store int-to-ASCII conversions. Will only be implemented if 22 * any of the related functions is implemented. The area is large enough to 23 * store "18446744073709551615" or "-9223372036854775808" and the final zero. 24 */ 25static __attribute__((unused)) char itoa_buffer[21]; 26 27/* 28 * As much as possible, please keep functions alphabetically sorted. 29 */ 30 31/* must be exported, as it's used by libgcc for various divide functions */ 32__attribute__((weak,unused,noreturn,section(".text.nolibc_abort"))) 33void abort(void) 34{ 35 sys_kill(sys_getpid(), SIGABRT); 36 for (;;); 37} 38 39static __attribute__((unused)) 40long atol(const char *s) 41{ 42 unsigned long ret = 0; 43 unsigned long d; 44 int neg = 0; 45 46 if (*s == '-') { 47 neg = 1; 48 s++; 49 } 50 51 while (1) { 52 d = (*s++) - '0'; 53 if (d > 9) 54 break; 55 ret *= 10; 56 ret += d; 57 } 58 59 return neg ? -ret : ret; 60} 61 62static __attribute__((unused)) 63int atoi(const char *s) 64{ 65 return atol(s); 66} 67 68static __attribute__((unused)) 69void free(void *ptr) 70{ 71 struct nolibc_heap *heap; 72 73 if (!ptr) 74 return; 75 76 heap = container_of(ptr, struct nolibc_heap, user_p); 77 munmap(heap, heap->len); 78} 79 80/* getenv() tries to find the environment variable named <name> in the 81 * environment array pointed to by global variable "environ" which must be 82 * declared as a char **, and must be terminated by a NULL (it is recommended 83 * to set this variable to the "envp" argument of main()). If the requested 84 * environment variable exists its value is returned otherwise NULL is 85 * returned. getenv() is forcefully inlined so that the reference to "environ" 86 * will be dropped if unused, even at -O0. 87 */ 88static __attribute__((unused)) 89char *_getenv(const char *name, char **environ) 90{ 91 int idx, i; 92 93 if (environ) { 94 for (idx = 0; environ[idx]; idx++) { 95 for (i = 0; name[i] && name[i] == environ[idx][i];) 96 i++; 97 if (!name[i] && environ[idx][i] == '=') 98 return &environ[idx][i+1]; 99 } 100 } 101 return NULL; 102} 103 104static inline __attribute__((unused,always_inline)) 105char *getenv(const char *name) 106{ 107 extern char **environ; 108 return _getenv(name, environ); 109} 110 111static __attribute__((unused)) 112void *malloc(size_t len) 113{ 114 struct nolibc_heap *heap; 115 116 /* Always allocate memory with size multiple of 4096. */ 117 len = sizeof(*heap) + len; 118 len = (len + 4095UL) & -4096UL; 119 heap = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 120 -1, 0); 121 if (__builtin_expect(heap == MAP_FAILED, 0)) 122 return NULL; 123 124 heap->len = len; 125 return heap->user_p; 126} 127 128static __attribute__((unused)) 129void *calloc(size_t size, size_t nmemb) 130{ 131 void *orig; 132 size_t res = 0; 133 134 if (__builtin_expect(__builtin_mul_overflow(nmemb, size, &res), 0)) { 135 SET_ERRNO(ENOMEM); 136 return NULL; 137 } 138 139 /* 140 * No need to zero the heap, the MAP_ANONYMOUS in malloc() 141 * already does it. 142 */ 143 return malloc(res); 144} 145 146static __attribute__((unused)) 147void *realloc(void *old_ptr, size_t new_size) 148{ 149 struct nolibc_heap *heap; 150 size_t user_p_len; 151 void *ret; 152 153 if (!old_ptr) 154 return malloc(new_size); 155 156 heap = container_of(old_ptr, struct nolibc_heap, user_p); 157 user_p_len = heap->len - sizeof(*heap); 158 /* 159 * Don't realloc() if @user_p_len >= @new_size, this block of 160 * memory is still enough to handle the @new_size. Just return 161 * the same pointer. 162 */ 163 if (user_p_len >= new_size) 164 return old_ptr; 165 166 ret = malloc(new_size); 167 if (__builtin_expect(!ret, 0)) 168 return NULL; 169 170 memcpy(ret, heap->user_p, heap->len); 171 munmap(heap, heap->len); 172 return ret; 173} 174 175/* Converts the unsigned long integer <in> to its hex representation into 176 * buffer <buffer>, which must be long enough to store the number and the 177 * trailing zero (17 bytes for "ffffffffffffffff" or 9 for "ffffffff"). The 178 * buffer is filled from the first byte, and the number of characters emitted 179 * (not counting the trailing zero) is returned. The function is constructed 180 * in a way to optimize the code size and avoid any divide that could add a 181 * dependency on large external functions. 182 */ 183static __attribute__((unused)) 184int utoh_r(unsigned long in, char *buffer) 185{ 186 signed char pos = (~0UL > 0xfffffffful) ? 60 : 28; 187 int digits = 0; 188 int dig; 189 190 do { 191 dig = in >> pos; 192 in -= (uint64_t)dig << pos; 193 pos -= 4; 194 if (dig || digits || pos < 0) { 195 if (dig > 9) 196 dig += 'a' - '0' - 10; 197 buffer[digits++] = '0' + dig; 198 } 199 } while (pos >= 0); 200 201 buffer[digits] = 0; 202 return digits; 203} 204 205/* converts unsigned long <in> to an hex string using the static itoa_buffer 206 * and returns the pointer to that string. 207 */ 208static inline __attribute__((unused)) 209char *utoh(unsigned long in) 210{ 211 utoh_r(in, itoa_buffer); 212 return itoa_buffer; 213} 214 215/* Converts the unsigned long integer <in> to its string representation into 216 * buffer <buffer>, which must be long enough to store the number and the 217 * trailing zero (21 bytes for 18446744073709551615 in 64-bit, 11 for 218 * 4294967295 in 32-bit). The buffer is filled from the first byte, and the 219 * number of characters emitted (not counting the trailing zero) is returned. 220 * The function is constructed in a way to optimize the code size and avoid 221 * any divide that could add a dependency on large external functions. 222 */ 223static __attribute__((unused)) 224int utoa_r(unsigned long in, char *buffer) 225{ 226 unsigned long lim; 227 int digits = 0; 228 int pos = (~0UL > 0xfffffffful) ? 19 : 9; 229 int dig; 230 231 do { 232 for (dig = 0, lim = 1; dig < pos; dig++) 233 lim *= 10; 234 235 if (digits || in >= lim || !pos) { 236 for (dig = 0; in >= lim; dig++) 237 in -= lim; 238 buffer[digits++] = '0' + dig; 239 } 240 } while (pos--); 241 242 buffer[digits] = 0; 243 return digits; 244} 245 246/* Converts the signed long integer <in> to its string representation into 247 * buffer <buffer>, which must be long enough to store the number and the 248 * trailing zero (21 bytes for -9223372036854775808 in 64-bit, 12 for 249 * -2147483648 in 32-bit). The buffer is filled from the first byte, and the 250 * number of characters emitted (not counting the trailing zero) is returned. 251 */ 252static __attribute__((unused)) 253int itoa_r(long in, char *buffer) 254{ 255 char *ptr = buffer; 256 int len = 0; 257 258 if (in < 0) { 259 in = -in; 260 *(ptr++) = '-'; 261 len++; 262 } 263 len += utoa_r(in, ptr); 264 return len; 265} 266 267/* for historical compatibility, same as above but returns the pointer to the 268 * buffer. 269 */ 270static inline __attribute__((unused)) 271char *ltoa_r(long in, char *buffer) 272{ 273 itoa_r(in, buffer); 274 return buffer; 275} 276 277/* converts long integer <in> to a string using the static itoa_buffer and 278 * returns the pointer to that string. 279 */ 280static inline __attribute__((unused)) 281char *itoa(long in) 282{ 283 itoa_r(in, itoa_buffer); 284 return itoa_buffer; 285} 286 287/* converts long integer <in> to a string using the static itoa_buffer and 288 * returns the pointer to that string. Same as above, for compatibility. 289 */ 290static inline __attribute__((unused)) 291char *ltoa(long in) 292{ 293 itoa_r(in, itoa_buffer); 294 return itoa_buffer; 295} 296 297/* converts unsigned long integer <in> to a string using the static itoa_buffer 298 * and returns the pointer to that string. 299 */ 300static inline __attribute__((unused)) 301char *utoa(unsigned long in) 302{ 303 utoa_r(in, itoa_buffer); 304 return itoa_buffer; 305} 306 307/* Converts the unsigned 64-bit integer <in> to its hex representation into 308 * buffer <buffer>, which must be long enough to store the number and the 309 * trailing zero (17 bytes for "ffffffffffffffff"). The buffer is filled from 310 * the first byte, and the number of characters emitted (not counting the 311 * trailing zero) is returned. The function is constructed in a way to optimize 312 * the code size and avoid any divide that could add a dependency on large 313 * external functions. 314 */ 315static __attribute__((unused)) 316int u64toh_r(uint64_t in, char *buffer) 317{ 318 signed char pos = 60; 319 int digits = 0; 320 int dig; 321 322 do { 323 if (sizeof(long) >= 8) { 324 dig = (in >> pos) & 0xF; 325 } else { 326 /* 32-bit platforms: avoid a 64-bit shift */ 327 uint32_t d = (pos >= 32) ? (in >> 32) : in; 328 dig = (d >> (pos & 31)) & 0xF; 329 } 330 if (dig > 9) 331 dig += 'a' - '0' - 10; 332 pos -= 4; 333 if (dig || digits || pos < 0) 334 buffer[digits++] = '0' + dig; 335 } while (pos >= 0); 336 337 buffer[digits] = 0; 338 return digits; 339} 340 341/* converts uint64_t <in> to an hex string using the static itoa_buffer and 342 * returns the pointer to that string. 343 */ 344static inline __attribute__((unused)) 345char *u64toh(uint64_t in) 346{ 347 u64toh_r(in, itoa_buffer); 348 return itoa_buffer; 349} 350 351/* Converts the unsigned 64-bit integer <in> to its string representation into 352 * buffer <buffer>, which must be long enough to store the number and the 353 * trailing zero (21 bytes for 18446744073709551615). The buffer is filled from 354 * the first byte, and the number of characters emitted (not counting the 355 * trailing zero) is returned. The function is constructed in a way to optimize 356 * the code size and avoid any divide that could add a dependency on large 357 * external functions. 358 */ 359static __attribute__((unused)) 360int u64toa_r(uint64_t in, char *buffer) 361{ 362 unsigned long long lim; 363 int digits = 0; 364 int pos = 19; /* start with the highest possible digit */ 365 int dig; 366 367 do { 368 for (dig = 0, lim = 1; dig < pos; dig++) 369 lim *= 10; 370 371 if (digits || in >= lim || !pos) { 372 for (dig = 0; in >= lim; dig++) 373 in -= lim; 374 buffer[digits++] = '0' + dig; 375 } 376 } while (pos--); 377 378 buffer[digits] = 0; 379 return digits; 380} 381 382/* Converts the signed 64-bit integer <in> to its string representation into 383 * buffer <buffer>, which must be long enough to store the number and the 384 * trailing zero (21 bytes for -9223372036854775808). The buffer is filled from 385 * the first byte, and the number of characters emitted (not counting the 386 * trailing zero) is returned. 387 */ 388static __attribute__((unused)) 389int i64toa_r(int64_t in, char *buffer) 390{ 391 char *ptr = buffer; 392 int len = 0; 393 394 if (in < 0) { 395 in = -in; 396 *(ptr++) = '-'; 397 len++; 398 } 399 len += u64toa_r(in, ptr); 400 return len; 401} 402 403/* converts int64_t <in> to a string using the static itoa_buffer and returns 404 * the pointer to that string. 405 */ 406static inline __attribute__((unused)) 407char *i64toa(int64_t in) 408{ 409 i64toa_r(in, itoa_buffer); 410 return itoa_buffer; 411} 412 413/* converts uint64_t <in> to a string using the static itoa_buffer and returns 414 * the pointer to that string. 415 */ 416static inline __attribute__((unused)) 417char *u64toa(uint64_t in) 418{ 419 u64toa_r(in, itoa_buffer); 420 return itoa_buffer; 421} 422 423#endif /* _NOLIBC_STDLIB_H */