Print this page
10823 should ignore DW_TAG_subprogram with DW_AT_declaration tags
10824 GCC7-derived CTF can double qualifiers on arrays
10825 ctfdump -c drops last type
10826 ctfdump -c goes off the rails with a missing parent
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Jason King <jason.king@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/test/util-tests/tests/ctf/check-common.c
+++ new/usr/src/test/util-tests/tests/ctf/check-common.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 - * Copyright (c) 2019, Joyent, Inc.
13 + * Copyright 2019, Joyent, Inc.
14 14 */
15 15
16 16 /*
17 17 * Collection of common utilities for CTF testing.
18 18 */
19 19
20 20 #include <strings.h>
21 21 #include <libctf.h>
22 22 #include "check-common.h"
23 23
24 24 typedef struct ctftests_lookup_cb {
25 25 ctf_file_t *clc_fp;
26 26 ctf_id_t clc_id;
27 27 const char *clc_name;
28 28 } ctftests_lookup_cb_t;
29 29
30 30 typedef struct ctftest_member_cb {
31 31 ctf_file_t *cmc_fp;
32 32 const check_member_t *cmc_members;
33 33 const char *cmc_name;
34 34 } ctftest_member_cb_t;
35 35
36 36 static int
37 37 ctftest_lookup_type_cb(ctf_id_t id, boolean_t root, void *arg)
38 38 {
39 39 char buf[2048];
40 40 ctftests_lookup_cb_t *clc = arg;
41 41
42 42 if (ctf_type_name(clc->clc_fp, id, buf, sizeof (buf)) == NULL)
43 43 return (0);
44 44
45 45 if (strcmp(buf, clc->clc_name) != 0)
46 46 return (0);
47 47
48 48 clc->clc_id = id;
49 49 return (1);
50 50 }
51 51
52 52 /*
53 53 * This is a variant on the classic ctf_lookup_by_name(). ctf_lookup_by_name()
54 54 * skips qualifiers, which makes sense given what the consumers of it are trying
55 55 * to do. However, that's not what we want here. So instead we basically have to
56 56 * walk the type table.
57 57 */
58 58 static ctf_id_t
59 59 ctftest_lookup_type(ctf_file_t *fp, const char *name)
60 60 {
61 61 ctftests_lookup_cb_t clc;
62 62
63 63 clc.clc_fp = fp;
64 64 clc.clc_id = CTF_ERR;
65 65 clc.clc_name = name;
66 66
67 67 (void) ctf_type_iter(fp, B_TRUE, ctftest_lookup_type_cb, &clc);
68 68 return (clc.clc_id);
69 69 }
70 70
71 71 static int
72 72 ctftest_lookup_object_cb(const char *obj, ctf_id_t type, ulong_t idx, void *arg)
73 73 {
74 74 ctftests_lookup_cb_t *clc = arg;
75 75
76 76 if (strcmp(obj, clc->clc_name) == 0) {
77 77 clc->clc_id = type;
78 78 return (1);
79 79 }
80 80
81 81 return (0);
82 82 }
83 83
84 84 static ctf_id_t
85 85 ctftest_lookup_symbol(ctf_file_t *fp, const char *name)
86 86 {
87 87 ctftests_lookup_cb_t clc;
88 88
89 89 clc.clc_fp = fp;
90 90 clc.clc_id = CTF_ERR;
91 91 clc.clc_name = name;
92 92
93 93 (void) ctf_object_iter(fp, ctftest_lookup_object_cb, &clc);
94 94 return (clc.clc_id);
95 95 }
96 96
97 97 typedef struct ctf_function_cb {
98 98 const char *cfc_name;
99 99 ulong_t *cfc_symp;
100 100 ctf_funcinfo_t *cfc_fip;
101 101 } ctf_function_cb_t;
102 102
103 103 static int
104 104 ctftest_lookup_function_cb(const char *name, ulong_t symidx,
105 105 ctf_funcinfo_t *fip, void *arg)
106 106 {
107 107 ctf_function_cb_t *cfc = arg;
108 108 if (strcmp(name, cfc->cfc_name) != 0)
109 109 return (0);
110 110
111 111 *cfc->cfc_symp = symidx;
112 112 *cfc->cfc_fip = *fip;
113 113
114 114 return (1);
115 115 }
116 116
117 117 /*
118 118 * Note, this function finds the first one with a matching name. This must not
119 119 * be used when performing searches where a given name may occur more than once.
120 120 */
121 121 static boolean_t
122 122 ctftest_lookup_function(ctf_file_t *fp, const char *name, ulong_t *symp,
123 123 ctf_funcinfo_t *fip)
124 124 {
125 125 ctf_function_cb_t cfc;
126 126
127 127 *symp = 0;
128 128 cfc.cfc_name = name;
129 129 cfc.cfc_symp = symp;
130 130 cfc.cfc_fip = fip;
131 131 (void) ctf_function_iter(fp, ctftest_lookup_function_cb, &cfc);
132 132 return (*symp == 0 ? B_FALSE : B_TRUE);
133 133 }
134 134
135 135 boolean_t
136 136 ctftest_check_numbers(ctf_file_t *fp, const check_number_t *tests)
137 137 {
138 138 uint_t i;
139 139 boolean_t ret = B_TRUE;
140 140
141 141 for (i = 0; tests[i].cn_tname != NULL; i++) {
142 142 ctf_id_t id;
143 143 ctf_encoding_t enc;
144 144
145 145 id = ctftest_lookup_type(fp, tests[i].cn_tname);
146 146 if (id == CTF_ERR) {
147 147 warnx("failed to look up %s", tests[i].cn_tname);
148 148 ret = B_FALSE;
149 149 continue;
150 150 }
151 151
152 152 if (ctf_type_kind(fp, id) != tests[i].cn_kind) {
153 153 warnx("type kind mismatch for %s: got %u, expected %u",
154 154 tests[i].cn_tname, ctf_type_kind(fp, id),
155 155 tests[i].cn_kind);
156 156 ret = B_FALSE;
157 157 continue;
158 158 }
159 159
160 160 if (ctf_type_encoding(fp, id, &enc) == CTF_ERR) {
161 161 warnx("failed to get type encoding for %s: %s",
162 162 tests[i].cn_tname, ctf_errmsg(ctf_errno(fp)));
163 163 ret = B_FALSE;
164 164 continue;
165 165 }
166 166
167 167 if (enc.cte_format != tests[i].cn_flags) {
168 168 warnx("encoding flags mismatch for %s: got 0x%x, "
169 169 "expected 0x%x", tests[i].cn_tname, enc.cte_format,
170 170 tests[i].cn_flags);
171 171 ret = B_FALSE;
172 172 continue;
173 173 }
174 174
175 175 if (enc.cte_offset != tests[i].cn_offset) {
176 176 warnx("encoding offset mismatch for %s: got 0x%x, "
177 177 "expected 0x%x", tests[i].cn_tname, enc.cte_offset,
178 178 tests[i].cn_offset);
179 179 ret = B_FALSE;
180 180 continue;
181 181 }
182 182
183 183 if (enc.cte_bits != tests[i].cn_size) {
184 184 warnx("encoding size mismatch for %s: got 0x%x, "
185 185 "expected 0x%x", tests[i].cn_tname, enc.cte_bits,
186 186 tests[i].cn_size);
187 187 ret = B_FALSE;
188 188 continue;
189 189 }
190 190 }
191 191
192 192 return (ret);
193 193 }
194 194
195 195 typedef struct ctftests_symbol_cb {
196 196 ctf_file_t *csc_fp;
197 197 boolean_t csc_ret;
198 198 const check_symbol_t *csc_tests;
199 199 } ctftest_symbol_cb_t;
200 200
201 201 static int
202 202 ctftest_check_symbol_cb(const char *obj, ctf_id_t type, ulong_t idx, void *arg)
203 203 {
204 204 ctftest_symbol_cb_t *cb = arg;
205 205 const check_symbol_t *tests = cb->csc_tests;
206 206 ctf_file_t *fp = cb->csc_fp;
207 207 uint_t i;
208 208
209 209 for (i = 0; tests[i].cs_symbol != NULL; i++) {
210 210 ctf_id_t id;
211 211
212 212 if (strcmp(obj, tests[i].cs_symbol) != 0)
213 213 continue;
214 214
215 215 id = ctftest_lookup_type(fp, tests[i].cs_type);
216 216 if (id == CTF_ERR) {
217 217 warnx("failed to lookup type %s for symbol %s",
218 218 tests[i].cs_type, tests[i].cs_symbol);
219 219 cb->csc_ret = B_FALSE;
220 220 return (0);
221 221 }
222 222
223 223 if (id != type) {
224 224 warnx("type mismatch for symbol %s, has type id %u, "
225 225 "but specified type %s has id %u",
226 226 tests[i].cs_symbol, type, tests[i].cs_type, id);
227 227 cb->csc_ret = B_FALSE;
228 228 return (0);
229 229 }
230 230 }
231 231
232 232 return (0);
233 233 }
234 234
235 235 boolean_t
236 236 ctftest_check_symbols(ctf_file_t *fp, const check_symbol_t *tests)
237 237 {
238 238 ctftest_symbol_cb_t cb;
239 239
240 240 cb.csc_fp = fp;
↓ open down ↓ |
217 lines elided |
↑ open up ↑ |
241 241 cb.csc_ret = B_TRUE;
242 242 cb.csc_tests = tests;
243 243 if (ctf_object_iter(fp, ctftest_check_symbol_cb, &cb) != 0)
244 244 return (B_FALSE);
245 245 return (cb.csc_ret);
246 246 }
247 247
248 248
249 249 boolean_t
250 250 ctftest_check_descent(const char *symbol, ctf_file_t *fp,
251 - const check_descent_t *tests)
251 + const check_descent_t *tests, boolean_t quiet)
252 252 {
253 253 ctf_id_t base;
254 254 uint_t layer = 0;
255 255
256 256 /*
257 257 * First, find the initial type of the symbol.
258 258 */
259 259 base = ctftest_lookup_symbol(fp, symbol);
260 260 if (base == CTF_ERR) {
261 261 warnx("failed to lookup type for symbol %s", symbol);
262 262 return (B_FALSE);
263 263 }
264 264
265 265 while (tests->cd_tname != NULL) {
266 266 ctf_id_t tid;
267 267 int kind;
268 268 ctf_arinfo_t ari;
269 269
270 270 if (base == CTF_ERR) {
271 - warnx("encountered non-reference type at layer %u "
272 - "while still expecting type %s for symbol %s",
273 - layer, tests->cd_tname, symbol);
271 + if (!quiet) {
272 + warnx("encountered non-reference type at layer "
273 + "%u while still expecting type %s for "
274 + "symbol %s", layer,
275 + tests->cd_tname, symbol);
276 + }
274 277 return (B_FALSE);
275 278 }
276 279
277 280 tid = ctftest_lookup_type(fp, tests->cd_tname);
278 281 if (tid == CTF_ERR) {
279 - warnx("failed to lookup type %s", tests->cd_tname);
282 + if (!quiet) {
283 + warnx("failed to lookup type %s",
284 + tests->cd_tname);
285 + }
280 286 return (B_FALSE);
281 287 }
282 288
283 289 if (tid != base) {
284 - warnx("type mismatch at layer %u: found id %u, but "
285 - "expecting type id %u for type %s, symbol %s",
286 - layer, base, tid, tests->cd_tname, symbol);
290 + if (!quiet) {
291 + warnx("type mismatch at layer %u: found id %u, "
292 + "but expecting type id %u for type %s, "
293 + "symbol %s", layer, base, tid,
294 + tests->cd_tname, symbol);
295 + }
287 296 return (B_FALSE);
288 297 }
289 298
290 299 kind = ctf_type_kind(fp, base);
291 300 if (kind != tests->cd_kind) {
292 - warnx("type kind mismatch at layer %u: found kind %u, "
293 - "but expected kind %u for %s, symbol %s", layer,
294 - kind, tests->cd_kind, tests->cd_tname, symbol);
301 + if (!quiet) {
302 + warnx("type kind mismatch at layer %u: found "
303 + "kind %u, but expected kind %u for %s, "
304 + "symbol %s", layer, kind, tests->cd_kind,
305 + tests->cd_tname, symbol);
306 + }
295 307 return (B_FALSE);
296 308 }
297 309
298 310 switch (kind) {
299 311 case CTF_K_ARRAY:
300 312 if (ctf_array_info(fp, base, &ari) == CTF_ERR) {
301 - warnx("failed to lookup array info at layer "
302 - "%u for type %s, symbol %s: %s", base,
303 - tests->cd_tname, symbol,
304 - ctf_errmsg(ctf_errno(fp)));
313 + if (!quiet) {
314 + warnx("failed to lookup array info at "
315 + "layer %u for type %s, symbol "
316 + "%s: %s", base, tests->cd_tname,
317 + symbol, ctf_errmsg(ctf_errno(fp)));
318 + }
305 319 return (B_FALSE);
306 320 }
307 321
308 322 if (tests->cd_nents != ari.ctr_nelems) {
309 - warnx("array element mismatch at layer %u "
310 - "for type %s, symbol %s: found %u, "
311 - "expected %u", layer, tests->cd_tname,
312 - symbol, ari.ctr_nelems, tests->cd_nents);
323 + if (!quiet) {
324 + warnx("array element mismatch at layer "
325 + "%u for type %s, symbol %s: found "
326 + "%u, expected %u", layer,
327 + tests->cd_tname, symbol,
328 + ari.ctr_nelems, tests->cd_nents);
329 + }
313 330 return (B_FALSE);
314 331 }
315 332
316 333 tid = ctftest_lookup_type(fp, tests->cd_contents);
317 334 if (tid == CTF_ERR) {
318 - warnx("failed to look up type %s",
319 - tests->cd_contents);
335 + if (!quiet) {
336 + warnx("failed to look up type %s",
337 + tests->cd_contents);
338 + }
320 339 return (B_FALSE);
321 340 }
322 341
323 342 if (ari.ctr_contents != tid) {
324 - warnx("array contents mismatch at layer %u "
325 - "for type %s, symbol %s: found %u, "
326 - "expected %s/%u", layer, tests->cd_tname,
327 - symbol, ari.ctr_contents,
328 - tests->cd_contents, tid);
329 -
343 + if (!quiet) {
344 + warnx("array contents mismatch at "
345 + "layer %u for type %s, symbol %s: "
346 + "found %u, expected %s/%u", layer,
347 + tests->cd_tname, symbol,
348 + ari.ctr_contents,
349 + tests->cd_contents, tid);
350 + }
330 351 return (B_FALSE);
331 352 }
332 353 base = ari.ctr_contents;
333 354 break;
334 355 default:
335 356 base = ctf_type_reference(fp, base);
336 357 break;
337 358 }
338 359
339 360 tests++;
340 361 layer++;
341 362 }
342 363
343 364 if (base != CTF_ERR) {
344 - warnx("found additional type %u in chain, but expected no more",
345 - base);
365 + if (!quiet) {
366 + warnx("found additional type %u in chain, "
367 + "but expected no more", base);
368 + }
346 369 return (B_FALSE);
347 370 }
348 371
349 372 return (B_TRUE);
350 373 }
351 374
352 375 int
353 376 ctftest_check_enum_count(const char *name, int value, void *arg)
354 377 {
355 378 uint_t *u = arg;
356 379 *u = *u + 1;
357 380 return (0);
358 381 }
359 382
360 383 int
361 384 ctftest_check_enum_value(const char *name, int value, void *arg)
362 385 {
363 386 uint_t i;
364 387 const check_enum_t *enums = arg;
365 388
366 389 for (i = 0; enums[i].ce_name != NULL; i++) {
367 390 if (strcmp(enums[i].ce_name, name) != 0)
368 391 continue;
369 392 if (enums[i].ce_value == (int64_t)value)
370 393 return (0);
371 394 warnx("enum %s value mismatch: found %d, expected %" PRId64,
372 395 name, value, enums[i].ce_value);
373 396 return (1);
374 397 }
375 398
376 399 warnx("found no matching entry for enum member %s", name);
377 400 return (1);
378 401 }
379 402
380 403 boolean_t
381 404 ctftest_check_enum(const char *type, ctf_file_t *fp, const check_enum_t *enums)
382 405 {
383 406 int ret;
384 407 uint_t tcount, ecount;
385 408 ctf_id_t base;
386 409
387 410 if ((base = ctftest_lookup_type(fp, type)) == CTF_ERR) {
388 411 warnx("Failed to look up type %s", type);
389 412 return (B_FALSE);
390 413 }
391 414
392 415 if (ctf_type_kind(fp, base) != CTF_K_ENUM) {
393 416 warnx("%s is not an enum", type);
394 417 return (B_FALSE);
395 418 }
396 419
397 420 /*
398 421 * First count how many entries we have.
399 422 */
400 423 tcount = 0;
401 424 while (enums[tcount].ce_name != NULL) {
402 425 tcount++;
403 426 }
404 427
405 428 ecount = 0;
406 429 if (ctf_enum_iter(fp, base, ctftest_check_enum_count, &ecount) != 0) {
407 430 warnx("failed to walk enum %s: %s", type,
408 431 ctf_errmsg(ctf_errno(fp)));
409 432 return (B_FALSE);
410 433 }
411 434
412 435 if (tcount != ecount) {
413 436 warnx("enum value mismatch: expected %u values, but found %u",
414 437 tcount, ecount);
415 438 return (B_FALSE);
416 439 }
417 440
418 441 if ((ret = ctf_enum_iter(fp, base, ctftest_check_enum_value,
419 442 (void *)enums)) != 0) {
420 443 if (ret == -1) {
421 444 warnx("failed to walk enum %s: %s", type,
422 445 ctf_errmsg(ctf_errno(fp)));
423 446 }
424 447 return (B_FALSE);
425 448 }
426 449
427 450 return (B_TRUE);
428 451 }
429 452
430 453 int
431 454 ctftest_check_member_count(const char *mname, ctf_id_t mtype, ulong_t bitoff,
432 455 void *arg)
433 456 {
434 457 uint_t *countp = arg;
435 458 *countp = *countp + 1;
436 459 return (0);
437 460 }
438 461
439 462 int
440 463 ctftest_check_members_cb(const char *mname, ctf_id_t mtype, ulong_t bitoff,
441 464 void *arg)
442 465 {
443 466 uint_t i;
444 467 const ctftest_member_cb_t *cmc = arg;
445 468 const check_member_t *members = cmc->cmc_members;
446 469 ctf_file_t *fp = cmc->cmc_fp;
447 470
448 471 for (i = 0; members[i].cm_name != NULL; i++) {
449 472 boolean_t bad = B_FALSE;
450 473 char buf[2048];
451 474
452 475 if (strcmp(mname, members[i].cm_name) != 0)
453 476 continue;
454 477
455 478 if (bitoff != members[i].cm_offset) {
456 479 warnx("member %s of type %s has mismatched bit offset: "
457 480 "found %lu, expected %lu", mname, cmc->cmc_name,
458 481 bitoff, members[i].cm_offset);
459 482 bad = B_TRUE;
460 483 }
461 484
462 485 if (ctf_type_name(fp, mtype, buf, sizeof (buf)) == NULL) {
463 486 warnx("failed to obtain type name for member %s",
464 487 mname, ctf_errmsg(ctf_errno(fp)));
465 488 bad = B_TRUE;
466 489 } else if (strcmp(buf, members[i].cm_type) != 0) {
467 490 warnx("member %s has bad type, found %s, expected %s",
468 491 mname, buf, members[i].cm_type);
469 492 bad = B_TRUE;
470 493 }
471 494
472 495 return (bad ? 1 : 0);
473 496 }
474 497
475 498 warnx("found no matching entry for member %s of type %s", mname,
476 499 cmc->cmc_name);
477 500 return (1);
478 501 }
479 502
480 503 boolean_t
481 504 ctftest_check_members(const char *type, ctf_file_t *fp, int kind,
482 505 size_t size, const check_member_t *members)
483 506 {
484 507 int ret;
485 508 uint_t tcount, mcount;
486 509 ctf_id_t base;
487 510 ctftest_member_cb_t cmc;
488 511
489 512 if ((base = ctftest_lookup_type(fp, type)) == CTF_ERR) {
490 513 warnx("failed to look up type %s", type);
491 514 return (B_FALSE);
492 515 }
493 516
494 517 if (ctf_type_kind(fp, base) != kind) {
495 518 warnx("%s has kind %s, expected %s", type,
496 519 ctf_kind_name(fp, ctf_type_kind(fp, base)),
497 520 ctf_kind_name(fp, kind));
498 521 return (B_FALSE);
499 522 }
500 523
501 524 if (size != ctf_type_size(fp, base)) {
502 525 warnx("%s has bad size, expected %lu, found %lu",
503 526 type, size, ctf_type_size(fp, base));
504 527 return (B_FALSE);
505 528 }
506 529
507 530 /*
508 531 * First count how many entries we have.
509 532 */
510 533 tcount = 0;
511 534 while (members[tcount].cm_name != NULL) {
512 535 tcount++;
513 536 }
514 537
515 538 mcount = 0;
516 539 if (ctf_member_iter(fp, base, ctftest_check_member_count, &mcount) !=
517 540 0) {
518 541 warnx("failed to walk members of %s: %s", type,
519 542 ctf_errmsg(ctf_errno(fp)));
520 543 return (B_FALSE);
521 544 }
522 545
523 546 if (tcount != mcount) {
524 547 warnx("type member mismatch: expected %u values, but found %u",
525 548 tcount, mcount);
526 549 return (B_FALSE);
527 550 }
528 551
529 552 cmc.cmc_fp = fp;
530 553 cmc.cmc_members = members;
531 554 cmc.cmc_name = type;
532 555 if ((ret = ctf_member_iter(fp, base, ctftest_check_members_cb,
533 556 &cmc)) != 0) {
534 557 if (ret == -1) {
535 558 warnx("failed to walk type %s: %s", type,
536 559 ctf_errmsg(ctf_errno(fp)));
537 560 }
538 561 return (B_FALSE);
539 562 }
540 563
541 564 return (B_TRUE);
542 565 }
543 566
544 567 boolean_t
545 568 ctftest_check_function(const char *symbol, ctf_file_t *fp, const char *rtype,
546 569 uint_t nargs, uint_t flags, const char **argv)
547 570 {
548 571 ulong_t sym;
549 572 ctf_funcinfo_t fi;
550 573 uint_t i;
551 574 boolean_t ret = B_TRUE;
552 575 ctf_id_t *args;
553 576 char buf[2048];
554 577
555 578
556 579 if (!ctftest_lookup_function(fp, symbol, &sym, &fi)) {
557 580 warnx("failed to look up function %s", symbol);
558 581 return (B_FALSE);
559 582 }
560 583
561 584 if (ctf_type_name(fp, fi.ctc_return, buf, sizeof (buf)) == NULL) {
562 585 warnx("failed to lookup return type name for function %s",
563 586 symbol);
564 587 ret = B_FALSE;
565 588 } else if (strcmp(rtype, buf) != 0) {
566 589 warnx("return type has wrong type: found %s, expected %s",
567 590 buf, rtype);
568 591 ret = B_FALSE;
569 592 }
570 593
571 594 if (nargs != fi.ctc_argc) {
572 595 warnx("function argument mismatch: found %u, expected %u",
573 596 fi.ctc_argc, nargs);
574 597 ret = B_FALSE;
575 598 }
576 599
577 600 if (flags != fi.ctc_flags) {
578 601 warnx("function flags mismatch, found 0x%x, expected 0x%x",
579 602 fi.ctc_flags, flags);
580 603 ret = B_FALSE;
581 604 }
582 605
583 606 if (!ret || fi.ctc_argc == 0) {
584 607 return (ret);
585 608 }
586 609
587 610 if ((args = calloc(fi.ctc_argc, sizeof (ctf_id_t))) == NULL) {
588 611 warnx("failed to allocate memory for function arguments");
589 612 return (B_FALSE);
590 613 }
591 614
592 615 if (ctf_func_args(fp, sym, fi.ctc_argc, args) != 0) {
593 616 warnx("failed to get function information: %s",
594 617 ctf_errmsg(ctf_errno(fp)));
595 618 free(args);
596 619 return (B_FALSE);
597 620 }
598 621
599 622 for (i = 0; i < fi.ctc_argc; i++) {
600 623 if (ctf_type_name(fp, args[i], buf, sizeof (buf)) == NULL) {
601 624 warnx("failed to obtain type name for argument %u",
602 625 i, ctf_errmsg(ctf_errno(fp)));
603 626 ret = B_FALSE;
604 627 break;
605 628 }
606 629
607 630 if (strcmp(buf, argv[i]) != 0) {
608 631 warnx("argument %u has wrong type: found %s, "
609 632 "expected %s", i, buf, argv[i]);
610 633 ret = B_FALSE;
611 634 break;
612 635 }
613 636 }
614 637
615 638 free(args);
616 639 return (ret);
617 640 }
618 641
619 642 boolean_t
620 643 ctftest_check_fptr(const char *type, ctf_file_t *fp, const char *rtype,
621 644 uint_t nargs, uint_t flags, const char **argv)
622 645 {
623 646 ctf_id_t tid;
624 647 ctf_funcinfo_t fi;
625 648 uint_t i;
626 649 boolean_t ret = B_TRUE;
627 650 ctf_id_t *args;
628 651 char buf[2048];
629 652
630 653
631 654 if ((tid = ctf_lookup_by_name(fp, type)) == CTF_ERR) {
632 655 warnx("failed to look up type %s: %s", type,
633 656 ctf_errmsg(ctf_errno(fp)));
634 657 return (B_FALSE);
635 658 }
636 659
637 660 /*
638 661 * Perform two CTF type resolves, one for the function pointer and one
639 662 * for the typedef that gets passed in.
640 663 */
641 664 if ((tid = ctf_type_resolve(fp, tid)) == CTF_ERR) {
642 665 warnx("failed to convert type %s to base type: %s", type,
643 666 ctf_errmsg(ctf_errno(fp)));
644 667 return (B_FALSE);
645 668 }
646 669
647 670 if (ctf_type_kind(fp, tid) == CTF_K_POINTER &&
648 671 (tid = ctf_type_reference(fp, tid)) == CTF_ERR) {
649 672 warnx("failed to convert type %s to base type: %s", type,
650 673 ctf_errmsg(ctf_errno(fp)));
651 674 return (B_FALSE);
652 675 }
653 676
654 677 if (ctf_func_info_by_id(fp, tid, &fi) != 0) {
655 678 warnx("failed to get function information for type %s: %s",
656 679 type, ctf_errmsg(ctf_errno(fp)));
657 680 return (B_FALSE);
658 681 }
659 682
660 683 if (ctf_type_name(fp, fi.ctc_return, buf, sizeof (buf)) == NULL) {
661 684 warnx("failed to lookup return type name for function %s",
662 685 type);
663 686 ret = B_FALSE;
664 687 } else if (strcmp(rtype, buf) != 0) {
665 688 warnx("return type has wrong type: found %s, expected %s",
666 689 buf, rtype);
667 690 ret = B_FALSE;
668 691 }
669 692
670 693 if (nargs != fi.ctc_argc) {
671 694 warnx("function argument mismatch: found %u, expected %u",
672 695 fi.ctc_argc, nargs);
673 696 ret = B_FALSE;
674 697 }
675 698
676 699 if (flags != fi.ctc_flags) {
677 700 warnx("function flags mismatch, found 0x%x, expected 0x%x",
678 701 fi.ctc_flags, flags);
679 702 ret = B_FALSE;
680 703 }
681 704
682 705 if (!ret || fi.ctc_argc == 0) {
683 706 return (ret);
684 707 }
685 708
686 709 if ((args = calloc(fi.ctc_argc, sizeof (ctf_id_t))) == NULL) {
687 710 warnx("failed to allocate memory for function arguments");
688 711 return (B_FALSE);
689 712 }
690 713
691 714 if (ctf_func_args_by_id(fp, tid, fi.ctc_argc, args) != 0) {
692 715 warnx("failed to get function information: %s",
693 716 ctf_errmsg(ctf_errno(fp)));
694 717 free(args);
695 718 return (B_FALSE);
696 719 }
697 720
698 721 for (i = 0; i < fi.ctc_argc; i++) {
699 722 if (ctf_type_name(fp, args[i], buf, sizeof (buf)) == NULL) {
700 723 warnx("failed to obtain type name for argument %u",
701 724 i, ctf_errmsg(ctf_errno(fp)));
702 725 ret = B_FALSE;
703 726 break;
704 727 }
705 728
706 729 if (strcmp(buf, argv[i]) != 0) {
707 730 warnx("argument %u has wrong type: found %s, "
708 731 "expected %s", i, buf, argv[i]);
709 732 ret = B_FALSE;
710 733 break;
711 734 }
712 735 }
713 736
714 737 free(args);
715 738 return (ret);
716 739 }
717 740
718 741 typedef struct ctftest_duplicates {
719 742 ctf_file_t *ctd_fp;
720 743 char **ctd_names;
721 744 size_t ctd_len;
722 745 size_t ctd_curent;
723 746 boolean_t ctd_ret;
724 747 } ctftest_duplicates_t;
725 748
726 749 static int
727 750 ctftest_duplicates_cb(ctf_id_t id, boolean_t root, void *arg)
728 751 {
729 752 char buf[2048];
730 753 ctftest_duplicates_t *dup = arg;
731 754 size_t i;
732 755
733 756 if (ctf_type_name(dup->ctd_fp, id, buf, sizeof (buf)) == NULL) {
734 757 warnx("failed to lookup name for id %ld", id);
735 758 dup->ctd_ret = B_FALSE;
736 759 return (1);
737 760 }
738 761
739 762 for (i = 0; i < dup->ctd_curent; i++) {
740 763 if (strcmp(buf, dup->ctd_names[i]) == 0) {
741 764 warnx("encountered duplicate type '%s'", buf);
742 765 dup->ctd_ret = B_FALSE;
743 766 /*
744 767 * Don't break out of the loop and keep going in case we
745 768 * find another duplicate.
746 769 */
747 770 return (0);
748 771 }
749 772 }
750 773
751 774 if (dup->ctd_curent == dup->ctd_len) {
752 775 char **n;
753 776 size_t newlen = dup->ctd_len * 2;
754 777
755 778 n = recallocarray(dup->ctd_names, dup->ctd_len, newlen,
756 779 sizeof (char *));
757 780 if (n == NULL) {
758 781 warnx("failed to resize type name array");
759 782 dup->ctd_ret = B_FALSE;
760 783 return (1);
761 784 }
762 785
763 786 dup->ctd_names = n;
764 787 dup->ctd_len = newlen;
765 788 }
766 789
767 790 dup->ctd_names[dup->ctd_curent] = strdup(buf);
768 791 if (dup->ctd_names[dup->ctd_curent] == NULL) {
769 792 warn("failed to duplicate type name");
770 793 dup->ctd_ret = B_FALSE;
771 794 return (1);
772 795 }
773 796 dup->ctd_curent++;
774 797
775 798 return (0);
776 799 }
777 800
778 801 boolean_t
779 802 ctftest_duplicates(ctf_file_t *fp)
780 803 {
781 804 size_t i;
782 805 ctftest_duplicates_t d;
783 806
784 807 bzero(&d, sizeof (d));
785 808 d.ctd_fp = fp;
786 809 d.ctd_len = 4;
787 810 d.ctd_ret = B_TRUE;
788 811 d.ctd_names = recallocarray(NULL, 0, d.ctd_len, sizeof (char *));
789 812 if (d.ctd_names == NULL) {
790 813 warnx("failed to allocate duplicate name storage");
791 814 return (B_FALSE);
792 815 }
793 816
794 817 (void) ctf_type_iter(fp, B_TRUE, ctftest_duplicates_cb, &d);
795 818
796 819 for (i = 0; i < d.ctd_curent; i++) {
797 820 free(d.ctd_names[i]);
798 821 }
799 822 free(d.ctd_names);
800 823
801 824 return (d.ctd_ret);
802 825 }
↓ open down ↓ |
447 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX