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