1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
/* Verify that name lookup of basic types including old-style bitfield types
yields the non-bitfield. */
#include <ctf-api.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
int bitfieldery (int count, int up, int pos)
{
unsigned char *ctf_written;
size_t size;
ctf_dict_t *dict;
const char *err = "opening";
int open_err;
ctf_encoding_t en;
ctf_encoding_t basic;
ctf_id_t type;
size_t i;
/* This is rendered annoying by two factors: old-style bitfields are not
generated by current compilers, so we need to build a suitable dict by
hand; and this is an open-time bug, so we need to serialize it and then
load it back in again. */
if ((dict = ctf_create (&open_err)) == NULL)
goto open_err;
/* Populate with a pile of bitfields of increasing/decreasing size, with a
single basic type dropped in at position POS. Oscillate the offset
between 0 and 1. */
basic.cte_bits = count;
basic.cte_offset = 0;
basic.cte_format = CTF_INT_SIGNED;
en.cte_bits = up ? 0 : count - 1;
en.cte_offset = 0;
en.cte_format = CTF_INT_SIGNED;
for (i = 0; i < count; i++)
{
if (i == pos)
{
err = "populating with basic type";
if (ctf_add_integer (dict, CTF_ADD_ROOT, "int", &basic) < 0)
goto err;
}
err = "populating";
if (ctf_add_integer (dict, CTF_ADD_ROOT, "int", &en) < 0)
goto err;
en.cte_bits += up ? 1 : -1;
if (en.cte_offset == 0)
en.cte_offset = 1;
else
en.cte_offset = 0;
}
/* Possibly populate with at-end basic type. */
if (i == pos)
{
err = "populating with basic type";
if (ctf_add_integer (dict, CTF_ADD_ROOT, "int", &basic) < 0)
goto err;
}
err = "writing";
if ((ctf_written = ctf_write_mem (dict, &size, 4096)) == NULL)
goto err;
ctf_dict_close (dict);
err = "opening";
if ((dict = ctf_simple_open ((char *) ctf_written, size, NULL, 0,
0, NULL, 0, &open_err)) == NULL)
goto open_err;
err = "looking up";
if ((type = ctf_lookup_by_name (dict, "int")) == CTF_ERR)
goto err;
err = "encoding check";
if (ctf_type_encoding (dict, type, &en) < 0)
goto err;
if (en.cte_bits < count || en.cte_offset != 0)
{
fprintf (stderr, "Name lookup with count %i, pos %i, counting %s "
"gave bitfield ID %lx with bits %i, offset %i\n", count, pos,
up ? "up" : "down", type, en.cte_bits, en.cte_offset);
return 1;
}
ctf_dict_close (dict);
free (ctf_written);
return 0;
open_err:
fprintf (stdout, "Error %s: %s\n", err, ctf_errmsg (open_err));
return 1;
err:
fprintf (stdout, "Error %s: %s\n", err, ctf_errmsg (ctf_errno (dict)));
return 1;
}
/* Do a bunch of tests with a type of a given size: up and down, basic type
at and near the start and end, and in the middle. */
void mass_bitfieldery (long size)
{
size *= 8;
bitfieldery (size, 1, 0);
bitfieldery (size, 0, 0);
bitfieldery (size, 1, 1);
bitfieldery (size, 0, 1);
bitfieldery (size, 1, size / 2);
bitfieldery (size, 0, size / 2);
bitfieldery (size, 1, size - 1);
bitfieldery (size, 0, size - 1);
bitfieldery (size, 1, size);
bitfieldery (size, 0, size);
}
int main (void)
{
mass_bitfieldery (sizeof (char));
mass_bitfieldery (sizeof (short));
mass_bitfieldery (sizeof (int));
mass_bitfieldery (sizeof (long));
mass_bitfieldery (sizeof (uint64_t));
printf ("All done.\n");
return 0;
}
|