at v6.15 554 lines 13 kB view raw
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 17struct 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 */ 26static __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 */ 33void abort(void); 34__attribute__((weak,unused,noreturn,section(".text.nolibc_abort"))) 35void abort(void) 36{ 37 sys_kill(sys_getpid(), SIGABRT); 38 for (;;); 39} 40 41static __attribute__((unused)) 42long 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 64static __attribute__((unused)) 65int atoi(const char *s) 66{ 67 return atol(s); 68} 69 70static __attribute__((unused)) 71void 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 */ 89static __attribute__((unused)) 90char *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 105static __attribute__((unused)) 106unsigned 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 131static __attribute__((unused)) 132void *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 148static __attribute__((unused)) 149void *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 165static __attribute__((unused)) 166void *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 */ 202static __attribute__((unused)) 203int 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 */ 227static __inline__ __attribute__((unused)) 228char *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 */ 242static __attribute__((unused)) 243int 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 */ 271static __attribute__((unused)) 272int 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 */ 289static __inline__ __attribute__((unused)) 290char *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 */ 299static __inline__ __attribute__((unused)) 300char *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 */ 309static __inline__ __attribute__((unused)) 310char *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 */ 319static __inline__ __attribute__((unused)) 320char *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 */ 334static __attribute__((unused)) 335int 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 */ 363static __inline__ __attribute__((unused)) 364char *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 */ 378static __attribute__((unused)) 379int 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 */ 407static __attribute__((unused)) 408int 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 */ 425static __inline__ __attribute__((unused)) 426char *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 */ 435static __inline__ __attribute__((unused)) 436char *u64toa(uint64_t in) 437{ 438 u64toa_r(in, itoa_buffer); 439 return itoa_buffer; 440} 441 442static __attribute__((unused)) 443uintmax_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 505out: 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 515static __attribute__((unused)) 516long strtol(const char *nptr, char **endptr, int base) 517{ 518 return __strtox(nptr, endptr, base, LONG_MIN, LONG_MAX); 519} 520 521static __attribute__((unused)) 522unsigned long strtoul(const char *nptr, char **endptr, int base) 523{ 524 return __strtox(nptr, endptr, base, 0, ULONG_MAX); 525} 526 527static __attribute__((unused)) 528long long strtoll(const char *nptr, char **endptr, int base) 529{ 530 return __strtox(nptr, endptr, base, LLONG_MIN, LLONG_MAX); 531} 532 533static __attribute__((unused)) 534unsigned long long strtoull(const char *nptr, char **endptr, int base) 535{ 536 return __strtox(nptr, endptr, base, 0, ULLONG_MAX); 537} 538 539static __attribute__((unused)) 540intmax_t strtoimax(const char *nptr, char **endptr, int base) 541{ 542 return __strtox(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX); 543} 544 545static __attribute__((unused)) 546uintmax_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 */