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

     1  /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
     2  /*
     3   * string function definitions for NOLIBC
     4   * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
     5   */
     6  
     7  #ifndef _NOLIBC_STRING_H
     8  #define _NOLIBC_STRING_H
     9  
    10  #include "std.h"
    11  
    12  static void *malloc(size_t len);
    13  
    14  /*
    15   * As much as possible, please keep functions alphabetically sorted.
    16   */
    17  
    18  static __attribute__((unused))
    19  int memcmp(const void *s1, const void *s2, size_t n)
    20  {
    21  	size_t ofs = 0;
    22  	int c1 = 0;
    23  
    24  	while (ofs < n && !(c1 = ((unsigned char *)s1)[ofs] - ((unsigned char *)s2)[ofs])) {
    25  		ofs++;
    26  	}
    27  	return c1;
    28  }
    29  
    30  static __attribute__((unused))
    31  void *_nolibc_memcpy_up(void *dst, const void *src, size_t len)
    32  {
    33  	size_t pos = 0;
    34  
    35  	while (pos < len) {
    36  		((char *)dst)[pos] = ((const char *)src)[pos];
    37  		pos++;
    38  	}
    39  	return dst;
    40  }
    41  
    42  static __attribute__((unused))
    43  void *_nolibc_memcpy_down(void *dst, const void *src, size_t len)
    44  {
    45  	while (len) {
    46  		len--;
    47  		((char *)dst)[len] = ((const char *)src)[len];
    48  	}
    49  	return dst;
    50  }
    51  
    52  /* might be ignored by the compiler without -ffreestanding, then found as
    53   * missing.
    54   */
    55  __attribute__((weak,unused,section(".text.nolibc_memmove")))
    56  void *memmove(void *dst, const void *src, size_t len)
    57  {
    58  	size_t dir, pos;
    59  
    60  	pos = len;
    61  	dir = -1;
    62  
    63  	if (dst < src) {
    64  		pos = -1;
    65  		dir = 1;
    66  	}
    67  
    68  	while (len) {
    69  		pos += dir;
    70  		((char *)dst)[pos] = ((const char *)src)[pos];
    71  		len--;
    72  	}
    73  	return dst;
    74  }
    75  
    76  /* must be exported, as it's used by libgcc on ARM */
    77  __attribute__((weak,unused,section(".text.nolibc_memcpy")))
    78  void *memcpy(void *dst, const void *src, size_t len)
    79  {
    80  	return _nolibc_memcpy_up(dst, src, len);
    81  }
    82  
    83  /* might be ignored by the compiler without -ffreestanding, then found as
    84   * missing.
    85   */
    86  __attribute__((weak,unused,section(".text.nolibc_memset")))
    87  void *memset(void *dst, int b, size_t len)
    88  {
    89  	char *p = dst;
    90  
    91  	while (len--) {
    92  		/* prevent gcc from recognizing memset() here */
    93  		__asm__ volatile("");
    94  		*(p++) = b;
    95  	}
    96  	return dst;
    97  }
    98  
    99  static __attribute__((unused))
   100  char *strchr(const char *s, int c)
   101  {
   102  	while (*s) {
   103  		if (*s == (char)c)
   104  			return (char *)s;
   105  		s++;
   106  	}
   107  	return NULL;
   108  }
   109  
   110  static __attribute__((unused))
   111  int strcmp(const char *a, const char *b)
   112  {
   113  	unsigned int c;
   114  	int diff;
   115  
   116  	while (!(diff = (unsigned char)*a++ - (c = (unsigned char)*b++)) && c)
   117  		;
   118  	return diff;
   119  }
   120  
   121  static __attribute__((unused))
   122  char *strcpy(char *dst, const char *src)
   123  {
   124  	char *ret = dst;
   125  
   126  	while ((*dst++ = *src++));
   127  	return ret;
   128  }
   129  
   130  /* this function is only used with arguments that are not constants or when
   131   * it's not known because optimizations are disabled. Note that gcc 12
   132   * recognizes an strlen() pattern and replaces it with a jump to strlen(),
   133   * thus itself, hence the asm() statement below that's meant to disable this
   134   * confusing practice.
   135   */
   136  static __attribute__((unused))
   137  size_t strlen(const char *str)
   138  {
   139  	size_t len;
   140  
   141  	for (len = 0; str[len]; len++)
   142  		__asm__("");
   143  	return len;
   144  }
   145  
   146  /* do not trust __builtin_constant_p() at -O0, as clang will emit a test and
   147   * the two branches, then will rely on an external definition of strlen().
   148   */
   149  #if defined(__OPTIMIZE__)
   150  #define nolibc_strlen(x) strlen(x)
   151  #define strlen(str) ({                          \
   152  	__builtin_constant_p((str)) ?           \
   153  		__builtin_strlen((str)) :       \
   154  		nolibc_strlen((str));           \
   155  })
   156  #endif
   157  
   158  static __attribute__((unused))
   159  size_t strnlen(const char *str, size_t maxlen)
   160  {
   161  	size_t len;
   162  
   163  	for (len = 0; (len < maxlen) && str[len]; len++);
   164  	return len;
   165  }
   166  
   167  static __attribute__((unused))
   168  char *strdup(const char *str)
   169  {
   170  	size_t len;
   171  	char *ret;
   172  
   173  	len = strlen(str);
   174  	ret = malloc(len + 1);
   175  	if (__builtin_expect(ret != NULL, 1))
   176  		memcpy(ret, str, len + 1);
   177  
   178  	return ret;
   179  }
   180  
   181  static __attribute__((unused))
   182  char *strndup(const char *str, size_t maxlen)
   183  {
   184  	size_t len;
   185  	char *ret;
   186  
   187  	len = strnlen(str, maxlen);
   188  	ret = malloc(len + 1);
   189  	if (__builtin_expect(ret != NULL, 1)) {
   190  		memcpy(ret, str, len);
   191  		ret[len] = '\0';
   192  	}
   193  
   194  	return ret;
   195  }
   196  
   197  static __attribute__((unused))
   198  size_t strlcat(char *dst, const char *src, size_t size)
   199  {
   200  	size_t len;
   201  	char c;
   202  
   203  	for (len = 0; dst[len];	len++)
   204  		;
   205  
   206  	for (;;) {
   207  		c = *src;
   208  		if (len < size)
   209  			dst[len] = c;
   210  		if (!c)
   211  			break;
   212  		len++;
   213  		src++;
   214  	}
   215  
   216  	return len;
   217  }
   218  
   219  static __attribute__((unused))
   220  size_t strlcpy(char *dst, const char *src, size_t size)
   221  {
   222  	size_t len;
   223  	char c;
   224  
   225  	for (len = 0;;) {
   226  		c = src[len];
   227  		if (len < size)
   228  			dst[len] = c;
   229  		if (!c)
   230  			break;
   231  		len++;
   232  	}
   233  	return len;
   234  }
   235  
   236  static __attribute__((unused))
   237  char *strncat(char *dst, const char *src, size_t size)
   238  {
   239  	char *orig = dst;
   240  
   241  	while (*dst)
   242  		dst++;
   243  
   244  	while (size && (*dst = *src)) {
   245  		src++;
   246  		dst++;
   247  		size--;
   248  	}
   249  
   250  	*dst = 0;
   251  	return orig;
   252  }
   253  
   254  static __attribute__((unused))
   255  int strncmp(const char *a, const char *b, size_t size)
   256  {
   257  	unsigned int c;
   258  	int diff = 0;
   259  
   260  	while (size-- &&
   261  	       !(diff = (unsigned char)*a++ - (c = (unsigned char)*b++)) && c)
   262  		;
   263  
   264  	return diff;
   265  }
   266  
   267  static __attribute__((unused))
   268  char *strncpy(char *dst, const char *src, size_t size)
   269  {
   270  	size_t len;
   271  
   272  	for (len = 0; len < size; len++)
   273  		if ((dst[len] = *src))
   274  			src++;
   275  	return dst;
   276  }
   277  
   278  static __attribute__((unused))
   279  char *strrchr(const char *s, int c)
   280  {
   281  	const char *ret = NULL;
   282  
   283  	while (*s) {
   284  		if (*s == (char)c)
   285  			ret = s;
   286  		s++;
   287  	}
   288  	return (char *)ret;
   289  }
   290  
   291  /* make sure to include all global symbols */
   292  #include "nolibc.h"
   293  
   294  #endif /* _NOLIBC_STRING_H */