aarch64: rcpc3: Add +rcpc3 architectural feature support flag
[platform/upstream/binutils.git] / libbacktrace / xztest.c
1 /* xztest.c -- Test for libbacktrace LZMA decoder.
2    Copyright (C) 2020-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 <limits.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <time.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43
44 #ifdef HAVE_LIBLZMA
45 #include <lzma.h>
46 #endif
47
48 #include "backtrace.h"
49 #include "backtrace-supported.h"
50
51 #include "internal.h"
52 #include "testlib.h"
53
54 #ifndef HAVE_CLOCK_GETTIME
55
56 typedef int xclockid_t;
57
58 static int
59 xclock_gettime (xclockid_t id ATTRIBUTE_UNUSED,
60                 struct timespec *ts ATTRIBUTE_UNUSED)
61 {
62   errno = EINVAL;
63   return -1;
64 }
65
66 #define clockid_t xclockid_t
67 #define clock_gettime xclock_gettime
68 #undef CLOCK_REALTIME
69 #define CLOCK_REALTIME 0
70
71 #endif /* !defined(HAVE_CLOCK_GETTIME) */
72
73 #ifdef CLOCK_PROCESS_CPUTIME_ID
74 #define LIBLZMA_CLOCK_GETTIME_ARG CLOCK_PROCESS_CPUTIME_ID
75 #else
76 #define LIBLZMA_CLOCK_GETTIME_ARG CLOCK_REALTIME
77 #endif
78
79 /* Some tests for the local lzma inflation code.  */
80
81 struct lzma_test
82 {
83   const char *name;
84   const char *uncompressed;
85   size_t uncompressed_len;
86   const char *compressed;
87   size_t compressed_len;
88 };
89
90 /* Error callback.  */
91
92 static void
93 error_callback_compress (void *vdata ATTRIBUTE_UNUSED, const char *msg,
94                          int errnum)
95 {
96   fprintf (stderr, "%s", msg);
97   if (errnum > 0)
98     fprintf (stderr, ": %s", strerror (errnum));
99   fprintf (stderr, "\n");
100   exit (EXIT_FAILURE);
101 }
102
103 static const struct lzma_test tests[] =
104 {
105   {
106     "empty",
107     "",
108     0,
109     ("\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x00\x00\x00\x00"
110      "\x1c\xdf\x44\x21\x1f\xb6\xf3\x7d\x01\x00\x00\x00\x00\x04\x59\x5a"),
111     32,
112   },
113   {
114     "hello",
115     "hello, world\n",
116     0,
117     ("\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21\x01"
118      "\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x0c\x68\x65\x6c\x6c\x6f"
119      "\x2c\x20\x77\x6f\x72\x6c\x64\x0a\x00\x00\x00\x00\x7b\x46\x5a\x81"
120      "\xc9\x12\xb8\xea\x00\x01\x25\x0d\x71\x19\xc4\xb6\x1f\xb6\xf3\x7d"
121      "\x01\x00\x00\x00\x00\x04\x59\x5a"),
122     72,
123   },
124   {
125     "goodbye",
126     "goodbye, world",
127     0,
128     ("\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21\x01"
129      "\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x0d\x67\x6f\x6f\x64\x62"
130      "\x79\x65\x2c\x20\x77\x6f\x72\x6c\x64\x00\x00\x00\xf6\xf8\xa3\x33"
131      "\x8c\x4e\xc9\x68\x00\x01\x26\x0e\x08\x1b\xe0\x04\x1f\xb6\xf3\x7d"
132      "\x01\x00\x00\x00\x00\x04\x59\x5a"),
133     72,
134   },
135 };
136
137 /* Test the hand coded samples.  */
138
139 static void
140 test_samples (struct backtrace_state *state)
141 {
142   size_t i;
143
144   for (i = 0; i < sizeof tests / sizeof tests[0]; ++i)
145     {
146       unsigned char *uncompressed;
147       size_t uncompressed_len;
148
149       uncompressed = NULL;
150       uncompressed_len = 0;
151       if (!backtrace_uncompress_lzma (state,
152                                       ((const unsigned char *)
153                                        tests[i].compressed),
154                                       tests[i].compressed_len,
155                                       error_callback_compress, NULL,
156                                       &uncompressed, &uncompressed_len))
157         {
158           fprintf (stderr, "test %s: uncompress failed\n", tests[i].name);
159           ++failures;
160         }
161       else
162         {
163           size_t v;
164
165           v = tests[i].uncompressed_len;
166           if (v == 0)
167             v = strlen (tests[i].uncompressed);
168           if (uncompressed_len != v)
169             {
170               fprintf (stderr,
171                        "test %s: got uncompressed length %zu, want %zu\n",
172                        tests[i].name, uncompressed_len, v);
173               ++failures;
174             }
175           else if (v > 0 && memcmp (tests[i].uncompressed, uncompressed, v) != 0)
176             {
177               size_t j;
178
179               fprintf (stderr, "test %s: uncompressed data mismatch\n",
180                        tests[i].name);
181               for (j = 0; j < v; ++j)
182                 if (tests[i].uncompressed[j] != uncompressed[j])
183                   fprintf (stderr, "  %zu: got %#x want %#x\n", j,
184                            uncompressed[j], tests[i].uncompressed[j]);
185               ++failures;
186             }
187           else
188             printf ("PASS: lzma %s\n", tests[i].name);
189
190           backtrace_free (state, uncompressed, uncompressed_len,
191                           error_callback_compress, NULL);
192         }
193     }
194 }
195
196 #if HAVE_LIBLZMA
197
198 /* Given a set of TRIALS timings, discard the lowest and highest
199    values and return the mean average of the rest.  */
200
201 static size_t
202 average_time (const size_t *times, size_t trials)
203 {
204   size_t imax;
205   size_t max;
206   size_t imin;
207   size_t min;
208   size_t i;
209   size_t sum;
210
211   imin = 0;
212   imax = 0;
213   min = times[0];
214   max = times[0];
215   for (i = 1; i < trials; ++i)
216     {
217       if (times[i] < min)
218         {
219           imin = i;
220           min = times[i];
221         }
222       if (times[i] > max)
223         {
224           imax = i;
225           max = times[i];
226         }
227     }
228
229   sum = 0;
230   for (i = 0; i < trials; ++i)
231     {
232       if (i != imax && i != imin)
233         sum += times[i];
234     }
235   return sum / (trials - 2);
236 }
237
238 #endif
239
240 /* Test a larger text, if available.  */
241
242 static void
243 test_large (struct backtrace_state *state ATTRIBUTE_UNUSED)
244 {
245 #if HAVE_LIBLZMA
246   unsigned char *orig_buf;
247   size_t orig_bufsize;
248   size_t i;
249   lzma_stream initial_stream = LZMA_STREAM_INIT;
250   lzma_stream stream;
251   unsigned char *compressed_buf;
252   size_t compressed_bufsize;
253   unsigned char *uncompressed_buf;
254   size_t uncompressed_bufsize;
255   unsigned char *spare_buf;
256   int r;
257   clockid_t cid;
258   struct timespec ts1;
259   struct timespec ts2;
260   size_t ctime;
261   size_t ztime;
262   const size_t trials = 16;
263   size_t ctimes[16];
264   size_t ztimes[16];
265   static const char * const names[] = {
266     "Isaac.Newton-Opticks.txt",
267     "../libgo/go/testdata/Isaac.Newton-Opticks.txt",
268   };
269
270   orig_buf = NULL;
271   orig_bufsize = 0;
272   uncompressed_buf = NULL;
273   compressed_buf = NULL;
274
275   for (i = 0; i < sizeof names / sizeof names[0]; ++i)
276     {
277       size_t len;
278       char *namebuf;
279       FILE *e;
280       struct stat st;
281       char *rbuf;
282       size_t got;
283
284       len = strlen (SRCDIR) + strlen (names[i]) + 2;
285       namebuf = malloc (len);
286       if (namebuf == NULL)
287         {
288           perror ("malloc");
289           goto fail;
290         }
291       snprintf (namebuf, len, "%s/%s", SRCDIR, names[i]);
292       e = fopen (namebuf, "r");
293       free (namebuf);
294       if (e == NULL)
295         continue;
296       if (fstat (fileno (e), &st) < 0)
297         {
298           perror ("fstat");
299           fclose (e);
300           continue;
301         }
302       rbuf = malloc (st.st_size);
303       if (rbuf == NULL)
304         {
305           perror ("malloc");
306           goto fail;
307         }
308       got = fread (rbuf, 1, st.st_size, e);
309       fclose (e);
310       if (got > 0)
311         {
312           orig_buf = (unsigned char *) rbuf;
313           orig_bufsize = got;
314           break;
315         }
316       free (rbuf);
317     }
318
319   if (orig_buf == NULL)
320     {
321       /* We couldn't find an input file.  */
322       printf ("UNSUPPORTED: lzma large\n");
323       return;
324     }
325
326   stream = initial_stream;
327   r =  lzma_easy_encoder (&stream, 6, LZMA_CHECK_CRC32);
328   if (r != LZMA_OK)
329     {
330       fprintf (stderr, "lzma_easy_encoder failed: %d\n", r);
331       goto fail;
332     }
333
334   compressed_bufsize = orig_bufsize + 100;
335   compressed_buf = malloc (compressed_bufsize);
336   if (compressed_buf == NULL)
337     {
338       perror ("malloc");
339       goto fail;
340     }
341
342   stream.next_in = orig_buf;
343   stream.avail_in = orig_bufsize;
344   stream.next_out = compressed_buf;
345   stream.avail_out = compressed_bufsize;
346
347   do
348     {
349       r = lzma_code (&stream, LZMA_FINISH);
350       if (r != LZMA_OK && r != LZMA_STREAM_END)
351         {
352           fprintf (stderr, "lzma_code failed: %d\n", r);
353           goto fail;
354         }
355     }
356   while (r != LZMA_STREAM_END);
357
358   compressed_bufsize = stream.total_out;
359
360   if (!backtrace_uncompress_lzma (state, (unsigned char *) compressed_buf,
361                                   compressed_bufsize,
362                                   error_callback_compress, NULL,
363                                   &uncompressed_buf, &uncompressed_bufsize))
364     {
365       fprintf (stderr, "lzma large: backtrace_uncompress_lzma failed\n");
366       goto fail;
367     }
368
369   if (uncompressed_bufsize != orig_bufsize)
370     {
371       fprintf (stderr,
372                "lzma large: got uncompressed length %zu, want %zu\n",
373                uncompressed_bufsize, orig_bufsize);
374       goto fail;
375     }
376
377   if (memcmp (uncompressed_buf, orig_buf, uncompressed_bufsize) != 0)
378     {
379       fprintf (stderr, "lzma large: uncompressed data mismatch\n");
380       goto fail;
381     }
382
383   printf ("PASS: lzma large\n");
384
385   spare_buf = malloc (orig_bufsize);
386   if (spare_buf == NULL)
387     {
388       perror ("malloc");
389       goto fail;
390     }
391
392   for (i = 0; i < trials; ++i)
393     {
394       cid = LIBLZMA_CLOCK_GETTIME_ARG;
395       if (clock_gettime (cid, &ts1) < 0)
396         {
397           if (errno == EINVAL)
398             return;
399           perror ("clock_gettime");
400           return;
401         }
402
403       if (!backtrace_uncompress_lzma (state,
404                                       (unsigned char *) compressed_buf,
405                                       compressed_bufsize,
406                                       error_callback_compress, NULL,
407                                       &uncompressed_buf,
408                                       &uncompressed_bufsize))
409         {
410           fprintf (stderr,
411                    ("lzma large: "
412                     "benchmark backtrace_uncompress_lzma failed\n"));
413           return;
414         }
415
416       if (clock_gettime (cid, &ts2) < 0)
417         {
418           perror ("clock_gettime");
419           return;
420         }
421
422       ctime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
423       ctime += ts2.tv_nsec - ts1.tv_nsec;
424       ctimes[i] = ctime;
425
426       stream = initial_stream;
427
428       r = lzma_auto_decoder (&stream, UINT64_MAX, 0);
429       if (r != LZMA_OK)
430         {
431           fprintf (stderr, "lzma_stream_decoder failed: %d\n", r);
432           goto fail;
433         }
434
435       stream.next_in = compressed_buf;
436       stream.avail_in = compressed_bufsize;
437       stream.next_out = spare_buf;
438       stream.avail_out = orig_bufsize;
439
440       if (clock_gettime (cid, &ts1) < 0)
441         {
442           perror("clock_gettime");
443           return;
444         }
445
446       do
447         {
448           r = lzma_code (&stream, LZMA_FINISH);
449           if (r != LZMA_OK && r != LZMA_STREAM_END)
450             {
451               fprintf (stderr, "lzma_code failed: %d\n", r);
452               goto fail;
453             }
454         }
455       while (r != LZMA_STREAM_END);
456
457       if (clock_gettime (cid, &ts2) < 0)
458         {
459           perror ("clock_gettime");
460           return;
461         }
462
463       ztime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
464       ztime += ts2.tv_nsec - ts1.tv_nsec;
465       ztimes[i] = ztime;
466     }
467
468   /* Toss the highest and lowest times and average the rest.  */
469   ctime = average_time (ctimes, trials);
470   ztime = average_time (ztimes, trials);
471
472   printf ("backtrace: %zu ns\n", ctime);
473   printf ("liblzma  : %zu ns\n", ztime);
474   printf ("ratio    : %g\n", (double) ztime / (double) ctime);
475
476   return;
477
478  fail:
479   printf ("FAIL: lzma large\n");
480   ++failures;
481
482   if (orig_buf != NULL)
483     free (orig_buf);
484   if (compressed_buf != NULL)
485     free (compressed_buf);
486   if (uncompressed_buf != NULL)
487     free (uncompressed_buf);
488
489 #else /* !HAVE_LIBLZMA */
490
491  printf ("UNSUPPORTED: lzma large\n");
492
493 #endif /* !HAVE_LIBLZMA */
494 }
495
496 int
497 main (int argc ATTRIBUTE_UNUSED, char **argv)
498 {
499   struct backtrace_state *state;
500
501   state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
502                                   error_callback_create, NULL);
503
504   test_samples (state);
505   test_large (state);
506
507   exit (failures != 0 ? EXIT_FAILURE : EXIT_SUCCESS);
508 }