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