|  | /* 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); | 
|  | } |