at v6.0 11 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 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 size_t x = size * nmemb; 132 133 if (__builtin_expect(size && ((x / size) != nmemb), 0)) { 134 SET_ERRNO(ENOMEM); 135 return NULL; 136 } 137 138 /* 139 * No need to zero the heap, the MAP_ANONYMOUS in malloc() 140 * already does it. 141 */ 142 return malloc(x); 143} 144 145static __attribute__((unused)) 146void *realloc(void *old_ptr, size_t new_size) 147{ 148 struct nolibc_heap *heap; 149 size_t user_p_len; 150 void *ret; 151 152 if (!old_ptr) 153 return malloc(new_size); 154 155 heap = container_of(old_ptr, struct nolibc_heap, user_p); 156 user_p_len = heap->len - sizeof(*heap); 157 /* 158 * Don't realloc() if @user_p_len >= @new_size, this block of 159 * memory is still enough to handle the @new_size. Just return 160 * the same pointer. 161 */ 162 if (user_p_len >= new_size) 163 return old_ptr; 164 165 ret = malloc(new_size); 166 if (__builtin_expect(!ret, 0)) 167 return NULL; 168 169 memcpy(ret, heap->user_p, heap->len); 170 munmap(heap, heap->len); 171 return ret; 172} 173 174/* Converts the unsigned long integer <in> to its hex representation into 175 * buffer <buffer>, which must be long enough to store the number and the 176 * trailing zero (17 bytes for "ffffffffffffffff" or 9 for "ffffffff"). The 177 * buffer is filled from the first byte, and the number of characters emitted 178 * (not counting the trailing zero) is returned. The function is constructed 179 * in a way to optimize the code size and avoid any divide that could add a 180 * dependency on large external functions. 181 */ 182static __attribute__((unused)) 183int utoh_r(unsigned long in, char *buffer) 184{ 185 signed char pos = (~0UL > 0xfffffffful) ? 60 : 28; 186 int digits = 0; 187 int dig; 188 189 do { 190 dig = in >> pos; 191 in -= (uint64_t)dig << pos; 192 pos -= 4; 193 if (dig || digits || pos < 0) { 194 if (dig > 9) 195 dig += 'a' - '0' - 10; 196 buffer[digits++] = '0' + dig; 197 } 198 } while (pos >= 0); 199 200 buffer[digits] = 0; 201 return digits; 202} 203 204/* converts unsigned long <in> to an hex string using the static itoa_buffer 205 * and returns the pointer to that string. 206 */ 207static inline __attribute__((unused)) 208char *utoh(unsigned long in) 209{ 210 utoh_r(in, itoa_buffer); 211 return itoa_buffer; 212} 213 214/* Converts the unsigned long integer <in> to its string representation into 215 * buffer <buffer>, which must be long enough to store the number and the 216 * trailing zero (21 bytes for 18446744073709551615 in 64-bit, 11 for 217 * 4294967295 in 32-bit). The buffer is filled from the first byte, and the 218 * number of characters emitted (not counting the trailing zero) is returned. 219 * The function is constructed in a way to optimize the code size and avoid 220 * any divide that could add a dependency on large external functions. 221 */ 222static __attribute__((unused)) 223int utoa_r(unsigned long in, char *buffer) 224{ 225 unsigned long lim; 226 int digits = 0; 227 int pos = (~0UL > 0xfffffffful) ? 19 : 9; 228 int dig; 229 230 do { 231 for (dig = 0, lim = 1; dig < pos; dig++) 232 lim *= 10; 233 234 if (digits || in >= lim || !pos) { 235 for (dig = 0; in >= lim; dig++) 236 in -= lim; 237 buffer[digits++] = '0' + dig; 238 } 239 } while (pos--); 240 241 buffer[digits] = 0; 242 return digits; 243} 244 245/* Converts the signed long integer <in> to its string representation into 246 * buffer <buffer>, which must be long enough to store the number and the 247 * trailing zero (21 bytes for -9223372036854775808 in 64-bit, 12 for 248 * -2147483648 in 32-bit). The buffer is filled from the first byte, and the 249 * number of characters emitted (not counting the trailing zero) is returned. 250 */ 251static __attribute__((unused)) 252int itoa_r(long in, char *buffer) 253{ 254 char *ptr = buffer; 255 int len = 0; 256 257 if (in < 0) { 258 in = -in; 259 *(ptr++) = '-'; 260 len++; 261 } 262 len += utoa_r(in, ptr); 263 return len; 264} 265 266/* for historical compatibility, same as above but returns the pointer to the 267 * buffer. 268 */ 269static inline __attribute__((unused)) 270char *ltoa_r(long in, char *buffer) 271{ 272 itoa_r(in, buffer); 273 return buffer; 274} 275 276/* converts long integer <in> to a string using the static itoa_buffer and 277 * returns the pointer to that string. 278 */ 279static inline __attribute__((unused)) 280char *itoa(long in) 281{ 282 itoa_r(in, itoa_buffer); 283 return itoa_buffer; 284} 285 286/* converts long integer <in> to a string using the static itoa_buffer and 287 * returns the pointer to that string. Same as above, for compatibility. 288 */ 289static inline __attribute__((unused)) 290char *ltoa(long in) 291{ 292 itoa_r(in, itoa_buffer); 293 return itoa_buffer; 294} 295 296/* converts unsigned long integer <in> to a string using the static itoa_buffer 297 * and returns the pointer to that string. 298 */ 299static inline __attribute__((unused)) 300char *utoa(unsigned long in) 301{ 302 utoa_r(in, itoa_buffer); 303 return itoa_buffer; 304} 305 306/* Converts the unsigned 64-bit integer <in> to its hex representation into 307 * buffer <buffer>, which must be long enough to store the number and the 308 * trailing zero (17 bytes for "ffffffffffffffff"). The buffer is filled from 309 * the first byte, and the number of characters emitted (not counting the 310 * trailing zero) is returned. The function is constructed in a way to optimize 311 * the code size and avoid any divide that could add a dependency on large 312 * external functions. 313 */ 314static __attribute__((unused)) 315int u64toh_r(uint64_t in, char *buffer) 316{ 317 signed char pos = 60; 318 int digits = 0; 319 int dig; 320 321 do { 322 if (sizeof(long) >= 8) { 323 dig = (in >> pos) & 0xF; 324 } else { 325 /* 32-bit platforms: avoid a 64-bit shift */ 326 uint32_t d = (pos >= 32) ? (in >> 32) : in; 327 dig = (d >> (pos & 31)) & 0xF; 328 } 329 if (dig > 9) 330 dig += 'a' - '0' - 10; 331 pos -= 4; 332 if (dig || digits || pos < 0) 333 buffer[digits++] = '0' + dig; 334 } while (pos >= 0); 335 336 buffer[digits] = 0; 337 return digits; 338} 339 340/* converts uint64_t <in> to an hex string using the static itoa_buffer and 341 * returns the pointer to that string. 342 */ 343static inline __attribute__((unused)) 344char *u64toh(uint64_t in) 345{ 346 u64toh_r(in, itoa_buffer); 347 return itoa_buffer; 348} 349 350/* Converts the unsigned 64-bit integer <in> to its string representation into 351 * buffer <buffer>, which must be long enough to store the number and the 352 * trailing zero (21 bytes for 18446744073709551615). The buffer is filled from 353 * the first byte, and the number of characters emitted (not counting the 354 * trailing zero) is returned. The function is constructed in a way to optimize 355 * the code size and avoid any divide that could add a dependency on large 356 * external functions. 357 */ 358static __attribute__((unused)) 359int u64toa_r(uint64_t in, char *buffer) 360{ 361 unsigned long long lim; 362 int digits = 0; 363 int pos = 19; /* start with the highest possible digit */ 364 int dig; 365 366 do { 367 for (dig = 0, lim = 1; dig < pos; dig++) 368 lim *= 10; 369 370 if (digits || in >= lim || !pos) { 371 for (dig = 0; in >= lim; dig++) 372 in -= lim; 373 buffer[digits++] = '0' + dig; 374 } 375 } while (pos--); 376 377 buffer[digits] = 0; 378 return digits; 379} 380 381/* Converts the signed 64-bit integer <in> to its string representation into 382 * buffer <buffer>, which must be long enough to store the number and the 383 * trailing zero (21 bytes for -9223372036854775808). The buffer is filled from 384 * the first byte, and the number of characters emitted (not counting the 385 * trailing zero) is returned. 386 */ 387static __attribute__((unused)) 388int i64toa_r(int64_t in, char *buffer) 389{ 390 char *ptr = buffer; 391 int len = 0; 392 393 if (in < 0) { 394 in = -in; 395 *(ptr++) = '-'; 396 len++; 397 } 398 len += u64toa_r(in, ptr); 399 return len; 400} 401 402/* converts int64_t <in> to a string using the static itoa_buffer and returns 403 * the pointer to that string. 404 */ 405static inline __attribute__((unused)) 406char *i64toa(int64_t in) 407{ 408 i64toa_r(in, itoa_buffer); 409 return itoa_buffer; 410} 411 412/* converts uint64_t <in> to a string using the static itoa_buffer and returns 413 * the pointer to that string. 414 */ 415static inline __attribute__((unused)) 416char *u64toa(uint64_t in) 417{ 418 u64toa_r(in, itoa_buffer); 419 return itoa_buffer; 420} 421 422#endif /* _NOLIBC_STDLIB_H */