test-demangle.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /* Demangler test program,
  2. Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
  3. Written by Zack Weinberg <zack@codesourcery.com
  4. This file is part of GNU libiberty.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program 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
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include "ansidecl.h"
  21. #include <stdio.h>
  22. #include "libiberty.h"
  23. #include "demangle.h"
  24. #ifdef HAVE_STRING_H
  25. #include <string.h>
  26. #endif
  27. #if HAVE_STDLIB_H
  28. # include <stdlib.h>
  29. #endif
  30. #ifdef HAVE_UNISTD_H
  31. #include <unistd.h>
  32. #endif
  33. struct line
  34. {
  35. size_t alloced;
  36. char *data;
  37. };
  38. static unsigned int lineno;
  39. /* Safely read a single line of arbitrary length from standard input. */
  40. #define LINELEN 80
  41. static void
  42. get_line(buf)
  43. struct line *buf;
  44. {
  45. char *data = buf->data;
  46. size_t alloc = buf->alloced;
  47. size_t count = 0;
  48. int c;
  49. if (data == 0)
  50. {
  51. data = xmalloc (LINELEN);
  52. alloc = LINELEN;
  53. }
  54. /* Skip comment lines. */
  55. while ((c = getchar()) == '#')
  56. {
  57. while ((c = getchar()) != EOF && c != '\n');
  58. lineno++;
  59. }
  60. /* c is the first character on the line, and it's not a comment
  61. line: copy this line into the buffer and return. */
  62. while (c != EOF && c != '\n')
  63. {
  64. if (count + 1 >= alloc)
  65. {
  66. alloc *= 2;
  67. data = xrealloc (data, alloc);
  68. }
  69. data[count++] = c;
  70. c = getchar();
  71. }
  72. lineno++;
  73. data[count] = '\0';
  74. buf->data = data;
  75. buf->alloced = alloc;
  76. }
  77. /* If we have mmap() and mprotect(), copy the string S just before a
  78. protected page, so that if the demangler runs over the end of the
  79. string we'll get a fault, and return the address of the new string.
  80. If no mmap, or it fails, or it looks too hard, just return S. */
  81. #ifdef HAVE_SYS_MMAN_H
  82. #include <sys/mman.h>
  83. #endif
  84. #if defined(MAP_ANON) && ! defined (MAP_ANONYMOUS)
  85. #define MAP_ANONYMOUS MAP_ANON
  86. #endif
  87. static const char *
  88. protect_end (const char * s)
  89. {
  90. #if defined(HAVE_MMAP) && defined (MAP_ANONYMOUS)
  91. size_t pagesize = getpagesize();
  92. static char * buf;
  93. size_t s_len = strlen (s);
  94. char * result;
  95. /* Don't try if S is too long. */
  96. if (s_len >= pagesize)
  97. return s;
  98. /* Allocate one page of allocated space followed by an unmapped
  99. page. */
  100. if (buf == NULL)
  101. {
  102. buf = mmap (NULL, pagesize * 2, PROT_READ | PROT_WRITE,
  103. MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  104. if (! buf)
  105. return s;
  106. munmap (buf + pagesize, pagesize);
  107. }
  108. result = buf + (pagesize - s_len - 1);
  109. memcpy (result, s, s_len + 1);
  110. return result;
  111. #else
  112. return s;
  113. #endif
  114. }
  115. static void
  116. fail (lineno, opts, in, out, exp)
  117. int lineno;
  118. const char *opts;
  119. const char *in;
  120. const char *out;
  121. const char *exp;
  122. {
  123. printf ("\
  124. FAIL at line %d, options %s:\n\
  125. in: %s\n\
  126. out: %s\n\
  127. exp: %s\n",
  128. lineno, opts, in, out != NULL ? out : "(null)", exp);
  129. }
  130. /* The tester operates on a data file consisting of groups of lines:
  131. options
  132. input to be demangled
  133. expected output
  134. Supported options:
  135. --format=<name> Sets the demangling style.
  136. --no-params There are two lines of expected output; the first
  137. is with DMGL_PARAMS, the second is without it.
  138. --is-v3-ctor Calls is_gnu_v3_mangled_ctor on input; expected
  139. output is an integer representing ctor_kind.
  140. --is-v3-dtor Likewise, but for dtors.
  141. --ret-postfix Passes the DMGL_RET_POSTFIX option
  142. --ret-drop Passes the DMGL_RET_DROP option
  143. For compatibility, just in case it matters, the options line may be
  144. empty, to mean --format=auto. If it doesn't start with --, then it
  145. may contain only a format name.
  146. */
  147. int
  148. main(argc, argv)
  149. int argc;
  150. char **argv;
  151. {
  152. enum demangling_styles style = auto_demangling;
  153. int no_params;
  154. int is_v3_ctor;
  155. int is_v3_dtor;
  156. int ret_postfix, ret_drop;
  157. struct line format;
  158. struct line input;
  159. struct line expect;
  160. char *result;
  161. int failures = 0;
  162. int tests = 0;
  163. if (argc > 1)
  164. {
  165. fprintf (stderr, "usage: %s < test-set\n", argv[0]);
  166. return 2;
  167. }
  168. format.data = 0;
  169. input.data = 0;
  170. expect.data = 0;
  171. for (;;)
  172. {
  173. const char *inp;
  174. get_line (&format);
  175. if (feof (stdin))
  176. break;
  177. get_line (&input);
  178. get_line (&expect);
  179. inp = protect_end (input.data);
  180. tests++;
  181. no_params = 0;
  182. ret_postfix = 0;
  183. ret_drop = 0;
  184. is_v3_ctor = 0;
  185. is_v3_dtor = 0;
  186. if (format.data[0] == '\0')
  187. style = auto_demangling;
  188. else if (format.data[0] != '-')
  189. {
  190. style = cplus_demangle_name_to_style (format.data);
  191. if (style == unknown_demangling)
  192. {
  193. printf ("FAIL at line %d: unknown demangling style %s\n",
  194. lineno, format.data);
  195. failures++;
  196. continue;
  197. }
  198. }
  199. else
  200. {
  201. char *p;
  202. char *opt;
  203. p = format.data;
  204. while (*p != '\0')
  205. {
  206. char c;
  207. opt = p;
  208. p += strcspn (p, " \t=");
  209. c = *p;
  210. *p = '\0';
  211. if (strcmp (opt, "--format") == 0 && c == '=')
  212. {
  213. char *fstyle;
  214. *p = c;
  215. ++p;
  216. fstyle = p;
  217. p += strcspn (p, " \t");
  218. c = *p;
  219. *p = '\0';
  220. style = cplus_demangle_name_to_style (fstyle);
  221. if (style == unknown_demangling)
  222. {
  223. printf ("FAIL at line %d: unknown demangling style %s\n",
  224. lineno, fstyle);
  225. failures++;
  226. continue;
  227. }
  228. }
  229. else if (strcmp (opt, "--no-params") == 0)
  230. no_params = 1;
  231. else if (strcmp (opt, "--is-v3-ctor") == 0)
  232. is_v3_ctor = 1;
  233. else if (strcmp (opt, "--is-v3-dtor") == 0)
  234. is_v3_dtor = 1;
  235. else if (strcmp (opt, "--ret-postfix") == 0)
  236. ret_postfix = 1;
  237. else if (strcmp (opt, "--ret-drop") == 0)
  238. ret_drop = 1;
  239. else
  240. {
  241. printf ("FAIL at line %d: unrecognized option %s\n",
  242. lineno, opt);
  243. failures++;
  244. continue;
  245. }
  246. *p = c;
  247. p += strspn (p, " \t");
  248. }
  249. }
  250. if (is_v3_ctor || is_v3_dtor)
  251. {
  252. char buf[20];
  253. if (is_v3_ctor)
  254. {
  255. enum gnu_v3_ctor_kinds kc;
  256. kc = is_gnu_v3_mangled_ctor (inp);
  257. sprintf (buf, "%d", (int) kc);
  258. }
  259. else
  260. {
  261. enum gnu_v3_dtor_kinds kd;
  262. kd = is_gnu_v3_mangled_dtor (inp);
  263. sprintf (buf, "%d", (int) kd);
  264. }
  265. if (strcmp (buf, expect.data) != 0)
  266. {
  267. fail (lineno, format.data, input.data, buf, expect.data);
  268. failures++;
  269. }
  270. continue;
  271. }
  272. cplus_demangle_set_style (style);
  273. result = cplus_demangle (inp, (DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES
  274. | (ret_postfix ? DMGL_RET_POSTFIX : 0)
  275. | (ret_drop ? DMGL_RET_DROP : 0)));
  276. if (result
  277. ? strcmp (result, expect.data)
  278. : strcmp (input.data, expect.data))
  279. {
  280. fail (lineno, format.data, input.data, result, expect.data);
  281. failures++;
  282. }
  283. free (result);
  284. if (no_params)
  285. {
  286. get_line (&expect);
  287. result = cplus_demangle (inp, DMGL_ANSI|DMGL_TYPES);
  288. if (result
  289. ? strcmp (result, expect.data)
  290. : strcmp (input.data, expect.data))
  291. {
  292. fail (lineno, format.data, input.data, result, expect.data);
  293. failures++;
  294. }
  295. free (result);
  296. }
  297. }
  298. free (format.data);
  299. free (input.data);
  300. free (expect.data);
  301. printf ("%s: %d tests, %d failures\n", argv[0], tests, failures);
  302. return failures ? 1 : 0;
  303. }