565 lines
11 KiB
C
565 lines
11 KiB
C
/* 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;
|
|
}
|