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"))) 35 void abort(void) 36 { 37 sys_kill(sys_getpid(), SIGABRT); 38 for (;;); 39 } 40 41 static __attribute__((unused)) 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)) 65 int atoi(const char *s) 66 { 67 return atol(s); 68 } 69 70 static __attribute__((unused)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 436 char *u64toa(uint64_t in) 437 { 438 u64toa_r(in, itoa_buffer); 439 return itoa_buffer; 440 } 441 442 static __attribute__((unused)) 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)) 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)) 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)) 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)) 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)) 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)) 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