blob: 15e0c00240d62ea2764790590af57fd6700198d7 [file] [log] [blame]
/* Test program for read_[type]_unaligned.
Copyright (C) 2020, Red Hat Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
elfutils is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <assert.h>
#include <endian.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "../libdw/libdwP.h"
#include "../libdw/memory-access.h"
union u8
{
uint8_t v;
unsigned char c[1];
};
union s8
{
int8_t v;
unsigned char c[1];
};
union u16
{
uint16_t v;
unsigned char c[2];
};
union s16
{
int16_t v;
unsigned char c[2];
};
union u24
{
uint32_t v:24;
unsigned char c[3];
} __attribute__((packed));
union u32
{
uint32_t v;
unsigned char c[4];
};
union s32
{
int32_t v;
unsigned char c[4];
};
union u64
{
uint64_t v;
unsigned char c[8];
};
union s64
{
uint64_t v;
unsigned char c[8];
};
uint8_t u8_nums[] =
{
0,
1,
UINT8_MAX / 2 - 1,
UINT8_MAX / 2,
UINT8_MAX / 2 + 1,
UINT8_MAX,
UINT8_MAX -1
};
int8_t s8_nums[] =
{
INT8_MIN,
INT8_MIN + 1,
-1,
0,
1,
INT8_MAX,
INT8_MAX - 1
};
uint16_t u16_nums[] =
{
0,
1,
UINT16_MAX / 2 - 1,
UINT16_MAX / 2,
UINT16_MAX / 2 + 1,
UINT16_MAX,
UINT16_MAX -1
};
int16_t s16_nums[] =
{
INT16_MIN,
INT16_MIN + 1,
-1,
0,
1,
INT16_MAX,
INT16_MAX - 1
};
#define UINT24_MAX 0xffffff
uint32_t u24_nums[] =
{
0,
1,
UINT24_MAX / 2 - 1,
UINT24_MAX / 2,
UINT24_MAX / 2 + 1,
UINT24_MAX,
UINT24_MAX -1
};
uint32_t u32_nums[] =
{
0,
1,
UINT32_MAX / 2 - 1,
UINT32_MAX / 2,
UINT32_MAX / 2 + 1,
UINT32_MAX,
UINT32_MAX -1
};
int32_t s32_nums[] =
{
INT32_MIN,
INT32_MIN + 1,
-1,
0,
1,
INT32_MAX,
INT32_MAX - 1
};
uint64_t u64_nums[] =
{
0,
1,
UINT64_MAX / 2 - 1,
UINT64_MAX / 2,
UINT64_MAX / 2 + 1,
UINT64_MAX,
UINT64_MAX -1
};
int64_t s64_nums[] =
{
INT64_MIN,
INT64_MIN + 1,
-1,
0,
1,
INT64_MAX,
INT64_MAX - 1
};
static unsigned char le_mem[] =
{
/* u8 */
0x00,
0x01,
0x7e,
0x7f,
0x80,
0xff,
0xfe,
/* s8 */
0x80,
0x81,
0xff,
0x00,
0x01,
0x7f,
0x7e,
/* u16 */
0x00, 0x00,
0x01, 0x00,
0xfe, 0x7f,
0xff, 0x7f,
0x00, 0x80,
0xff, 0xff,
0xfe, 0xff,
/* s16 */
0x00, 0x80,
0x01, 0x80,
0xff, 0xff,
0x00, 0x00,
0x01, 0x00,
0xff, 0x7f,
0xfe, 0x7f,
/* u24 */
0x00, 0x00, 0x00,
0x01, 0x00, 0x00,
0xfe, 0xff, 0x7f,
0xff, 0xff, 0x7f,
0x00, 0x00, 0x80,
0xff, 0xff, 0xff,
0xfe, 0xff, 0xff,
/* u32 */
0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
0xfe, 0xff, 0xff, 0x7f,
0xff, 0xff, 0xff, 0x7f,
0x00, 0x00, 0x00, 0x80,
0xff, 0xff, 0xff, 0xff,
0xfe, 0xff, 0xff, 0xff,
/* s32 */
0x00, 0x00, 0x00, 0x80,
0x01, 0x00, 0x00, 0x80,
0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0x7f,
0xfe, 0xff, 0xff, 0x7f,
/* u64 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/* s64 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
};
static unsigned char be_mem[] =
{
/* u8 */
0x00,
0x01,
0x7e,
0x7f,
0x80,
0xff,
0xfe,
/* s8 */
0x80,
0x81,
0xff,
0x00,
0x01,
0x7f,
0x7e,
/* u16 */
0x00, 0x00,
0x00, 0x01,
0x7f, 0xfe,
0x7f, 0xff,
0x80, 0x00,
0xff, 0xff,
0xff, 0xfe,
/* s16 */
0x80, 0x00,
0x80, 0x01,
0xff, 0xff,
0x00, 0x00,
0x00, 0x01,
0x7f, 0xff,
0x7f, 0xfe,
/* u24 */
0x00, 0x00, 0x00,
0x00, 0x00, 0x01,
0x7f, 0xff, 0xfe,
0x7f, 0xff, 0xff,
0x80, 0x00, 0x00,
0xff, 0xff, 0xff,
0xff, 0xff, 0xfe,
/* u32 */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x7f, 0xff, 0xff, 0xfe,
0x7f, 0xff, 0xff, 0xff,
0x80, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe,
/* s32 */
0x80, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x01,
0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x7f, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xfe,
/* u64 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
/* s64 */
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
};
int
main (int argc, char **argv __attribute__((unused)))
{
/* No arguments means check, otherwise Write out the memory array. */
bool write = false;
if (argc > 1)
write = true;
bool is_le = (BYTE_ORDER == LITTLE_ENDIAN);
if (write)
{
if (is_le)
printf ("static unsigned char le_mem[] =\n");
else
printf ("static unsigned char be_mem[] =\n");
printf (" {\n");
}
Dwarf dbg_le = { .other_byte_order = !is_le };
Dwarf dbg_be = { .other_byte_order = is_le };
unsigned char *p_le = le_mem;
unsigned char *p_be = be_mem;
union u8 u8;
if (write)
printf (" /* u8 */\n");
for (size_t i = 0; i < sizeof (u8_nums) / sizeof (u8); i++)
{
if (write)
{
u8.v = u8_nums[i];
printf (" 0x%02" PRIx8 ",\n", u8.c[0]);
}
else
{
uint8_t v = *p_le++;
assert (v == u8_nums[i]);
v = *p_be++;
assert (v == u8_nums[i]);
}
}
union s8 s8;
if (write)
printf (" /* s8 */\n");
for (size_t i = 0; i < sizeof (s8_nums) / sizeof (s8); i++)
{
if (write)
{
s8.v = s8_nums[i];
printf (" 0x%02" PRIx8 ",\n", s8.c[0]);
}
else
{
int8_t v = *p_le++;
assert (v == s8_nums[i]);
v = *p_be++;
assert (v == s8_nums[i]);
}
}
union u16 u16;
if (write)
printf (" /* u16 */\n");
for (size_t i = 0; i < sizeof (u16_nums) / sizeof (u16); i++)
{
if (write)
{
u16.v = u16_nums[i];
printf (" 0x%02" PRIx8 ", ", u16.c[0]);
printf ("0x%02" PRIx8 ",\n", u16.c[1]);
}
else
{
uint16_t v = read_2ubyte_unaligned_inc (&dbg_le, p_le);
assert (v == u16_nums[i]);
v = read_2ubyte_unaligned_inc (&dbg_be, p_be);
assert (v == u16_nums[i]);
}
}
union s16 s16;
if (write)
printf (" /* s16 */\n");
for (size_t i = 0; i < sizeof (s16_nums) / sizeof (s16); i++)
{
if (write)
{
s16.v = s16_nums[i];
printf (" 0x%02" PRIx8 ", ", s16.c[0]);
printf ("0x%02" PRIx8 ",\n", s16.c[1]);
}
else
{
int16_t v = read_2sbyte_unaligned_inc (&dbg_le, p_le);
assert (v == s16_nums[i]);
v = read_2sbyte_unaligned_inc (&dbg_be, p_be);
assert (v == s16_nums[i]);
}
}
union u24 u24;
if (write)
printf (" /* u24 */\n");
for (size_t i = 0; i < sizeof (u24_nums) / sizeof (uint32_t); i++)
{
if (write)
{
u24.v = u24_nums[i];
printf (" 0x%02" PRIx8 ", ", u24.c[0]);
printf ("0x%02" PRIx8 ", ", u24.c[1]);
printf ("0x%02" PRIx8 ",\n", u24.c[2]);
}
else
{
uint32_t v = read_3ubyte_unaligned_inc (&dbg_le, p_le);
assert (v == u24_nums[i]);
v = read_3ubyte_unaligned_inc (&dbg_be, p_be);
assert (v == u24_nums[i]);
}
}
union u32 u32;
if (write)
printf (" /* u32 */\n");
for (size_t i = 0; i < sizeof (u32_nums) / sizeof (u32); i++)
{
if (write)
{
u32.v = u32_nums[i];
printf (" 0x%02" PRIx8 ", ", u32.c[0]);
printf ("0x%02" PRIx8 ", ", u32.c[1]);
printf ("0x%02" PRIx8 ", ", u32.c[2]);
printf ("0x%02" PRIx8 ",\n", u32.c[3]);
}
else
{
uint32_t v = read_4ubyte_unaligned_inc (&dbg_le, p_le);
assert (v == u32_nums[i]);
v = read_4ubyte_unaligned_inc (&dbg_be, p_be);
assert (v == u32_nums[i]);
}
}
union s32 s32;
if (write)
printf (" /* s32 */\n");
for (size_t i = 0; i < sizeof (s32_nums) / sizeof (s32); i++)
{
if (write)
{
s32.v = s32_nums[i];
printf (" 0x%02" PRIx8 ", ", s32.c[0]);
printf ("0x%02" PRIx8 ", ", s32.c[1]);
printf ("0x%02" PRIx8 ", ", s32.c[2]);
printf ("0x%02" PRIx8 ",\n", s32.c[3]);
}
else
{
int32_t v = read_4sbyte_unaligned_inc (&dbg_le, p_le);
assert (v == s32_nums[i]);
v = read_4sbyte_unaligned_inc (&dbg_be, p_be);
assert (v == s32_nums[i]);
}
}
union u64 u64;
if (write)
printf (" /* u64 */\n");
for (size_t i = 0; i < sizeof (u64_nums) / sizeof (u64); i++)
{
if (write)
{
u64.v = u64_nums[i];
printf (" 0x%02" PRIx8 ", ", u64.c[0]);
printf ("0x%02" PRIx8 ", ", u64.c[1]);
printf ("0x%02" PRIx8 ", ", u64.c[2]);
printf ("0x%02" PRIx8 ", ", u64.c[3]);
printf ("0x%02" PRIx8 ", ", u64.c[4]);
printf ("0x%02" PRIx8 ", ", u64.c[5]);
printf ("0x%02" PRIx8 ", ", u64.c[6]);
printf ("0x%02" PRIx8 ",\n", u64.c[7]);
}
else
{
uint64_t v = read_8ubyte_unaligned_inc (&dbg_le, p_le);
assert (v == u64_nums[i]);
v = read_8ubyte_unaligned_inc (&dbg_be, p_be);
assert (v == u64_nums[i]);
}
}
union s64 s64;
if (write)
printf (" /* s64 */\n");
for (size_t i = 0; i < sizeof (s64_nums) / sizeof (s64); i++)
{
if (write)
{
s64.v = s64_nums[i];
printf (" 0x%02" PRIx8 ", ", s64.c[0]);
printf ("0x%02" PRIx8 ", ", s64.c[1]);
printf ("0x%02" PRIx8 ", ", s64.c[2]);
printf ("0x%02" PRIx8 ", ", s64.c[3]);
printf ("0x%02" PRIx8 ", ", s64.c[4]);
printf ("0x%02" PRIx8 ", ", s64.c[5]);
printf ("0x%02" PRIx8 ", ", s64.c[6]);
printf ("0x%02" PRIx8 ",\n", s64.c[7]);
}
else
{
int64_t v = read_8sbyte_unaligned_inc (&dbg_le, p_le);
assert (v == s64_nums[i]);
v = read_8sbyte_unaligned_inc (&dbg_be, p_be);
assert (v == s64_nums[i]);
}
}
if (write)
printf (" };\n");
else
{
assert (p_le == le_mem + sizeof (le_mem));
assert (p_be == be_mem + sizeof (be_mem));
}
return 0;
}