github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/dmz/nolibc/stdlib.h (about)

     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++) - '0';
    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, heap->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' - '0' - 10;
   215  			buffer[digits++] = '0' + 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++] = '0' + 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' - '0' - 10;
   350  		pos -= 4;
   351  		if (dig || digits || pos < 0)
   352  			buffer[digits++] = '0' + 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++] = '0' + 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  /* make sure to include all global symbols */
   442  #include "nolibc.h"
   443  
   444  #endif /* _NOLIBC_STDLIB_H */