xref: /illumos-gate/usr/src/test/util-tests/tests/ctf/check-sou.c (revision 5328fc53d11d7151861fa272e4fb0248b8f0e145)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2019, Joyent, Inc.
14  */
15 
16 /*
17  * Check that we properly handle structures and unions.
18  */
19 
20 #include "check-common.h"
21 
22 static check_number_t check_bitfields[] = {
23 #ifdef	TARGET_LP64
24 	{ "unsigned long:1", CTF_K_INTEGER, 0, 0, 1 },
25 	{ "unsigned long:2", CTF_K_INTEGER,  0, 0, 2 },
26 	{ "unsigned long:4", CTF_K_INTEGER,  0, 0, 4 },
27 	{ "unsigned long:5", CTF_K_INTEGER,  0, 0, 5 },
28 	{ "unsigned long:8", CTF_K_INTEGER,  0, 0, 8 },
29 	{ "unsigned long:16", CTF_K_INTEGER,  0, 0, 16 },
30 	{ "unsigned long:19", CTF_K_INTEGER,  0, 0, 19 },
31 	{ "unsigned long:32", CTF_K_INTEGER,  0, 0, 32 },
32 #else
33 	{ "unsigned long long:1", CTF_K_INTEGER, 0, 0, 1 },
34 	{ "unsigned long long:2", CTF_K_INTEGER,  0, 0, 2 },
35 	{ "unsigned long long:4", CTF_K_INTEGER,  0, 0, 4 },
36 	{ "unsigned long long:5", CTF_K_INTEGER,  0, 0, 5 },
37 	{ "unsigned long long:8", CTF_K_INTEGER,  0, 0, 8 },
38 	{ "unsigned long long:16", CTF_K_INTEGER,  0, 0, 16 },
39 	{ "unsigned long long:19", CTF_K_INTEGER,  0, 0, 19 },
40 	{ "unsigned long long:32", CTF_K_INTEGER,  0, 0, 32 },
41 #endif
42 	{ "unsigned short:1", CTF_K_INTEGER, 0, 0, 1 },
43 	{ "unsigned int:7", CTF_K_INTEGER, 0, 0, 7 },
44 	{ "unsigned int:32", CTF_K_INTEGER, 0, 0, 32 },
45 	{ "int:3", CTF_K_INTEGER, CTF_INT_SIGNED, 0, 3 },
46 	{ NULL }
47 };
48 
49 static check_symbol_t check_syms[] = {
50 	{ "foo", "struct foo" },
51 	{ "head", "nlist_t" },
52 	{ "forward", "const forward_t" },
53 	{ "oot", "struct round_up" },
54 	{ "botw", "struct fixed_up" },
55 	{ "sophie", "struct mysterious_barrel" },
56 	{ "ayesha", "struct dusk_barrel" },
57 	{ "stats", "struct stats" },
58 	{ "ring", "struct fellowship" },
59 	{ "rings", "struct rings" },
60 	{ "nvme", "struct csts" },
61 	{ "games", "union jrpg" },
62 	{ "nier", "union nier" },
63 	{ "kh", "union kh" },
64 	{ "ct", "struct trigger" },
65 	{ "regress", "const union regress [9]" },
66 	{ NULL }
67 };
68 
69 static check_member_t check_member_foo[] = {
70 	{ "a", "int", 0 },
71 	{ "b", "float", 4 * NBBY },
72 	{ "c", "const char *", 8 * NBBY },
73 	{ NULL }
74 };
75 
76 static check_member_t check_member_node[] = {
77 	{ "prev", "struct node *", 0 },
78 #ifdef	TARGET_LP64
79 	{ "next", "struct node *", 8 * NBBY },
80 #else
81 	{ "next", "struct node *", 4 * NBBY },
82 #endif
83 	{ NULL }
84 };
85 
86 static check_member_t check_member_nlist[] = {
87 	{ "size", "size_t", 0 },
88 #ifdef	TARGET_LP64
89 	{ "off", "size_t", 8 * NBBY },
90 	{ "head", "struct node", 16 * NBBY },
91 #else
92 	{ "off", "size_t", 4 * NBBY },
93 	{ "head", "struct node", 8 * NBBY },
94 #endif
95 	{ NULL }
96 };
97 
98 static check_member_t check_member_forward[] = {
99 	{ "past", "void *", 0 },
100 #ifdef	TARGET_LP64
101 	{ "present", "void *", 8 * NBBY },
102 	{ "future", "void *", 16 * NBBY },
103 #else
104 	{ "present", "void *", 4 * NBBY },
105 	{ "future", "void *", 8 * NBBY },
106 #endif
107 	{ NULL }
108 };
109 
110 static check_member_t check_member_round_up[] = {
111 	{ "triforce", "uint8_t", 0 },
112 	{ "link", "uint32_t", 4 * NBBY },
113 	{ "zelda", "uint8_t", 8 * NBBY },
114 	{ "ganon", "uint8_t", 9 * NBBY },
115 	{ NULL }
116 };
117 
118 static check_member_t check_member_fixed_up[] = {
119 	{ "triforce", "uint8_t", 0 },
120 	{ "link", "uint32_t", 1 * NBBY },
121 	{ "zelda", "uint8_t", 5 * NBBY },
122 	{ "ganon", "uint8_t", 6 * NBBY },
123 	{ NULL }
124 };
125 
126 #ifdef	TARGET_LP64
127 static check_member_t check_member_component[] = {
128 	{ "m", "enum material", 0 },
129 	{ "grade", "uint64_t", 8 * NBBY },
130 	{ "count", "uint64_t", 16 * NBBY },
131 	{ "locations", "const char *[4]", 24 * NBBY },
132 	{ NULL }
133 };
134 
135 static check_member_t check_member_mysterious[] = {
136 	{ "name", "const char *", 0 },
137 	{ "capacity", "size_t", 8 * NBBY },
138 	{ "optional", "struct component [0]", 16 * NBBY },
139 	{ NULL }
140 };
141 
142 static check_member_t check_member_dusk[] = {
143 	{ "name", "const char *", 0 },
144 	{ "opacity", "size_t", 8 * NBBY },
145 	{ "optional", "struct component [0]", 16 * NBBY },
146 	{ NULL }
147 };
148 
149 
150 static check_member_t check_member_stats[] = {
151 	{ "hp", "unsigned long:16", 0 },
152 	{ "mp", "unsigned long:16", 16 },
153 	{ "str", "unsigned long:8", 32 },
154 	{ "dex", "unsigned long:4", 40 },
155 	{ "con", "unsigned long:1", 44 },
156 	{ "inte", "unsigned long:2", 45 },
157 	{ "wis", "unsigned long:1", 47 },
158 	{ "cha", "unsigned long:4", 48 },
159 	{ "sanity", "unsigned long:1", 52 },
160 	{ "attack", "unsigned long:2", 53 },
161 	{ "mattack", "unsigned long:1", 55 },
162 	{ "defense", "unsigned long:8", 56 },
163 	{ "mdefense", "unsigned long:32", 64 },
164 	{ "evasion", "unsigned long:8", 96 },
165 	{ "crit", "unsigned long:5", 104 },
166 	{ "luck", "unsigned long:19", 109 },
167 	{ NULL }
168 };
169 #else
170 static check_member_t check_member_component[] = {
171 	{ "m", "enum material", 0 },
172 	{ "grade", "uint64_t", 4 * NBBY },
173 	{ "count", "uint64_t", 12 * NBBY },
174 	{ "locations", "const char *[4]", 20 * NBBY },
175 	{ NULL }
176 };
177 
178 static check_member_t check_member_mysterious[] = {
179 	{ "name", "const char *", 0 },
180 	{ "capacity", "size_t", 4 * NBBY },
181 	{ "optional", "struct component [0]", 8 * NBBY },
182 	{ NULL }
183 };
184 
185 static check_member_t check_member_dusk[] = {
186 	{ "name", "const char *", 0 },
187 	{ "opacity", "size_t", 4 * NBBY },
188 	{ "optional", "struct component [0]", 8 * NBBY },
189 	{ NULL }
190 };
191 
192 
193 static check_member_t check_member_stats[] = {
194 	{ "hp", "unsigned long long:16", 0 },
195 	{ "mp", "unsigned long long:16", 16 },
196 	{ "str", "unsigned long long:8", 32 },
197 	{ "dex", "unsigned long long:4", 40 },
198 	{ "con", "unsigned long long:1", 44 },
199 	{ "inte", "unsigned long long:2", 45 },
200 	{ "wis", "unsigned long long:1", 47 },
201 	{ "cha", "unsigned long long:4", 48 },
202 	{ "sanity", "unsigned long long:1", 52 },
203 	{ "attack", "unsigned long long:2", 53 },
204 	{ "mattack", "unsigned long long:1", 55 },
205 	{ "defense", "unsigned long long:8", 56 },
206 	{ "mdefense", "unsigned long long:32", 64 },
207 	{ "evasion", "unsigned long long:8", 96 },
208 	{ "crit", "unsigned long long:5", 104 },
209 	{ "luck", "unsigned long long:19", 109 },
210 	{ NULL }
211 };
212 #endif
213 
214 static check_member_t check_member_fellowship[] = {
215 	{ "frodo", "unsigned short:1", 0 },
216 	{ "sam", "unsigned short:1", 1 },
217 	{ "merry", "unsigned short:1", 2 },
218 	{ "pippin", "unsigned short:1", 3 },
219 	{ "aragorn", "unsigned short:1", 4 },
220 	{ "boromir", "unsigned short:1", 5 },
221 	{ "legolas", "unsigned short:1", 6 },
222 	{ "gimli", "unsigned short:1", 7 },
223 	{ "gandalf", "unsigned short:1", 8 },
224 	{ NULL }
225 };
226 
227 static check_member_t check_member_rings[] = {
228 	{ "elves", "unsigned int:3", 0 },
229 	{ "dwarves", "unsigned int:7", 3 },
230 	{ "men", "unsigned int:9", 10 },
231 	{ "one", "uint8_t", 3 * NBBY },
232 	{ "silmarils", "uint8_t [3]", 4 * NBBY },
233 	{ NULL }
234 };
235 
236 static check_member_t check_member_csts[] = {
237 	{ "rdy", "unsigned int:7", 0 },
238 	{ "csts", "unsigned int:32", 7 },
239 	{ NULL }
240 };
241 
242 static check_member_t check_member_jrpg[] = {
243 	{ "ff", "int", 0 },
244 	{ "atelier", "double [4]", 0 },
245 	{ "tales", "const char *", 0 },
246 	{ "chrono", "int (*)()", 0 },
247 	{ "xeno", "struct rings", 0 },
248 	{ NULL }
249 };
250 
251 static check_member_t check_member_android[] = {
252 	{ "_2b", "unsigned int:16", 0 },
253 	{ "_9s", "unsigned int:16", 16 },
254 	{ NULL }
255 };
256 
257 static check_member_t check_member_nier[] = {
258 	{ "automata", "uint32_t", 0 },
259 	{ "android", "struct android", 0 },
260 	{ NULL }
261 };
262 
263 static check_member_t check_member_kh[] = {
264 	{ "sora", "int:3", 0 },
265 	{ "riku", "char:7", 0 },
266 	{ "kairi", "double", 0 },
267 	{ "namine", "complex double", 0 },
268 	{ NULL }
269 };
270 
271 static check_member_t check_member_trigger[] = {
272 	{ "chrono", "uint8_t", 0 },
273 	{ "cross", "uint8_t", 8 },
274 	/*
275 	 * This test has an anonymous union. Unfortunately, there's not a great
276 	 * way to distinguish between various anonymous unions in this form.
277 	 */
278 #ifdef	TARGET_LP64
279 	{ "", "union ", 64 },
280 #else
281 	{ "", "union ", 32 },
282 #endif
283 	{ NULL }
284 };
285 
286 static check_member_t check_member_regress[] = {
287 	{ "i", "unsigned int [3]", 0 },
288 	{ "e", "long double", 0 },
289 	{ NULL }
290 };
291 
292 static check_member_test_t members[] = {
293 #ifdef	TARGET_LP64
294 	{ "struct foo", CTF_K_STRUCT, 16, check_member_foo },
295 	{ "struct node", CTF_K_STRUCT, 16, check_member_node },
296 	{ "struct nlist", CTF_K_STRUCT, 32, check_member_nlist },
297 	{ "struct forward", CTF_K_STRUCT, 24, check_member_forward },
298 #else
299 	{ "struct foo", CTF_K_STRUCT, 12, check_member_foo },
300 	{ "struct node", CTF_K_STRUCT, 8, check_member_node },
301 	{ "struct nlist", CTF_K_STRUCT, 16, check_member_nlist },
302 	{ "struct forward", CTF_K_STRUCT, 12, check_member_forward },
303 #endif
304 	{ "struct round_up", CTF_K_STRUCT, 12, check_member_round_up },
305 	{ "struct fixed_up", CTF_K_STRUCT, 7, check_member_fixed_up },
306 #ifdef	TARGET_LP64
307 	{ "struct component", CTF_K_STRUCT, 56, check_member_component },
308 	{ "struct mysterious_barrel", CTF_K_STRUCT, 16,
309 	    check_member_mysterious },
310 	{ "struct dusk_barrel", CTF_K_STRUCT, 16, check_member_dusk },
311 #else
312 	{ "struct component", CTF_K_STRUCT, 36, check_member_component },
313 	{ "struct mysterious_barrel", CTF_K_STRUCT, 8,
314 	    check_member_mysterious },
315 	{ "struct dusk_barrel", CTF_K_STRUCT, 8, check_member_dusk },
316 #endif
317 	{ "struct stats", CTF_K_STRUCT, 16, check_member_stats },
318 	{ "struct fellowship", CTF_K_STRUCT, 2, check_member_fellowship },
319 	{ "struct rings", CTF_K_STRUCT, 8, check_member_rings },
320 	{ "struct csts", CTF_K_STRUCT, 5, check_member_csts },
321 	{ "union jrpg", CTF_K_UNION, 32, check_member_jrpg },
322 	{ "struct android", CTF_K_STRUCT, 4, check_member_android },
323 	{ "union nier", CTF_K_UNION, 4, check_member_nier },
324 	{ "union kh", CTF_K_UNION, 16, check_member_kh },
325 #ifdef	TARGET_LP64
326 	{ "struct trigger", CTF_K_STRUCT, 32, check_member_trigger },
327 	{ "union regress", CTF_K_UNION, 16, check_member_regress },
328 #else
329 	{ "struct trigger", CTF_K_STRUCT, 28, check_member_trigger },
330 	{ "union regress", CTF_K_UNION, 12, check_member_regress },
331 #endif
332 	{ NULL }
333 };
334 
335 static check_descent_t check_descent_head[] = {
336 	{ "nlist_t", CTF_K_TYPEDEF },
337 	{ "struct nlist", CTF_K_STRUCT },
338 	{ NULL }
339 };
340 
341 static check_descent_t check_descent_forward[] = {
342 	{ "const forward_t", CTF_K_CONST },
343 	{ "forward_t", CTF_K_TYPEDEF },
344 	{ "struct forward", CTF_K_STRUCT },
345 	{ NULL }
346 };
347 
348 static check_descent_test_t descents[] = {
349 	{ "head", check_descent_head },
350 	{ "forward", check_descent_forward },
351 	{ NULL }
352 };
353 
354 static check_descent_t check_descent_regress_gcc4[] = {
355 	{ "const union regress [9]", CTF_K_CONST },
356 	{ "union regress [9]", CTF_K_ARRAY, "union regress", 9 },
357 	{ "union regress", CTF_K_UNION },
358 	{ NULL }
359 };
360 
361 static check_descent_t check_descent_regress_gcc7[] = {
362 	{ "const union regress [9]", CTF_K_ARRAY, "const union regress", 9 },
363 	{ "const union regress", CTF_K_CONST },
364 	{ "union regress", CTF_K_UNION },
365 	{ NULL }
366 };
367 
368 /*
369  * See needed_array_qualifier(): applying this fix means the qualifier order is
370  * different between GCC versions. Accept either form.
371  */
372 static check_descent_test_t alt_descents[] = {
373 	{ "regress", check_descent_regress_gcc4 },
374 	{ "regress", check_descent_regress_gcc7 },
375 	{ NULL }
376 };
377 
378 int
379 main(int argc, char *argv[])
380 {
381 	int i, ret = 0;
382 
383 	if (argc < 2) {
384 		errx(EXIT_FAILURE, "missing test files");
385 	}
386 
387 	for (i = 1; i < argc; i++) {
388 		ctf_file_t *fp;
389 		int alt_ok = 0;
390 		uint_t j;
391 
392 		if ((fp = ctf_open(argv[i], &ret)) == NULL) {
393 			warnx("failed to open %s: %s", argv[i],
394 			    ctf_errmsg(ret));
395 			ret = EXIT_FAILURE;
396 			continue;
397 		}
398 
399 		if (!ctftest_check_numbers(fp, check_bitfields))
400 			ret = EXIT_FAILURE;
401 		if (!ctftest_check_symbols(fp, check_syms))
402 			ret = EXIT_FAILURE;
403 		for (j = 0; descents[j].cdt_sym != NULL; j++) {
404 			if (!ctftest_check_descent(descents[j].cdt_sym, fp,
405 			    descents[j].cdt_tests, B_FALSE)) {
406 				ret = EXIT_FAILURE;
407 			}
408 		}
409 
410 		for (j = 0; alt_descents[j].cdt_sym != NULL; j++) {
411 			if (ctftest_check_descent(alt_descents[j].cdt_sym, fp,
412 			    alt_descents[j].cdt_tests, B_TRUE)) {
413 				alt_ok = 1;
414 				break;
415 			}
416 		}
417 
418 		if (!alt_ok) {
419 			warnx("all descents failed for %s",
420 			    alt_descents[0].cdt_sym);
421 			ret = EXIT_FAILURE;
422 		}
423 
424 		for (j = 0; members[j].cmt_type != NULL; j++) {
425 			if (!ctftest_check_members(members[j].cmt_type, fp,
426 			    members[j].cmt_kind, members[j].cmt_size,
427 			    members[j].cmt_members)) {
428 				ret = EXIT_FAILURE;
429 			}
430 		}
431 
432 		ctf_close(fp);
433 	}
434 
435 	return (ret);
436 }
437