test-string.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* Test and measure string and memory functions.
  2. Copyright (C) 1999-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <sys/cdefs.h>
  16. #include <support/support.h>
  17. typedef struct
  18. {
  19. const char *name;
  20. void (*fn) (void);
  21. long test;
  22. } impl_t;
  23. extern impl_t __start_impls[], __stop_impls[];
  24. #define IMPL(name, test) \
  25. impl_t tst_ ## name \
  26. __attribute__ ((section ("impls"), aligned (sizeof (void *)))) \
  27. = { __STRING (name), (void (*) (void))name, test };
  28. #ifdef TEST_MAIN
  29. #ifndef _GNU_SOURCE
  30. #define _GNU_SOURCE
  31. #endif
  32. #undef __USE_STRING_INLINES
  33. #include <libc-misc.h>
  34. #include <getopt.h>
  35. #include <stdint.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <sys/mman.h>
  40. #include <sys/param.h>
  41. #include <unistd.h>
  42. #include <fcntl.h>
  43. #include <error.h>
  44. #include <errno.h>
  45. #include <time.h>
  46. #include <ifunc-impl-list.h>
  47. #define GL(x) _##x
  48. #define GLRO(x) _##x
  49. # define TEST_FUNCTION test_main
  50. # ifndef TIMEOUT
  51. # define TIMEOUT (4 * 60)
  52. # endif
  53. # define OPT_ITERATIONS 10000
  54. # define OPT_RANDOM 10001
  55. # define OPT_SEED 10002
  56. unsigned char *buf1, *buf2;
  57. int ret, do_srandom;
  58. unsigned int seed;
  59. size_t page_size;
  60. # ifndef ITERATIONS
  61. size_t iterations = 100000;
  62. # define ITERATIONS_OPTIONS \
  63. { "iterations", required_argument, NULL, OPT_ITERATIONS },
  64. # define ITERATIONS_PROCESS \
  65. case OPT_ITERATIONS: \
  66. iterations = strtoul (optarg, NULL, 0); \
  67. break;
  68. # define ITERATIONS iterations
  69. # else
  70. # define ITERATIONS_OPTIONS
  71. # define ITERATIONS_PROCESS
  72. # endif
  73. # define CMDLINE_OPTIONS ITERATIONS_OPTIONS \
  74. { "random", no_argument, NULL, OPT_RANDOM }, \
  75. { "seed", required_argument, NULL, OPT_SEED },
  76. static void __attribute__ ((used))
  77. cmdline_process_function (int c)
  78. {
  79. switch (c)
  80. {
  81. ITERATIONS_PROCESS
  82. case OPT_RANDOM:
  83. {
  84. int fdr = open ("/dev/urandom", O_RDONLY);
  85. if (fdr < 0 || read (fdr, &seed, sizeof (seed)) != sizeof (seed))
  86. seed = time (NULL);
  87. if (fdr >= 0)
  88. close (fdr);
  89. do_srandom = 1;
  90. break;
  91. }
  92. case OPT_SEED:
  93. seed = strtoul (optarg, NULL, 0);
  94. do_srandom = 1;
  95. break;
  96. }
  97. }
  98. # define CMDLINE_PROCESS cmdline_process_function
  99. #define CALL(impl, ...) \
  100. (* (proto_t) (impl)->fn) (__VA_ARGS__)
  101. #ifdef TEST_NAME
  102. /* Increase size of FUNC_LIST if assert is triggered at run-time. */
  103. static struct libc_ifunc_impl func_list[32];
  104. static int func_count;
  105. static int impl_count __attribute__ ((unused)) = -1;
  106. static impl_t *impl_array __attribute__ ((unused));
  107. # define FOR_EACH_IMPL(impl, notall) \
  108. impl_t *impl; \
  109. int count; \
  110. if (impl_count == -1) \
  111. { \
  112. impl_count = 0; \
  113. if (func_count != 0) \
  114. { \
  115. int f; \
  116. impl_t *skip = NULL, *a; \
  117. for (impl = __start_impls; impl < __stop_impls; ++impl) \
  118. if (strcmp (impl->name, TEST_NAME) == 0) \
  119. skip = impl; \
  120. else \
  121. impl_count++; \
  122. a = impl_array = xmalloc ((impl_count + func_count) * \
  123. sizeof (impl_t)); \
  124. for (impl = __start_impls; impl < __stop_impls; ++impl) \
  125. if (impl != skip) \
  126. *a++ = *impl; \
  127. for (f = 0; f < func_count; f++) \
  128. if (func_list[f].usable) \
  129. { \
  130. a->name = func_list[f].name; \
  131. a->fn = func_list[f].fn; \
  132. a->test = 1; \
  133. a++; \
  134. } \
  135. impl_count = a - impl_array; \
  136. } \
  137. else \
  138. { \
  139. impl_count = __stop_impls - __start_impls; \
  140. impl_array = __start_impls; \
  141. } \
  142. } \
  143. impl = impl_array; \
  144. for (count = 0; count < impl_count; ++count, ++impl) \
  145. if (!notall || impl->test)
  146. #else
  147. # define FOR_EACH_IMPL(impl, notall) \
  148. for (impl_t *impl = __start_impls; impl < __stop_impls; ++impl) \
  149. if (!notall || impl->test)
  150. #endif
  151. #ifndef BUF1PAGES
  152. # define BUF1PAGES 1
  153. #endif
  154. static void
  155. test_init (void)
  156. {
  157. #ifdef TEST_NAME
  158. func_count = __libc_ifunc_impl_list (TEST_NAME, func_list,
  159. (sizeof func_list
  160. / sizeof func_list[0]));
  161. #endif
  162. page_size = 2 * getpagesize ();
  163. #ifdef MIN_PAGE_SIZE
  164. if (page_size < MIN_PAGE_SIZE)
  165. page_size = MIN_PAGE_SIZE;
  166. #endif
  167. buf1 = mmap (0, (BUF1PAGES + 1) * page_size, PROT_READ | PROT_WRITE,
  168. MAP_PRIVATE | MAP_ANON, -1, 0);
  169. if (buf1 == MAP_FAILED)
  170. error (EXIT_FAILURE, errno, "mmap failed");
  171. if (mprotect (buf1 + BUF1PAGES * page_size, page_size, PROT_NONE))
  172. error (EXIT_FAILURE, errno, "mprotect failed");
  173. buf2 = mmap (0, 2 * page_size, PROT_READ | PROT_WRITE,
  174. MAP_PRIVATE | MAP_ANON, -1, 0);
  175. if (buf2 == MAP_FAILED)
  176. error (EXIT_FAILURE, errno, "mmap failed");
  177. if (mprotect (buf2 + page_size, page_size, PROT_NONE))
  178. error (EXIT_FAILURE, errno, "mprotect failed");
  179. if (do_srandom)
  180. {
  181. printf ("Setting seed to 0x%x\n", seed);
  182. srandom (seed);
  183. }
  184. memset (buf1, 0xa5, BUF1PAGES * page_size);
  185. memset (buf2, 0x5a, page_size);
  186. }
  187. #endif