aarch64: rcpc3: Add +rcpc3 architectural feature support flag
[platform/upstream/binutils.git] / libbacktrace / ztest.c
1 /* ztest.c -- Test for libbacktrace inflate code.
2    Copyright (C) 2017-2021 Free Software Foundation, Inc.
3    Written by Ian Lance Taylor, Google.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9     (1) Redistributions of source code must retain the above copyright
10     notice, this list of conditions and the following disclaimer.
11
12     (2) Redistributions in binary form must reproduce the above copyright
13     notice, this list of conditions and the following disclaimer in
14     the documentation and/or other materials provided with the
15     distribution.
16
17     (3) The name of the author may not be used to
18     endorse or promote products derived from this software without
19     specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE.  */
32
33 #include "config.h"
34
35 #include <errno.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <time.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42
43 #ifdef HAVE_ZLIB
44 #include <zlib.h>
45 #endif
46
47 #include "backtrace.h"
48 #include "backtrace-supported.h"
49
50 #include "internal.h"
51 #include "testlib.h"
52
53 #ifndef HAVE_CLOCK_GETTIME
54
55 typedef int xclockid_t;
56
57 static int
58 xclock_gettime (xclockid_t id ATTRIBUTE_UNUSED,
59                 struct timespec *ts ATTRIBUTE_UNUSED)
60 {
61   errno = EINVAL;
62   return -1;
63 }
64
65 #define clockid_t xclockid_t
66 #define clock_gettime xclock_gettime
67 #undef CLOCK_REALTIME
68 #define CLOCK_REALTIME 0
69
70 #endif /* !defined(HAVE_CLOCK_GETTIME) */
71
72 #ifdef CLOCK_PROCESS_CPUTIME_ID
73 #define ZLIB_CLOCK_GETTIME_ARG CLOCK_PROCESS_CPUTIME_ID
74 #else
75 #define ZLIB_CLOCK_GETTIME_ARG CLOCK_REALTIME
76 #endif
77
78 /* Some tests for the local zlib inflation code.  */
79
80 struct zlib_test
81 {
82   const char *name;
83   const char *uncompressed;
84   size_t uncompressed_len;
85   const char *compressed;
86   size_t compressed_len;
87 };
88
89 /* Error callback.  */
90
91 static void
92 error_callback_compress (void *vdata ATTRIBUTE_UNUSED, const char *msg,
93                          int errnum)
94 {
95   fprintf (stderr, "%s", msg);
96   if (errnum > 0)
97     fprintf (stderr, ": %s", strerror (errnum));
98   fprintf (stderr, "\n");
99   exit (EXIT_FAILURE);
100 }
101
102 static const struct zlib_test tests[] =
103 {
104   {
105     "empty",
106     "",
107     0,
108     "\x78\x9c\x03\x00\x00\x00\x00\x01",
109     8,
110   },
111   {
112     "hello",
113     "hello, world\n",
114     0,
115     ("\x78\x9c\xca\x48\xcd\xc9\xc9\xd7\x51\x28\xcf"
116      "\x2f\xca\x49\xe1\x02\x04\x00\x00\xff\xff\x21\xe7\x04\x93"),
117     25,
118   },
119   {
120     "goodbye",
121     "goodbye, world",
122     0,
123     ("\x78\x9c\x4b\xcf\xcf\x4f\x49\xaa"
124      "\x4c\xd5\x51\x28\xcf\x2f\xca\x49"
125      "\x01\x00\x28\xa5\x05\x5e"),
126     22,
127   },
128   {
129     "ranges",
130     ("\xcc\x11\x00\x00\x00\x00\x00\x00\xd5\x13\x00\x00\x00\x00\x00\x00"
131      "\x1c\x14\x00\x00\x00\x00\x00\x00\x72\x14\x00\x00\x00\x00\x00\x00"
132      "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
133      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
134      "\xfb\x12\x00\x00\x00\x00\x00\x00\x09\x13\x00\x00\x00\x00\x00\x00"
135      "\x0c\x13\x00\x00\x00\x00\x00\x00\xcb\x13\x00\x00\x00\x00\x00\x00"
136      "\x29\x14\x00\x00\x00\x00\x00\x00\x4e\x14\x00\x00\x00\x00\x00\x00"
137      "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
138      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
139      "\xfb\x12\x00\x00\x00\x00\x00\x00\x09\x13\x00\x00\x00\x00\x00\x00"
140      "\x67\x13\x00\x00\x00\x00\x00\x00\xcb\x13\x00\x00\x00\x00\x00\x00"
141      "\x9d\x14\x00\x00\x00\x00\x00\x00\xd5\x14\x00\x00\x00\x00\x00\x00"
142      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
143      "\x5f\x0b\x00\x00\x00\x00\x00\x00\x6c\x0b\x00\x00\x00\x00\x00\x00"
144      "\x7d\x0b\x00\x00\x00\x00\x00\x00\x7e\x0c\x00\x00\x00\x00\x00\x00"
145      "\x38\x0f\x00\x00\x00\x00\x00\x00\x5c\x0f\x00\x00\x00\x00\x00\x00"
146      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
147      "\x83\x0c\x00\x00\x00\x00\x00\x00\xfa\x0c\x00\x00\x00\x00\x00\x00"
148      "\xfd\x0d\x00\x00\x00\x00\x00\x00\xef\x0e\x00\x00\x00\x00\x00\x00"
149      "\x14\x0f\x00\x00\x00\x00\x00\x00\x38\x0f\x00\x00\x00\x00\x00\x00"
150      "\x9f\x0f\x00\x00\x00\x00\x00\x00\xac\x0f\x00\x00\x00\x00\x00\x00"
151      "\xdb\x0f\x00\x00\x00\x00\x00\x00\xff\x0f\x00\x00\x00\x00\x00\x00"
152      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
153      "\xfd\x0d\x00\x00\x00\x00\x00\x00\xd8\x0e\x00\x00\x00\x00\x00\x00"
154      "\x9f\x0f\x00\x00\x00\x00\x00\x00\xac\x0f\x00\x00\x00\x00\x00\x00"
155      "\xdb\x0f\x00\x00\x00\x00\x00\x00\xff\x0f\x00\x00\x00\x00\x00\x00"
156      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
157      "\xfa\x0c\x00\x00\x00\x00\x00\x00\xea\x0d\x00\x00\x00\x00\x00\x00"
158      "\xef\x0e\x00\x00\x00\x00\x00\x00\x14\x0f\x00\x00\x00\x00\x00\x00"
159      "\x5c\x0f\x00\x00\x00\x00\x00\x00\x9f\x0f\x00\x00\x00\x00\x00\x00"
160      "\xac\x0f\x00\x00\x00\x00\x00\x00\xdb\x0f\x00\x00\x00\x00\x00\x00"
161      "\xff\x0f\x00\x00\x00\x00\x00\x00\x2c\x10\x00\x00\x00\x00\x00\x00"
162      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
163      "\x60\x11\x00\x00\x00\x00\x00\x00\xd1\x16\x00\x00\x00\x00\x00\x00"
164      "\x40\x0b\x00\x00\x00\x00\x00\x00\x2c\x10\x00\x00\x00\x00\x00\x00"
165      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
166      "\x7a\x00\x00\x00\x00\x00\x00\x00\xb6\x00\x00\x00\x00\x00\x00\x00"
167      "\x9f\x01\x00\x00\x00\x00\x00\x00\xa7\x01\x00\x00\x00\x00\x00\x00"
168      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
169      "\x7a\x00\x00\x00\x00\x00\x00\x00\xa9\x00\x00\x00\x00\x00\x00\x00"
170      "\x9f\x01\x00\x00\x00\x00\x00\x00\xa7\x01\x00\x00\x00\x00\x00\x00"
171      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"),
172     672,
173     ("\x78\x9c\x3b\x23\xc8\x00\x06\x57\x85\x21\xb4\x8c\x08\x84\x2e\x82"
174      "\xd2\x73\xa1\xf4\x55\x28\x8d\x0e\x7e\x0b\x41\x68\x4e\xa8\x7e\x1e"
175      "\x28\x7d\x1a\x4a\x6b\x42\xf5\xf9\x91\x69\x5e\x3a\x9a\x79\x84\xf4"
176      "\xc7\x73\x43\xe8\x1c\x28\x5d\x0b\xa5\xeb\x78\x20\xb4\x05\x3f\x84"
177      "\x8e\xe1\xc7\xae\xbf\x19\xaa\xee\x17\x94\xfe\xcb\x0b\xa1\xdf\xf3"
178      "\x41\x68\x11\x7e\x54\x73\xe6\x43\xe9\x35\x50\xfa\x36\x94\xfe\x8f"
179      "\xc3\x7c\x98\x79\x37\xf8\xc8\xd3\x0f\x73\xd7\x2b\x1c\xee\x8a\x21"
180      "\xd2\x5d\x3a\x02\xd8\xcd\x4f\x80\xa6\x87\x8b\x62\x10\xda\x81\x1b"
181      "\xbf\xfa\x2a\x28\xbd\x0d\x4a\xcf\x67\x84\xd0\xcb\x19\xf1\xab\x5f"
182      "\x49\xa4\x7a\x00\x48\x97\x29\xd4"),
183     152,
184   }
185 };
186
187 /* Test the hand coded samples.  */
188
189 static void
190 test_samples (struct backtrace_state *state)
191 {
192   size_t i;
193
194   for (i = 0; i < sizeof tests / sizeof tests[0]; ++i)
195     {
196       char *p;
197       size_t v;
198       size_t j;
199       unsigned char *uncompressed;
200       size_t uncompressed_len;
201
202       p = malloc (12 + tests[i].compressed_len);
203       memcpy (p, "ZLIB", 4);
204       v = tests[i].uncompressed_len;
205       if (v == 0)
206         v = strlen (tests[i].uncompressed);
207       for (j = 0; j < 8; ++j)
208         p[j + 4] = (v >> ((7 - j) * 8)) & 0xff;
209       memcpy (p + 12, tests[i].compressed, tests[i].compressed_len);
210       uncompressed = NULL;
211       uncompressed_len = 0;
212       if (!backtrace_uncompress_zdebug (state, (unsigned char *) p,
213                                         tests[i].compressed_len + 12,
214                                         error_callback_compress, NULL,
215                                         &uncompressed, &uncompressed_len))
216         {
217           fprintf (stderr, "test %s: uncompress failed\n", tests[i].name);
218           ++failures;
219         }
220       else
221         {
222           if (uncompressed_len != v)
223             {
224               fprintf (stderr,
225                        "test %s: got uncompressed length %zu, want %zu\n",
226                        tests[i].name, uncompressed_len, v);
227               ++failures;
228             }
229           else if (memcmp (tests[i].uncompressed, uncompressed, v) != 0)
230             {
231               size_t j;
232
233               fprintf (stderr, "test %s: uncompressed data mismatch\n",
234                        tests[i].name);
235               for (j = 0; j < v; ++j)
236                 if (tests[i].uncompressed[j] != uncompressed[j])
237                   fprintf (stderr, "  %zu: got %#x want %#x\n", j,
238                            uncompressed[j], tests[i].uncompressed[j]);
239               ++failures;
240             }
241           else
242             printf ("PASS: inflate %s\n", tests[i].name);
243
244           backtrace_free (state, uncompressed, uncompressed_len,
245                           error_callback_compress, NULL);
246         }
247     }
248 }
249
250 #ifdef HAVE_ZLIB
251
252 /* Given a set of TRIALS timings, discard the lowest and highest
253    values and return the mean average of the rest.  */
254
255 static size_t
256 average_time (const size_t *times, size_t trials)
257 {
258   size_t imax;
259   size_t max;
260   size_t imin;
261   size_t min;
262   size_t i;
263   size_t sum;
264
265   imin = 0;
266   imax = 0;
267   min = times[0];
268   max = times[0];
269   for (i = 1; i < trials; ++i)
270     {
271       if (times[i] < min)
272         {
273           imin = i;
274           min = times[i];
275         }
276       if (times[i] > max)
277         {
278           imax = i;
279           max = times[i];
280         }
281     }
282
283   sum = 0;
284   for (i = 0; i < trials; ++i)
285     {
286       if (i != imax && i != imin)
287         sum += times[i];
288     }
289   return sum / (trials - 2);
290 }
291
292 #endif
293
294 /* Test a larger text, if available.  */
295
296 static void
297 test_large (struct backtrace_state *state ATTRIBUTE_UNUSED)
298 {
299 #ifdef HAVE_ZLIB
300   unsigned char *orig_buf;
301   size_t orig_bufsize;
302   size_t i;
303   char *compressed_buf;
304   size_t compressed_bufsize;
305   unsigned long compress_sizearg;
306   unsigned char *uncompressed_buf;
307   size_t uncompressed_bufsize;
308   int r;
309   clockid_t cid;
310   struct timespec ts1;
311   struct timespec ts2;
312   size_t ctime;
313   size_t ztime;
314   const size_t trials = 16;
315   size_t ctimes[16];
316   size_t ztimes[16];
317   static const char * const names[] = {
318     "Isaac.Newton-Opticks.txt",
319     "../libgo/go/testdata/Isaac.Newton-Opticks.txt",
320   };
321
322   orig_buf = NULL;
323   orig_bufsize = 0;
324   uncompressed_buf = NULL;
325   compressed_buf = NULL;
326
327   for (i = 0; i < sizeof names / sizeof names[0]; ++i)
328     {
329       size_t len;
330       char *namebuf;
331       FILE *e;
332       struct stat st;
333       char *rbuf;
334       size_t got;
335
336       len = strlen (SRCDIR) + strlen (names[i]) + 2;
337       namebuf = malloc (len);
338       if (namebuf == NULL)
339         {
340           perror ("malloc");
341           goto fail;
342         }
343       snprintf (namebuf, len, "%s/%s", SRCDIR, names[i]);
344       e = fopen (namebuf, "r");
345       free (namebuf);
346       if (e == NULL)
347         continue;
348       if (fstat (fileno (e), &st) < 0)
349         {
350           perror ("fstat");
351           fclose (e);
352           continue;
353         }
354       rbuf = malloc (st.st_size);
355       if (rbuf == NULL)
356         {
357           perror ("malloc");
358           goto fail;
359         }
360       got = fread (rbuf, 1, st.st_size, e);
361       fclose (e);
362       if (got > 0)
363         {
364           orig_buf = (unsigned char *) rbuf;
365           orig_bufsize = got;
366           break;
367         }
368       free (rbuf);
369     }
370
371   if (orig_buf == NULL)
372     {
373       /* We couldn't find an input file.  */
374       printf ("UNSUPPORTED: inflate large\n");
375       return;
376     }
377
378   compressed_bufsize = compressBound (orig_bufsize) + 12;
379   compressed_buf = malloc (compressed_bufsize);
380   if (compressed_buf == NULL)
381     {
382       perror ("malloc");
383       goto fail;
384     }
385
386   compress_sizearg = compressed_bufsize - 12;
387   r = compress ((unsigned char *) compressed_buf + 12, &compress_sizearg,
388                 orig_buf, orig_bufsize);
389   if (r != Z_OK)
390     {
391       fprintf (stderr, "zlib compress failed: %d\n", r);
392       goto fail;
393     }
394
395   compressed_bufsize = compress_sizearg + 12;
396
397   /* Prepare the header that our library expects.  */
398   memcpy (compressed_buf, "ZLIB", 4);
399   for (i = 0; i < 8; ++i)
400     compressed_buf[i + 4] = (orig_bufsize >> ((7 - i) * 8)) & 0xff;
401
402   uncompressed_buf = malloc (orig_bufsize);
403   if (uncompressed_buf == NULL)
404     {
405       perror ("malloc");
406       goto fail;
407     }
408   uncompressed_bufsize = orig_bufsize;
409
410   if (!backtrace_uncompress_zdebug (state, (unsigned char *) compressed_buf,
411                                     compressed_bufsize,
412                                     error_callback_compress, NULL,
413                                     &uncompressed_buf, &uncompressed_bufsize))
414     {
415       fprintf (stderr, "inflate large: backtrace_uncompress_zdebug failed\n");
416       goto fail;
417     }
418
419   if (uncompressed_bufsize != orig_bufsize)
420     {
421       fprintf (stderr,
422                "inflate large: got uncompressed length %zu, want %zu\n",
423                uncompressed_bufsize, orig_bufsize);
424       goto fail;
425     }
426
427   if (memcmp (uncompressed_buf, orig_buf, uncompressed_bufsize) != 0)
428     {
429       fprintf (stderr, "inflate large: uncompressed data mismatch\n");
430       goto fail;
431     }
432
433   printf ("PASS: inflate large\n");
434
435   for (i = 0; i < trials; ++i)
436     {
437       unsigned long uncompress_sizearg;
438
439       cid = ZLIB_CLOCK_GETTIME_ARG;
440       if (clock_gettime (cid, &ts1) < 0)
441         {
442           if (errno == EINVAL)
443             return;
444           perror ("clock_gettime");
445           return;
446         }
447
448       if (!backtrace_uncompress_zdebug (state,
449                                         (unsigned char *) compressed_buf,
450                                         compressed_bufsize,
451                                         error_callback_compress, NULL,
452                                         &uncompressed_buf,
453                                         &uncompressed_bufsize))
454         {
455           fprintf (stderr,
456                    ("inflate large: "
457                     "benchmark backtrace_uncompress_zdebug failed\n"));
458           return;
459         }
460
461       if (clock_gettime (cid, &ts2) < 0)
462         {
463           perror ("clock_gettime");
464           return;
465         }
466
467       ctime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
468       ctime += ts2.tv_nsec - ts1.tv_nsec;
469       ctimes[i] = ctime;
470
471       if (clock_gettime (cid, &ts1) < 0)
472         {
473           perror("clock_gettime");
474           return;
475         }
476
477       uncompress_sizearg = uncompressed_bufsize;
478       r = uncompress ((unsigned char *) uncompressed_buf, &uncompress_sizearg,
479                       (unsigned char *) compressed_buf + 12,
480                       compressed_bufsize - 12);
481
482       if (clock_gettime (cid, &ts2) < 0)
483         {
484           perror ("clock_gettime");
485           return;
486         }
487
488       if (r != Z_OK)
489         {
490           fprintf (stderr,
491                    "inflate large: benchmark zlib uncompress failed: %d\n",
492                    r);
493           return;
494         }
495
496       ztime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
497       ztime += ts2.tv_nsec - ts1.tv_nsec;
498       ztimes[i] = ztime;
499     }
500
501   /* Toss the highest and lowest times and average the rest.  */
502   ctime = average_time (ctimes, trials);
503   ztime = average_time (ztimes, trials);
504
505   printf ("backtrace: %zu ns\n", ctime);
506   printf ("zlib     : %zu ns\n", ztime);
507   printf ("ratio    : %g\n", (double) ztime / (double) ctime);
508
509   return;
510
511  fail:
512   printf ("FAIL: inflate large\n");
513   ++failures;
514
515   if (orig_buf != NULL)
516     free (orig_buf);
517   if (compressed_buf != NULL)
518     free (compressed_buf);
519   if (uncompressed_buf != NULL)
520     free (uncompressed_buf);
521
522 #else /* !HAVE_ZLIB */
523
524  printf ("UNSUPPORTED: inflate large\n");
525
526 #endif /* !HAVE_ZLIB */
527 }
528
529 int
530 main (int argc ATTRIBUTE_UNUSED, char **argv)
531 {
532   struct backtrace_state *state;
533
534   state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
535                                   error_callback_create, NULL);
536
537   test_samples (state);
538   test_large (state);
539
540   exit (failures != 0 ? EXIT_FAILURE : EXIT_SUCCESS);
541 }