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 __attribute__((weak,unused,noreturn,section(".text.nolibc_abort"))) 34 void abort(void) 35 { 36 sys_kill(sys_getpid(), SIGABRT); 37 for (;;); 38 } 39 40 static __attribute__((unused)) 41 long atol(const char *s) 42 { 43 unsigned long ret = 0; 44 unsigned long d; 45 int neg = 0; 46 47 if (*s == '-') { 48 neg = 1; 49 s++; 50 } 51 52 while (1) { 53 d = (*s++) - ''; 54 if (d > 9) 55 break; 56 ret *= 10; 57 ret += d; 58 } 59 60 return neg ? -ret : ret; 61 } 62 63 static __attribute__((unused)) 64 int atoi(const char *s) 65 { 66 return atol(s); 67 } 68 69 static __attribute__((unused)) 70 void free(void *ptr) 71 { 72 struct nolibc_heap *heap; 73 74 if (!ptr) 75 return; 76 77 heap = container_of(ptr, struct nolibc_heap, user_p); 78 munmap(heap, heap->len); 79 } 80 81 /* getenv() tries to find the environment variable named <name> in the 82 * environment array pointed to by global variable "environ" which must be 83 * declared as a char **, and must be terminated by a NULL (it is recommended 84 * to set this variable to the "envp" argument of main()). If the requested 85 * environment variable exists its value is returned otherwise NULL is 86 * returned. 87 */ 88 static __attribute__((unused)) 89 char *getenv(const char *name) 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 104 static __attribute__((unused)) 105 unsigned long getauxval(unsigned long type) 106 { 107 const unsigned long *auxv = _auxv; 108 unsigned long ret; 109 110 if (!auxv) 111 return 0; 112 113 while (1) { 114 if (!auxv[0] && !auxv[1]) { 115 ret = 0; 116 break; 117 } 118 119 if (auxv[0] == type) { 120 ret = auxv[1]; 121 break; 122 } 123 124 auxv += 2; 125 } 126 127 return ret; 128 } 129 130 static __attribute__((unused)) 131 void *malloc(size_t len) 132 { 133 struct nolibc_heap *heap; 134 135 /* Always allocate memory with size multiple of 4096. */ 136 len = sizeof(*heap) + len; 137 len = (len + 4095UL) & -4096UL; 138 heap = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 139 -1, 0); 140 if (__builtin_expect(heap == MAP_FAILED, 0)) 141 return NULL; 142 143 heap->len = len; 144 return heap->user_p; 145 } 146 147 static __attribute__((unused)) 148 void *calloc(size_t size, size_t nmemb) 149 { 150 size_t x = size * nmemb; 151 152 if (__builtin_expect(size && ((x / size) != nmemb), 0)) { 153 SET_ERRNO(ENOMEM); 154 return NULL; 155 } 156 157 /* 158 * No need to zero the heap, the MAP_ANONYMOUS in malloc() 159 * already does it. 160 */ 161 return malloc(x); 162 } 163 164 static __attribute__((unused)) 165 void *realloc(void *old_ptr, size_t new_size) 166 { 167 struct nolibc_heap *heap; 168 size_t user_p_len; 169 void *ret; 170 171 if (!old_ptr) 172 return malloc(new_size); 173 174 heap = container_of(old_ptr, struct nolibc_heap, user_p); 175 user_p_len = heap->len - sizeof(*heap); 176 /* 177 * Don't realloc() if @user_p_len >= @new_size, this block of 178 * memory is still enough to handle the @new_size. Just return 179 * the same pointer. 180 */ 181 if (user_p_len >= new_size) 182 return old_ptr; 183 184 ret = malloc(new_size); 185 if (__builtin_expect(!ret, 0)) 186 return NULL; 187 188 memcpy(ret, heap->user_p, user_p_len); 189 munmap(heap, heap->len); 190 return ret; 191 } 192 193 /* Converts the unsigned long integer <in> to its hex representation into 194 * buffer <buffer>, which must be long enough to store the number and the 195 * trailing zero (17 bytes for "ffffffffffffffff" or 9 for "ffffffff"). The 196 * buffer is filled from the first byte, and the number of characters emitted 197 * (not counting the trailing zero) is returned. The function is constructed 198 * in a way to optimize the code size and avoid any divide that could add a 199 * dependency on large external functions. 200 */ 201 static __attribute__((unused)) 202 int utoh_r(unsigned long in, char *buffer) 203 { 204 signed char pos = (~0UL > 0xfffffffful) ? 60 : 28; 205 int digits = 0; 206 int dig; 207 208 do { 209 dig = in >> pos; 210 in -= (uint64_t)dig << pos; 211 pos -= 4; 212 if (dig || digits || pos < 0) { 213 if (dig > 9) 214 dig += 'a' - '' - 10; 215 buffer[digits++] = '' + dig; 216 } 217 } while (pos >= 0); 218 219 buffer[digits] = 0; 220 return digits; 221 } 222 223 /* converts unsigned long <in> to an hex string using the static itoa_buffer 224 * and returns the pointer to that string. 225 */ 226 static __inline__ __attribute__((unused)) 227 char *utoh(unsigned long in) 228 { 229 utoh_r(in, itoa_buffer); 230 return itoa_buffer; 231 } 232 233 /* Converts the unsigned long integer <in> to its string representation into 234 * buffer <buffer>, which must be long enough to store the number and the 235 * trailing zero (21 bytes for 18446744073709551615 in 64-bit, 11 for 236 * 4294967295 in 32-bit). The buffer is filled from the first byte, and the 237 * number of characters emitted (not counting the trailing zero) is returned. 238 * The function is constructed in a way to optimize the code size and avoid 239 * any divide that could add a dependency on large external functions. 240 */ 241 static __attribute__((unused)) 242 int utoa_r(unsigned long in, char *buffer) 243 { 244 unsigned long lim; 245 int digits = 0; 246 int pos = (~0UL > 0xfffffffful) ? 19 : 9; 247 int dig; 248 249 do { 250 for (dig = 0, lim = 1; dig < pos; dig++) 251 lim *= 10; 252 253 if (digits || in >= lim || !pos) { 254 for (dig = 0; in >= lim; dig++) 255 in -= lim; 256 buffer[digits++] = '' + dig; 257 } 258 } while (pos--); 259 260 buffer[digits] = 0; 261 return digits; 262 } 263 264 /* Converts the signed long integer <in> to its string representation into 265 * buffer <buffer>, which must be long enough to store the number and the 266 * trailing zero (21 bytes for -9223372036854775808 in 64-bit, 12 for 267 * -2147483648 in 32-bit). The buffer is filled from the first byte, and the 268 * number of characters emitted (not counting the trailing zero) is returned. 269 */ 270 static __attribute__((unused)) 271 int itoa_r(long in, char *buffer) 272 { 273 char *ptr = buffer; 274 int len = 0; 275 276 if (in < 0) { 277 in = -in; 278 *(ptr++) = '-'; 279 len++; 280 } 281 len += utoa_r(in, ptr); 282 return len; 283 } 284 285 /* for historical compatibility, same as above but returns the pointer to the 286 * buffer. 287 */ 288 static __inline__ __attribute__((unused)) 289 char *ltoa_r(long in, char *buffer) 290 { 291 itoa_r(in, buffer); 292 return buffer; 293 } 294 295 /* converts long integer <in> to a string using the static itoa_buffer and 296 * returns the pointer to that string. 297 */ 298 static __inline__ __attribute__((unused)) 299 char *itoa(long in) 300 { 301 itoa_r(in, itoa_buffer); 302 return itoa_buffer; 303 } 304 305 /* converts long integer <in> to a string using the static itoa_buffer and 306 * returns the pointer to that string. Same as above, for compatibility. 307 */ 308 static __inline__ __attribute__((unused)) 309 char *ltoa(long in) 310 { 311 itoa_r(in, itoa_buffer); 312 return itoa_buffer; 313 } 314 315 /* converts unsigned long integer <in> to a string using the static itoa_buffer 316 * and returns the pointer to that string. 317 */ 318 static __inline__ __attribute__((unused)) 319 char *utoa(unsigned long in) 320 { 321 utoa_r(in, itoa_buffer); 322 return itoa_buffer; 323 } 324 325 /* Converts the unsigned 64-bit integer <in> to its hex representation into 326 * buffer <buffer>, which must be long enough to store the number and the 327 * trailing zero (17 bytes for "ffffffffffffffff"). The buffer is filled from 328 * the first byte, and the number of characters emitted (not counting the 329 * trailing zero) is returned. The function is constructed in a way to optimize 330 * the code size and avoid any divide that could add a dependency on large 331 * external functions. 332 */ 333 static __attribute__((unused)) 334 int u64toh_r(uint64_t in, char *buffer) 335 { 336 signed char pos = 60; 337 int digits = 0; 338 int dig; 339 340 do { 341 if (sizeof(long) >= 8) { 342 dig = (in >> pos) & 0xF; 343 } else { 344 /* 32-bit platforms: avoid a 64-bit shift */ 345 uint32_t d = (pos >= 32) ? (in >> 32) : in; 346 dig = (d >> (pos & 31)) & 0xF; 347 } 348 if (dig > 9) 349 dig += 'a' - '' - 10; 350 pos -= 4; 351 if (dig || digits || pos < 0) 352 buffer[digits++] = '' + dig; 353 } while (pos >= 0); 354 355 buffer[digits] = 0; 356 return digits; 357 } 358 359 /* converts uint64_t <in> to an hex string using the static itoa_buffer and 360 * returns the pointer to that string. 361 */ 362 static __inline__ __attribute__((unused)) 363 char *u64toh(uint64_t in) 364 { 365 u64toh_r(in, itoa_buffer); 366 return itoa_buffer; 367 } 368 369 /* Converts the unsigned 64-bit integer <in> to its string representation into 370 * buffer <buffer>, which must be long enough to store the number and the 371 * trailing zero (21 bytes for 18446744073709551615). The buffer is filled from 372 * the first byte, and the number of characters emitted (not counting the 373 * trailing zero) is returned. The function is constructed in a way to optimize 374 * the code size and avoid any divide that could add a dependency on large 375 * external functions. 376 */ 377 static __attribute__((unused)) 378 int u64toa_r(uint64_t in, char *buffer) 379 { 380 unsigned long long lim; 381 int digits = 0; 382 int pos = 19; /* start with the highest possible digit */ 383 int dig; 384 385 do { 386 for (dig = 0, lim = 1; dig < pos; dig++) 387 lim *= 10; 388 389 if (digits || in >= lim || !pos) { 390 for (dig = 0; in >= lim; dig++) 391 in -= lim; 392 buffer[digits++] = '' + dig; 393 } 394 } while (pos--); 395 396 buffer[digits] = 0; 397 return digits; 398 } 399 400 /* Converts the signed 64-bit integer <in> to its string representation into 401 * buffer <buffer>, which must be long enough to store the number and the 402 * trailing zero (21 bytes for -9223372036854775808). The buffer is filled from 403 * the first byte, and the number of characters emitted (not counting the 404 * trailing zero) is returned. 405 */ 406 static __attribute__((unused)) 407 int i64toa_r(int64_t in, char *buffer) 408 { 409 char *ptr = buffer; 410 int len = 0; 411 412 if (in < 0) { 413 in = -in; 414 *(ptr++) = '-'; 415 len++; 416 } 417 len += u64toa_r(in, ptr); 418 return len; 419 } 420 421 /* converts int64_t <in> to a string using the static itoa_buffer and returns 422 * the pointer to that string. 423 */ 424 static __inline__ __attribute__((unused)) 425 char *i64toa(int64_t in) 426 { 427 i64toa_r(in, itoa_buffer); 428 return itoa_buffer; 429 } 430 431 /* converts uint64_t <in> to a string using the static itoa_buffer and returns 432 * the pointer to that string. 433 */ 434 static __inline__ __attribute__((unused)) 435 char *u64toa(uint64_t in) 436 { 437 u64toa_r(in, itoa_buffer); 438 return itoa_buffer; 439 } 440 441 static __attribute__((unused)) 442 uintmax_t __strtox(const char *nptr, char **endptr, int base, intmax_t lower_limit, uintmax_t upper_limit) 443 { 444 const char signed_ = lower_limit != 0; 445 unsigned char neg = 0, overflow = 0; 446 uintmax_t val = 0, limit, old_val; 447 char c; 448 449 if (base < 0 || base > 36) { 450 SET_ERRNO(EINVAL); 451 goto out; 452 } 453 454 while (isspace(*nptr)) 455 nptr++; 456 457 if (*nptr == '+') { 458 nptr++; 459 } else if (*nptr == '-') { 460 neg = 1; 461 nptr++; 462 } 463 464 if (signed_ && neg) 465 limit = -(uintmax_t)lower_limit; 466 else 467 limit = upper_limit; 468 469 if ((base == 0 || base == 16) && 470 (strncmp(nptr, "0x", 2) == 0 || strncmp(nptr, "0X", 2) == 0)) { 471 base = 16; 472 nptr += 2; 473 } else if (base == 0 && strncmp(nptr, "", 1) == 0) { 474 base = 8; 475 nptr += 1; 476 } else if (base == 0) { 477 base = 10; 478 } 479 480 while (*nptr) { 481 c = *nptr; 482 483 if (c >= '' && c <= '9') 484 c -= ''; 485 else if (c >= 'a' && c <= 'z') 486 c = c - 'a' + 10; 487 else if (c >= 'A' && c <= 'Z') 488 c = c - 'A' + 10; 489 else 490 goto out; 491 492 if (c >= base) 493 goto out; 494 495 nptr++; 496 old_val = val; 497 val *= base; 498 val += c; 499 500 if (val > limit || val < old_val) 501 overflow = 1; 502 } 503 504 out: 505 if (overflow) { 506 SET_ERRNO(ERANGE); 507 val = limit; 508 } 509 if (endptr) 510 *endptr = (char *)nptr; 511 return neg ? -val : val; 512 } 513 514 static __attribute__((unused)) 515 long strtol(const char *nptr, char **endptr, int base) 516 { 517 return __strtox(nptr, endptr, base, LONG_MIN, LONG_MAX); 518 } 519 520 static __attribute__((unused)) 521 unsigned long strtoul(const char *nptr, char **endptr, int base) 522 { 523 return __strtox(nptr, endptr, base, 0, ULONG_MAX); 524 } 525 526 static __attribute__((unused)) 527 long long strtoll(const char *nptr, char **endptr, int base) 528 { 529 return __strtox(nptr, endptr, base, LLONG_MIN, LLONG_MAX); 530 } 531 532 static __attribute__((unused)) 533 unsigned long long strtoull(const char *nptr, char **endptr, int base) 534 { 535 return __strtox(nptr, endptr, base, 0, ULLONG_MAX); 536 } 537 538 static __attribute__((unused)) 539 intmax_t strtoimax(const char *nptr, char **endptr, int base) 540 { 541 return __strtox(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX); 542 } 543 544 static __attribute__((unused)) 545 uintmax_t strtoumax(const char *nptr, char **endptr, int base) 546 { 547 return __strtox(nptr, endptr, base, 0, UINTMAX_MAX); 548 } 549 550 /* make sure to include all global symbols */ 551 #include "nolibc.h" 552 553 #endif /* _NOLIBC_STDLIB_H */ 554
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.