1/* Test program for read_[type]_unaligned.
2   Copyright (C) 2020, Red Hat Inc.
3   This file is part of elfutils.
4
5   This file 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 3 of the License, or
8   (at your option) any later version.
9
10   elfutils is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18#include <assert.h>
19#include <endian.h>
20#include <inttypes.h>
21#include <stdbool.h>
22#include <stdint.h>
23#include <stdio.h>
24
25#include "../libdw/libdwP.h"
26#include "../libdw/memory-access.h"
27
28union u8
29{
30  uint8_t v;
31  unsigned char c[1];
32};
33
34union s8
35{
36  int8_t v;
37  unsigned char c[1];
38};
39
40union u16
41{
42  uint16_t v;
43  unsigned char c[2];
44};
45
46union s16
47{
48  int16_t v;
49  unsigned char c[2];
50};
51
52union u24
53{
54  uint32_t v:24;
55  unsigned char c[3];
56} __attribute__((packed));
57
58union u32
59{
60  uint32_t v;
61  unsigned char c[4];
62};
63
64union s32
65{
66  int32_t v;
67  unsigned char c[4];
68};
69
70union u64
71{
72  uint64_t v;
73  unsigned char c[8];
74};
75
76union s64
77{
78  uint64_t v;
79  unsigned char c[8];
80};
81
82uint8_t u8_nums[] =
83  {
84   0,
85   1,
86   UINT8_MAX / 2 - 1,
87   UINT8_MAX / 2,
88   UINT8_MAX / 2 + 1,
89   UINT8_MAX,
90   UINT8_MAX -1
91  };
92
93int8_t s8_nums[] =
94  {
95   INT8_MIN,
96   INT8_MIN + 1,
97   -1,
98   0,
99   1,
100   INT8_MAX,
101   INT8_MAX - 1
102  };
103
104uint16_t u16_nums[] =
105  {
106   0,
107   1,
108   UINT16_MAX / 2 - 1,
109   UINT16_MAX / 2,
110   UINT16_MAX / 2 + 1,
111   UINT16_MAX,
112   UINT16_MAX -1
113  };
114
115int16_t s16_nums[] =
116  {
117   INT16_MIN,
118   INT16_MIN + 1,
119   -1,
120   0,
121   1,
122   INT16_MAX,
123   INT16_MAX - 1
124  };
125
126#define UINT24_MAX 0xffffff
127
128uint32_t u24_nums[] =
129  {
130   0,
131   1,
132   UINT24_MAX / 2 - 1,
133   UINT24_MAX / 2,
134   UINT24_MAX / 2 + 1,
135   UINT24_MAX,
136   UINT24_MAX -1
137  };
138
139uint32_t u32_nums[] =
140  {
141   0,
142   1,
143   UINT32_MAX / 2 - 1,
144   UINT32_MAX / 2,
145   UINT32_MAX / 2 + 1,
146   UINT32_MAX,
147   UINT32_MAX -1
148  };
149
150int32_t s32_nums[] =
151  {
152   INT32_MIN,
153   INT32_MIN + 1,
154   -1,
155   0,
156   1,
157   INT32_MAX,
158   INT32_MAX - 1
159  };
160
161uint64_t u64_nums[] =
162  {
163   0,
164   1,
165   UINT64_MAX / 2 - 1,
166   UINT64_MAX / 2,
167   UINT64_MAX / 2 + 1,
168   UINT64_MAX,
169   UINT64_MAX -1
170  };
171
172int64_t s64_nums[] =
173  {
174   INT64_MIN,
175   INT64_MIN + 1,
176   -1,
177   0,
178   1,
179   INT64_MAX,
180   INT64_MAX - 1
181  };
182
183static unsigned char le_mem[] =
184  {
185    /* u8 */
186    0x00,
187    0x01,
188    0x7e,
189    0x7f,
190    0x80,
191    0xff,
192    0xfe,
193    /* s8 */
194    0x80,
195    0x81,
196    0xff,
197    0x00,
198    0x01,
199    0x7f,
200    0x7e,
201    /* u16 */
202    0x00, 0x00,
203    0x01, 0x00,
204    0xfe, 0x7f,
205    0xff, 0x7f,
206    0x00, 0x80,
207    0xff, 0xff,
208    0xfe, 0xff,
209    /* s16 */
210    0x00, 0x80,
211    0x01, 0x80,
212    0xff, 0xff,
213    0x00, 0x00,
214    0x01, 0x00,
215    0xff, 0x7f,
216    0xfe, 0x7f,
217    /* u24 */
218    0x00, 0x00, 0x00,
219    0x01, 0x00, 0x00,
220    0xfe, 0xff, 0x7f,
221    0xff, 0xff, 0x7f,
222    0x00, 0x00, 0x80,
223    0xff, 0xff, 0xff,
224    0xfe, 0xff, 0xff,
225    /* u32 */
226    0x00, 0x00, 0x00, 0x00,
227    0x01, 0x00, 0x00, 0x00,
228    0xfe, 0xff, 0xff, 0x7f,
229    0xff, 0xff, 0xff, 0x7f,
230    0x00, 0x00, 0x00, 0x80,
231    0xff, 0xff, 0xff, 0xff,
232    0xfe, 0xff, 0xff, 0xff,
233    /* s32 */
234    0x00, 0x00, 0x00, 0x80,
235    0x01, 0x00, 0x00, 0x80,
236    0xff, 0xff, 0xff, 0xff,
237    0x00, 0x00, 0x00, 0x00,
238    0x01, 0x00, 0x00, 0x00,
239    0xff, 0xff, 0xff, 0x7f,
240    0xfe, 0xff, 0xff, 0x7f,
241    /* u64 */
242    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244    0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
245    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
246    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
247    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
248    0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
249    /* s64 */
250    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
251    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
252    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
253    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
256    0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
257  };
258
259static unsigned char be_mem[] =
260  {
261    /* u8 */
262    0x00,
263    0x01,
264    0x7e,
265    0x7f,
266    0x80,
267    0xff,
268    0xfe,
269    /* s8 */
270    0x80,
271    0x81,
272    0xff,
273    0x00,
274    0x01,
275    0x7f,
276    0x7e,
277    /* u16 */
278    0x00, 0x00,
279    0x00, 0x01,
280    0x7f, 0xfe,
281    0x7f, 0xff,
282    0x80, 0x00,
283    0xff, 0xff,
284    0xff, 0xfe,
285    /* s16 */
286    0x80, 0x00,
287    0x80, 0x01,
288    0xff, 0xff,
289    0x00, 0x00,
290    0x00, 0x01,
291    0x7f, 0xff,
292    0x7f, 0xfe,
293    /* u24 */
294    0x00, 0x00, 0x00,
295    0x00, 0x00, 0x01,
296    0x7f, 0xff, 0xfe,
297    0x7f, 0xff, 0xff,
298    0x80, 0x00, 0x00,
299    0xff, 0xff, 0xff,
300    0xff, 0xff, 0xfe,
301    /* u32 */
302    0x00, 0x00, 0x00, 0x00,
303    0x00, 0x00, 0x00, 0x01,
304    0x7f, 0xff, 0xff, 0xfe,
305    0x7f, 0xff, 0xff, 0xff,
306    0x80, 0x00, 0x00, 0x00,
307    0xff, 0xff, 0xff, 0xff,
308    0xff, 0xff, 0xff, 0xfe,
309    /* s32 */
310    0x80, 0x00, 0x00, 0x00,
311    0x80, 0x00, 0x00, 0x01,
312    0xff, 0xff, 0xff, 0xff,
313    0x00, 0x00, 0x00, 0x00,
314    0x00, 0x00, 0x00, 0x01,
315    0x7f, 0xff, 0xff, 0xff,
316    0x7f, 0xff, 0xff, 0xfe,
317    /* u64 */
318    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
320    0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
321    0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
322    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
324    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
325    /* s64 */
326    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
328    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
329    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
331    0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
332    0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
333  };
334
335int
336main (int argc, char **argv __attribute__((unused)))
337{
338  /* No arguments means check, otherwise Write out the memory array.  */
339  bool write = false;
340  if (argc > 1)
341    write = true;
342
343  bool is_le = (BYTE_ORDER == LITTLE_ENDIAN);
344
345  if (write)
346    {
347      if (is_le)
348	printf ("static unsigned char le_mem[] =\n");
349      else
350	printf ("static unsigned char be_mem[] =\n");
351      printf ("  {\n");
352    }
353
354  Dwarf dbg_le = { .other_byte_order = !is_le };
355  Dwarf dbg_be = { .other_byte_order = is_le };
356
357  unsigned char *p_le = le_mem;
358  unsigned char *p_be = be_mem;
359
360  union u8 u8;
361  if (write)
362    printf ("    /* u8 */\n");
363  for (size_t i = 0; i < sizeof (u8_nums) / sizeof (u8); i++)
364    {
365      if (write)
366	{
367	  u8.v = u8_nums[i];
368	  printf ("    0x%02" PRIx8 ",\n", u8.c[0]);
369	}
370      else
371	{
372	  uint8_t v = *p_le++;
373	  assert (v == u8_nums[i]);
374	  v = *p_be++;
375	  assert (v == u8_nums[i]);
376	}
377    }
378
379  union s8 s8;
380  if (write)
381    printf ("    /* s8 */\n");
382  for (size_t i = 0; i < sizeof (s8_nums) / sizeof (s8); i++)
383    {
384      if (write)
385	{
386	  s8.v = s8_nums[i];
387	  printf ("    0x%02" PRIx8 ",\n", s8.c[0]);
388	}
389      else
390	{
391	  int8_t v = *p_le++;
392	  assert (v == s8_nums[i]);
393	  v = *p_be++;
394	  assert (v == s8_nums[i]);
395	}
396    }
397
398  union u16 u16;
399  if (write)
400    printf ("    /* u16 */\n");
401  for (size_t i = 0; i < sizeof (u16_nums) / sizeof (u16); i++)
402    {
403      if (write)
404	{
405	  u16.v = u16_nums[i];
406	  printf ("    0x%02" PRIx8 ", ", u16.c[0]);
407	  printf ("0x%02" PRIx8 ",\n", u16.c[1]);
408	}
409      else
410	{
411	  uint16_t v = read_2ubyte_unaligned_inc (&dbg_le, p_le);
412	  assert (v == u16_nums[i]);
413	  v = read_2ubyte_unaligned_inc (&dbg_be, p_be);
414	  assert (v == u16_nums[i]);
415	}
416    }
417
418  union s16 s16;
419  if (write)
420    printf ("    /* s16 */\n");
421  for (size_t i = 0; i < sizeof (s16_nums) / sizeof (s16); i++)
422    {
423      if (write)
424	{
425	  s16.v = s16_nums[i];
426	  printf ("    0x%02" PRIx8 ", ", s16.c[0]);
427	  printf ("0x%02" PRIx8 ",\n", s16.c[1]);
428	}
429      else
430	{
431	  int16_t v = read_2sbyte_unaligned_inc (&dbg_le, p_le);
432	  assert (v == s16_nums[i]);
433	  v = read_2sbyte_unaligned_inc (&dbg_be, p_be);
434	  assert (v == s16_nums[i]);
435	}
436    }
437
438  union u24 u24;
439  if (write)
440    printf ("    /* u24 */\n");
441  for (size_t i = 0; i < sizeof (u24_nums) / sizeof (uint32_t); i++)
442    {
443      if (write)
444	{
445	  u24.v = u24_nums[i];
446	  printf ("    0x%02" PRIx8 ", ", u24.c[0]);
447	  printf ("0x%02" PRIx8 ", ", u24.c[1]);
448	  printf ("0x%02" PRIx8 ",\n", u24.c[2]);
449	}
450      else
451	{
452	  uint32_t v = read_3ubyte_unaligned_inc (&dbg_le, p_le);
453	  assert (v == u24_nums[i]);
454	  v = read_3ubyte_unaligned_inc (&dbg_be, p_be);
455	  assert (v == u24_nums[i]);
456	}
457    }
458
459  union u32 u32;
460  if (write)
461    printf ("    /* u32 */\n");
462  for (size_t i = 0; i < sizeof (u32_nums) / sizeof (u32); i++)
463    {
464      if (write)
465	{
466	  u32.v = u32_nums[i];
467	  printf ("    0x%02" PRIx8 ", ", u32.c[0]);
468	  printf ("0x%02" PRIx8 ", ", u32.c[1]);
469	  printf ("0x%02" PRIx8 ", ", u32.c[2]);
470	  printf ("0x%02" PRIx8 ",\n", u32.c[3]);
471	}
472      else
473	{
474	  uint32_t v = read_4ubyte_unaligned_inc (&dbg_le, p_le);
475	  assert (v == u32_nums[i]);
476	  v = read_4ubyte_unaligned_inc (&dbg_be, p_be);
477	  assert (v == u32_nums[i]);
478	}
479    }
480
481  union s32 s32;
482  if (write)
483    printf ("    /* s32 */\n");
484  for (size_t i = 0; i < sizeof (s32_nums) / sizeof (s32); i++)
485    {
486      if (write)
487	{
488	  s32.v = s32_nums[i];
489	  printf ("    0x%02" PRIx8 ", ", s32.c[0]);
490	  printf ("0x%02" PRIx8 ", ", s32.c[1]);
491	  printf ("0x%02" PRIx8 ", ", s32.c[2]);
492	  printf ("0x%02" PRIx8 ",\n", s32.c[3]);
493	}
494      else
495	{
496	  int32_t v = read_4sbyte_unaligned_inc (&dbg_le, p_le);
497	  assert (v == s32_nums[i]);
498	  v = read_4sbyte_unaligned_inc (&dbg_be, p_be);
499	  assert (v == s32_nums[i]);
500	}
501    }
502
503  union u64 u64;
504  if (write)
505    printf ("    /* u64 */\n");
506  for (size_t i = 0; i < sizeof (u64_nums) / sizeof (u64); i++)
507    {
508      if (write)
509	{
510	  u64.v = u64_nums[i];
511	  printf ("    0x%02" PRIx8 ", ", u64.c[0]);
512	  printf ("0x%02" PRIx8 ", ", u64.c[1]);
513	  printf ("0x%02" PRIx8 ", ", u64.c[2]);
514	  printf ("0x%02" PRIx8 ", ", u64.c[3]);
515	  printf ("0x%02" PRIx8 ", ", u64.c[4]);
516	  printf ("0x%02" PRIx8 ", ", u64.c[5]);
517	  printf ("0x%02" PRIx8 ", ", u64.c[6]);
518	  printf ("0x%02" PRIx8 ",\n", u64.c[7]);
519	}
520      else
521	{
522	  uint64_t v = read_8ubyte_unaligned_inc (&dbg_le, p_le);
523	  assert (v == u64_nums[i]);
524	  v = read_8ubyte_unaligned_inc (&dbg_be, p_be);
525	  assert (v == u64_nums[i]);
526	}
527    }
528
529  union s64 s64;
530  if (write)
531    printf ("    /* s64 */\n");
532  for (size_t i = 0; i < sizeof (s64_nums) / sizeof (s64); i++)
533    {
534      if (write)
535	{
536	  s64.v = s64_nums[i];
537	  printf ("    0x%02" PRIx8 ", ", s64.c[0]);
538	  printf ("0x%02" PRIx8 ", ", s64.c[1]);
539	  printf ("0x%02" PRIx8 ", ", s64.c[2]);
540	  printf ("0x%02" PRIx8 ", ", s64.c[3]);
541	  printf ("0x%02" PRIx8 ", ", s64.c[4]);
542	  printf ("0x%02" PRIx8 ", ", s64.c[5]);
543	  printf ("0x%02" PRIx8 ", ", s64.c[6]);
544	  printf ("0x%02" PRIx8 ",\n", s64.c[7]);
545	}
546      else
547	{
548	  int64_t v = read_8sbyte_unaligned_inc (&dbg_le, p_le);
549	  assert (v == s64_nums[i]);
550	  v = read_8sbyte_unaligned_inc (&dbg_be, p_be);
551	  assert (v == s64_nums[i]);
552	}
553    }
554
555  if (write)
556    printf ("  };\n");
557  else
558    {
559      assert (p_le == le_mem + sizeof (le_mem));
560      assert (p_be == be_mem + sizeof (be_mem));
561    }
562
563  return 0;
564}
565