xref: /netbsd-src/external/gpl3/gdb/dist/libctf/testsuite/libctf-writable/parent-child-dtd-crash-lib.c (revision 32d1c65c71fbdb65a012e8392a62a757dd6853e9)
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