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 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
/* Make sure we do various things right that involve DTD lookups of parents
from the perspective of children. */
#include <ctf-api.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum crash_method { ADD_STRUCT, ADD_UNION, ADD_MEMBER_OFFSET, ADD_MEMBER_ENCODED, ADD_ENUM, ADD_ENUMERATOR, SET_ARRAY };
void
dtd_crash (enum crash_method method, int parent_bigger)
{
ctf_dict_t *pfp, *cfp;
ctf_encoding_t e = { CTF_INT_SIGNED, 0, sizeof (long) };
ctf_id_t ptype, ftype, stype, foo;
int forward_kind = CTF_K_STRUCT;
size_t i;
int err;
/* Maybe make the relevant type IDs in the parent much bigger than those
in the child, or maybe vice versa. */
if ((pfp = ctf_create (&err)) == NULL)
goto create_err;
if (parent_bigger)
{
if ((foo = ctf_add_integer (pfp, CTF_ADD_NONROOT, "blah", &e)) == CTF_ERR)
goto create_parent;
for (i = 0; i < 4096; i++)
if (ctf_add_pointer (pfp, CTF_ADD_NONROOT, foo) == CTF_ERR)
goto create_parent;
}
if ((ptype = ctf_add_integer (pfp, CTF_ADD_NONROOT, "int", &e)) == CTF_ERR)
goto create_parent;
/* Add a forward to a struct, union, or enum (depending on the method) in
the parent, so we can try to replace it in the child and see what
happens. (Most of them are structs, or it doesn't matter, as for
SET_ARRAY; so we do that by default.) */
switch (method)
{
case ADD_UNION:
forward_kind = CTF_K_UNION;
break;
case ADD_ENUM:
case ADD_ENUMERATOR:
forward_kind = CTF_K_ENUM;
break;
/* Placate clang. */
default:
break;
}
if ((ftype = ctf_add_forward (pfp, CTF_ADD_ROOT, "foo", forward_kind)) == CTF_ERR)
goto create_parent;
if ((cfp = ctf_create (&err)) == NULL)
goto create_err;
if (ctf_import (cfp, pfp) < 0)
goto create_child;
if (!parent_bigger)
{
if ((foo = ctf_add_integer (pfp, CTF_ADD_NONROOT, "blah", &e)) == CTF_ERR)
goto create_parent;
for (i = 0; i < 4096; i++)
if (ctf_add_pointer (pfp, CTF_ADD_NONROOT, foo) == CTF_ERR)
goto create_parent;
}
switch (method)
{
/* These try to replace a forward, and should not do so if we're
adding in the child and it's in the parent. */
case ADD_STRUCT:
if ((stype = ctf_add_struct_sized (cfp, CTF_ADD_ROOT, "foo", 1024)) == CTF_ERR)
goto create_child;
if (stype == ftype)
fprintf (stderr, "Forward-promotion spotted!\n");
break;
case ADD_UNION:
if ((stype = ctf_add_union_sized (cfp, CTF_ADD_ROOT, "foo", 1024)) == CTF_ERR)
goto create_child;
if (stype == ftype)
fprintf (stderr, "Forward-promotion spotted!\n");
break;
case ADD_ENUM:
if ((stype = ctf_add_enum (cfp, CTF_ADD_ROOT, "foo")) == CTF_ERR)
goto create_child;
if (stype == ftype)
fprintf (stderr, "Forward-promotion spotted!\n");
break;
/* These try to look up the struct/union/enum we're adding to: make
sure this works from the perspective of the child if the type is in
the parent. Also make sure that addition of child types to parent
types this way is prohibited, and that addition of parent types to
parent types is allowed. */
case ADD_MEMBER_OFFSET:
{
ctf_id_t ctype;
if ((stype = ctf_add_struct (pfp, CTF_ADD_ROOT, "bar")) == CTF_ERR)
goto create_child;
if ((ctype = ctf_add_integer (cfp, CTF_ADD_NONROOT, "xyzzy", &e)) == CTF_ERR)
goto create_child;
if (ctf_add_member_offset (cfp, stype, "member", ptype, 5) == CTF_ERR)
goto create_child;
if (ctf_add_member_offset (cfp, stype, "xyzzy", ctype, 4) != CTF_ERR)
fprintf (stderr, "Addition of child type to parent via child unexpectedly succeeded\n");
else if (ctf_errno (cfp) == 0)
fprintf (stderr, "got error from ctype addition to parent struct, but no error found on child\n");
break;
}
case ADD_ENUMERATOR:
if ((stype = ctf_add_enum (pfp, CTF_ADD_ROOT, "bar")) == CTF_ERR)
goto create_parent;
if (ctf_add_enumerator (cfp, stype, "FOO", 0) == CTF_ERR)
goto create_child;
break;
/* This tries to look up the member type we're adding, and goes wrong
if the struct is in the child and the member type is in the parent. */
case ADD_MEMBER_ENCODED:
if ((stype = ctf_add_struct (cfp, CTF_ADD_ROOT, "foo")) == CTF_ERR)
goto create_child;
if (ctf_add_member_encoded (cfp, stype, "cmember", ptype, 5, e) == CTF_ERR)
goto create_child;
break;
/* This tries to look up the array we're resetting the state of. */
case SET_ARRAY:
{
ctf_arinfo_t ar;
ar.ctr_contents = ptype;
ar.ctr_index = ptype;
ar.ctr_nelems = 5;
if ((stype = ctf_add_array (pfp, CTF_ADD_ROOT, &ar)) == CTF_ERR)
goto create_child;
if (ctf_set_array (cfp, stype, &ar) == CTF_ERR)
goto create_child;
break;
}
}
ctf_dict_close (cfp);
ctf_dict_close (pfp);
return;
create_err:
fprintf (stderr, "Creation failed: %s\n", ctf_errmsg (err));
exit (1);
create_parent:
fprintf (stderr, "Cannot create parent type: %s\n", ctf_errmsg (ctf_errno (pfp)));
exit (1);
create_child:
fprintf (stderr, "Cannot create child type: %s\n", ctf_errmsg (ctf_errno (cfp)));
exit (1);
}
|