/* 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 . */ #include #include #include #include #include #include #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; }