1 /* Make sure we do various things right that involve DTD lookups of parents 2 from the perspective of children. */ 3 4 #include <ctf-api.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 enum crash_method { ADD_STRUCT, ADD_UNION, ADD_MEMBER_OFFSET, ADD_MEMBER_ENCODED, ADD_ENUM, ADD_ENUMERATOR, SET_ARRAY }; 10 11 void 12 dtd_crash (enum crash_method method, int parent_bigger) 13 { 14 ctf_dict_t *pfp, *cfp; 15 ctf_encoding_t e = { CTF_INT_SIGNED, 0, sizeof (long) }; 16 ctf_id_t ptype, ftype, stype, foo; 17 int forward_kind = CTF_K_STRUCT; 18 size_t i; 19 int err; 20 21 /* Maybe make the relevant type IDs in the parent much bigger than those 22 in the child, or maybe vice versa. */ 23 24 if ((pfp = ctf_create (&err)) == NULL) 25 goto create_err; 26 27 if (parent_bigger) 28 { 29 if ((foo = ctf_add_integer (pfp, CTF_ADD_NONROOT, "blah", &e)) == CTF_ERR) 30 goto create_parent; 31 32 for (i = 0; i < 4096; i++) 33 if (ctf_add_pointer (pfp, CTF_ADD_NONROOT, foo) == CTF_ERR) 34 goto create_parent; 35 } 36 37 if ((ptype = ctf_add_integer (pfp, CTF_ADD_NONROOT, "int", &e)) == CTF_ERR) 38 goto create_parent; 39 40 /* Add a forward to a struct, union, or enum (depending on the method) in 41 the parent, so we can try to replace it in the child and see what 42 happens. (Most of them are structs, or it doesn't matter, as for 43 SET_ARRAY; so we do that by default.) */ 44 45 switch (method) 46 { 47 case ADD_UNION: 48 forward_kind = CTF_K_UNION; 49 break; 50 case ADD_ENUM: 51 case ADD_ENUMERATOR: 52 forward_kind = CTF_K_ENUM; 53 break; 54 /* Placate clang. */ 55 default: 56 break; 57 } 58 59 if ((ftype = ctf_add_forward (pfp, CTF_ADD_ROOT, "foo", forward_kind)) == CTF_ERR) 60 goto create_parent; 61 62 if ((cfp = ctf_create (&err)) == NULL) 63 goto create_err; 64 65 if (ctf_import (cfp, pfp) < 0) 66 goto create_child; 67 68 if (!parent_bigger) 69 { 70 if ((foo = ctf_add_integer (pfp, CTF_ADD_NONROOT, "blah", &e)) == CTF_ERR) 71 goto create_parent; 72 73 for (i = 0; i < 4096; i++) 74 if (ctf_add_pointer (pfp, CTF_ADD_NONROOT, foo) == CTF_ERR) 75 goto create_parent; 76 } 77 78 switch (method) 79 { 80 /* These try to replace a forward, and should not do so if we're 81 adding in the child and it's in the parent. */ 82 case ADD_STRUCT: 83 if ((stype = ctf_add_struct_sized (cfp, CTF_ADD_ROOT, "foo", 1024)) == CTF_ERR) 84 goto create_child; 85 if (stype == ftype) 86 fprintf (stderr, "Forward-promotion spotted!\n"); 87 break; 88 89 case ADD_UNION: 90 if ((stype = ctf_add_union_sized (cfp, CTF_ADD_ROOT, "foo", 1024)) == CTF_ERR) 91 goto create_child; 92 if (stype == ftype) 93 fprintf (stderr, "Forward-promotion spotted!\n"); 94 break; 95 96 case ADD_ENUM: 97 if ((stype = ctf_add_enum (cfp, CTF_ADD_ROOT, "foo")) == CTF_ERR) 98 goto create_child; 99 if (stype == ftype) 100 fprintf (stderr, "Forward-promotion spotted!\n"); 101 break; 102 103 /* These try to look up the struct/union/enum we're adding to: make 104 sure this works from the perspective of the child if the type is in 105 the parent. Also make sure that addition of child types to parent 106 types this way is prohibited, and that addition of parent types to 107 parent types is allowed. */ 108 case ADD_MEMBER_OFFSET: 109 { 110 ctf_id_t ctype; 111 112 if ((stype = ctf_add_struct (pfp, CTF_ADD_ROOT, "bar")) == CTF_ERR) 113 goto create_child; 114 115 if ((ctype = ctf_add_integer (cfp, CTF_ADD_NONROOT, "xyzzy", &e)) == CTF_ERR) 116 goto create_child; 117 118 if (ctf_add_member_offset (cfp, stype, "member", ptype, 5) == CTF_ERR) 119 goto create_child; 120 121 if (ctf_add_member_offset (cfp, stype, "xyzzy", ctype, 4) != CTF_ERR) 122 fprintf (stderr, "Addition of child type to parent via child unexpectedly succeeded\n"); 123 else if (ctf_errno (cfp) == 0) 124 fprintf (stderr, "got error from ctype addition to parent struct, but no error found on child\n"); 125 126 break; 127 } 128 129 case ADD_ENUMERATOR: 130 if ((stype = ctf_add_enum (pfp, CTF_ADD_ROOT, "bar")) == CTF_ERR) 131 goto create_parent; 132 133 if (ctf_add_enumerator (cfp, stype, "FOO", 0) == CTF_ERR) 134 goto create_child; 135 break; 136 137 /* This tries to look up the member type we're adding, and goes wrong 138 if the struct is in the child and the member type is in the parent. */ 139 case ADD_MEMBER_ENCODED: 140 if ((stype = ctf_add_struct (cfp, CTF_ADD_ROOT, "foo")) == CTF_ERR) 141 goto create_child; 142 143 if (ctf_add_member_encoded (cfp, stype, "cmember", ptype, 5, e) == CTF_ERR) 144 goto create_child; 145 break; 146 147 /* This tries to look up the array we're resetting the state of. */ 148 case SET_ARRAY: 149 { 150 ctf_arinfo_t ar; 151 152 ar.ctr_contents = ptype; 153 ar.ctr_index = ptype; 154 ar.ctr_nelems = 5; 155 156 if ((stype = ctf_add_array (pfp, CTF_ADD_ROOT, &ar)) == CTF_ERR) 157 goto create_child; 158 159 if (ctf_set_array (cfp, stype, &ar) == CTF_ERR) 160 goto create_child; 161 break; 162 } 163 } 164 165 ctf_dict_close (cfp); 166 ctf_dict_close (pfp); 167 168 return; 169 170 create_err: 171 fprintf (stderr, "Creation failed: %s\n", ctf_errmsg (err)); 172 exit (1); 173 create_parent: 174 fprintf (stderr, "Cannot create parent type: %s\n", ctf_errmsg (ctf_errno (pfp))); 175 exit (1); 176 create_child: 177 fprintf (stderr, "Cannot create child type: %s\n", ctf_errmsg (ctf_errno (cfp))); 178 exit (1); 179 } 180