test-string.h 5.9 KB

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