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