15bb525f4SRobert Mustacchi /*
25bb525f4SRobert Mustacchi  * This file and its contents are supplied under the terms of the
35bb525f4SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
45bb525f4SRobert Mustacchi  * You may only use this file in accordance with the terms of version
55bb525f4SRobert Mustacchi  * 1.0 of the CDDL.
65bb525f4SRobert Mustacchi  *
75bb525f4SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
85bb525f4SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
95bb525f4SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
105bb525f4SRobert Mustacchi  */
115bb525f4SRobert Mustacchi 
125bb525f4SRobert Mustacchi /*
13fe2dc8bdSJohn Levon  * Copyright 2020 Joyent, Inc.
145bb525f4SRobert Mustacchi  */
155bb525f4SRobert Mustacchi 
165bb525f4SRobert Mustacchi /*
175bb525f4SRobert Mustacchi  * Collection of common utilities for CTF testing.
185bb525f4SRobert Mustacchi  */
195bb525f4SRobert Mustacchi 
205bb525f4SRobert Mustacchi #include <strings.h>
215bb525f4SRobert Mustacchi #include <libctf.h>
225bb525f4SRobert Mustacchi #include "check-common.h"
235bb525f4SRobert Mustacchi 
245bb525f4SRobert Mustacchi typedef struct ctftests_lookup_cb {
255bb525f4SRobert Mustacchi 	ctf_file_t *clc_fp;
265bb525f4SRobert Mustacchi 	ctf_id_t clc_id;
275bb525f4SRobert Mustacchi 	const char *clc_name;
285bb525f4SRobert Mustacchi } ctftests_lookup_cb_t;
295bb525f4SRobert Mustacchi 
305bb525f4SRobert Mustacchi typedef struct ctftest_member_cb {
315bb525f4SRobert Mustacchi 	ctf_file_t *cmc_fp;
325bb525f4SRobert Mustacchi 	const check_member_t *cmc_members;
335bb525f4SRobert Mustacchi 	const char *cmc_name;
345bb525f4SRobert Mustacchi } ctftest_member_cb_t;
355bb525f4SRobert Mustacchi 
365bb525f4SRobert Mustacchi static int
ctftest_lookup_type_cb(ctf_id_t id,boolean_t root,void * arg)375bb525f4SRobert Mustacchi ctftest_lookup_type_cb(ctf_id_t id, boolean_t root, void *arg)
385bb525f4SRobert Mustacchi {
395bb525f4SRobert Mustacchi 	char buf[2048];
405bb525f4SRobert Mustacchi 	ctftests_lookup_cb_t *clc = arg;
415bb525f4SRobert Mustacchi 
425bb525f4SRobert Mustacchi 	if (ctf_type_name(clc->clc_fp, id, buf, sizeof (buf)) == NULL)
435bb525f4SRobert Mustacchi 		return (0);
445bb525f4SRobert Mustacchi 
455bb525f4SRobert Mustacchi 	if (strcmp(buf, clc->clc_name) != 0)
465bb525f4SRobert Mustacchi 		return (0);
475bb525f4SRobert Mustacchi 
485bb525f4SRobert Mustacchi 	clc->clc_id = id;
495bb525f4SRobert Mustacchi 	return (1);
505bb525f4SRobert Mustacchi }
515bb525f4SRobert Mustacchi 
525bb525f4SRobert Mustacchi /*
535bb525f4SRobert Mustacchi  * This is a variant on the classic ctf_lookup_by_name(). ctf_lookup_by_name()
545bb525f4SRobert Mustacchi  * skips qualifiers, which makes sense given what the consumers of it are trying
555bb525f4SRobert Mustacchi  * to do. However, that's not what we want here. So instead we basically have to
565bb525f4SRobert Mustacchi  * walk the type table.
575bb525f4SRobert Mustacchi  */
585bb525f4SRobert Mustacchi static ctf_id_t
ctftest_lookup_type(ctf_file_t * fp,const char * name)595bb525f4SRobert Mustacchi ctftest_lookup_type(ctf_file_t *fp, const char *name)
605bb525f4SRobert Mustacchi {
615bb525f4SRobert Mustacchi 	ctftests_lookup_cb_t clc;
625bb525f4SRobert Mustacchi 
635bb525f4SRobert Mustacchi 	clc.clc_fp = fp;
645bb525f4SRobert Mustacchi 	clc.clc_id = CTF_ERR;
655bb525f4SRobert Mustacchi 	clc.clc_name = name;
665bb525f4SRobert Mustacchi 
675bb525f4SRobert Mustacchi 	(void) ctf_type_iter(fp, B_TRUE, ctftest_lookup_type_cb, &clc);
685bb525f4SRobert Mustacchi 	return (clc.clc_id);
695bb525f4SRobert Mustacchi }
705bb525f4SRobert Mustacchi 
715bb525f4SRobert Mustacchi static int
ctftest_lookup_object_cb(const char * obj,ctf_id_t type,ulong_t idx,void * arg)725bb525f4SRobert Mustacchi ctftest_lookup_object_cb(const char *obj, ctf_id_t type, ulong_t idx, void *arg)
735bb525f4SRobert Mustacchi {
745bb525f4SRobert Mustacchi 	ctftests_lookup_cb_t *clc = arg;
755bb525f4SRobert Mustacchi 
765bb525f4SRobert Mustacchi 	if (strcmp(obj, clc->clc_name) == 0) {
775bb525f4SRobert Mustacchi 		clc->clc_id = type;
785bb525f4SRobert Mustacchi 		return (1);
795bb525f4SRobert Mustacchi 	}
805bb525f4SRobert Mustacchi 
815bb525f4SRobert Mustacchi 	return (0);
825bb525f4SRobert Mustacchi }
835bb525f4SRobert Mustacchi 
845bb525f4SRobert Mustacchi static ctf_id_t
ctftest_lookup_symbol(ctf_file_t * fp,const char * name)855bb525f4SRobert Mustacchi ctftest_lookup_symbol(ctf_file_t *fp, const char *name)
865bb525f4SRobert Mustacchi {
875bb525f4SRobert Mustacchi 	ctftests_lookup_cb_t clc;
885bb525f4SRobert Mustacchi 
895bb525f4SRobert Mustacchi 	clc.clc_fp = fp;
905bb525f4SRobert Mustacchi 	clc.clc_id = CTF_ERR;
915bb525f4SRobert Mustacchi 	clc.clc_name = name;
925bb525f4SRobert Mustacchi 
935bb525f4SRobert Mustacchi 	(void) ctf_object_iter(fp, ctftest_lookup_object_cb, &clc);
945bb525f4SRobert Mustacchi 	return (clc.clc_id);
955bb525f4SRobert Mustacchi }
965bb525f4SRobert Mustacchi 
975bb525f4SRobert Mustacchi typedef struct ctf_function_cb {
985bb525f4SRobert Mustacchi 	const char *cfc_name;
995bb525f4SRobert Mustacchi 	ulong_t *cfc_symp;
1005bb525f4SRobert Mustacchi 	ctf_funcinfo_t *cfc_fip;
1015bb525f4SRobert Mustacchi } ctf_function_cb_t;
1025bb525f4SRobert Mustacchi 
1035bb525f4SRobert Mustacchi static int
ctftest_lookup_function_cb(const char * name,ulong_t symidx,ctf_funcinfo_t * fip,void * arg)1045bb525f4SRobert Mustacchi ctftest_lookup_function_cb(const char *name, ulong_t symidx,
1055bb525f4SRobert Mustacchi     ctf_funcinfo_t *fip, void *arg)
1065bb525f4SRobert Mustacchi {
1075bb525f4SRobert Mustacchi 	ctf_function_cb_t *cfc = arg;
1085bb525f4SRobert Mustacchi 	if (strcmp(name, cfc->cfc_name) != 0)
1095bb525f4SRobert Mustacchi 		return (0);
1105bb525f4SRobert Mustacchi 
1115bb525f4SRobert Mustacchi 	*cfc->cfc_symp = symidx;
1125bb525f4SRobert Mustacchi 	*cfc->cfc_fip = *fip;
1135bb525f4SRobert Mustacchi 
1145bb525f4SRobert Mustacchi 	return (1);
1155bb525f4SRobert Mustacchi }
1165bb525f4SRobert Mustacchi 
1175bb525f4SRobert Mustacchi /*
1185bb525f4SRobert Mustacchi  * Note, this function finds the first one with a matching name. This must not
1195bb525f4SRobert Mustacchi  * be used when performing searches where a given name may occur more than once.
1205bb525f4SRobert Mustacchi  */
1215bb525f4SRobert Mustacchi static boolean_t
ctftest_lookup_function(ctf_file_t * fp,const char * name,ulong_t * symp,ctf_funcinfo_t * fip)1225bb525f4SRobert Mustacchi ctftest_lookup_function(ctf_file_t *fp, const char *name, ulong_t *symp,
1235bb525f4SRobert Mustacchi     ctf_funcinfo_t *fip)
1245bb525f4SRobert Mustacchi {
1255bb525f4SRobert Mustacchi 	ctf_function_cb_t cfc;
1265bb525f4SRobert Mustacchi 
1275bb525f4SRobert Mustacchi 	*symp = 0;
1285bb525f4SRobert Mustacchi 	cfc.cfc_name = name;
1295bb525f4SRobert Mustacchi 	cfc.cfc_symp = symp;
1305bb525f4SRobert Mustacchi 	cfc.cfc_fip = fip;
1315bb525f4SRobert Mustacchi 	(void) ctf_function_iter(fp, ctftest_lookup_function_cb, &cfc);
1325bb525f4SRobert Mustacchi 	return (*symp == 0 ? B_FALSE : B_TRUE);
1335bb525f4SRobert Mustacchi }
1345bb525f4SRobert Mustacchi 
1355bb525f4SRobert Mustacchi boolean_t
ctftest_check_numbers(ctf_file_t * fp,const check_number_t * tests)1365bb525f4SRobert Mustacchi ctftest_check_numbers(ctf_file_t *fp, const check_number_t *tests)
1375bb525f4SRobert Mustacchi {
1385bb525f4SRobert Mustacchi 	uint_t i;
1395bb525f4SRobert Mustacchi 	boolean_t ret = B_TRUE;
1405bb525f4SRobert Mustacchi 
1415bb525f4SRobert Mustacchi 	for (i = 0; tests[i].cn_tname != NULL; i++) {
1425bb525f4SRobert Mustacchi 		ctf_id_t id;
1435bb525f4SRobert Mustacchi 		ctf_encoding_t enc;
1445bb525f4SRobert Mustacchi 
1453cec9822SRobert Mustacchi 		if (ctftest_skip(tests[i].cn_skips)) {
1463cec9822SRobert Mustacchi 			warnx("skipping check numbers test %s due to known "
1473cec9822SRobert Mustacchi 			    "compiler issue", tests[i].cn_tname);
1483cec9822SRobert Mustacchi 			continue;
1493cec9822SRobert Mustacchi 		}
1503cec9822SRobert Mustacchi 
1515bb525f4SRobert Mustacchi 		id = ctftest_lookup_type(fp, tests[i].cn_tname);
1525bb525f4SRobert Mustacchi 		if (id == CTF_ERR) {
1535bb525f4SRobert Mustacchi 			warnx("failed to look up %s", tests[i].cn_tname);
1545bb525f4SRobert Mustacchi 			ret = B_FALSE;
1555bb525f4SRobert Mustacchi 			continue;
1565bb525f4SRobert Mustacchi 		}
1575bb525f4SRobert Mustacchi 
1585bb525f4SRobert Mustacchi 		if (ctf_type_kind(fp, id) != tests[i].cn_kind) {
1595bb525f4SRobert Mustacchi 			warnx("type kind mismatch for %s: got %u, expected %u",
1605bb525f4SRobert Mustacchi 			    tests[i].cn_tname, ctf_type_kind(fp, id),
1615bb525f4SRobert Mustacchi 			    tests[i].cn_kind);
1625bb525f4SRobert Mustacchi 			ret = B_FALSE;
1635bb525f4SRobert Mustacchi 			continue;
1645bb525f4SRobert Mustacchi 		}
1655bb525f4SRobert Mustacchi 
1665bb525f4SRobert Mustacchi 		if (ctf_type_encoding(fp, id, &enc) == CTF_ERR) {
1675bb525f4SRobert Mustacchi 			warnx("failed to get type encoding for %s: %s",
1685bb525f4SRobert Mustacchi 			    tests[i].cn_tname, ctf_errmsg(ctf_errno(fp)));
1695bb525f4SRobert Mustacchi 			ret = B_FALSE;
1705bb525f4SRobert Mustacchi 			continue;
1715bb525f4SRobert Mustacchi 		}
1725bb525f4SRobert Mustacchi 
1735bb525f4SRobert Mustacchi 		if (enc.cte_format != tests[i].cn_flags) {
1745bb525f4SRobert Mustacchi 			warnx("encoding flags mismatch for %s: got 0x%x, "
1755bb525f4SRobert Mustacchi 			    "expected 0x%x", tests[i].cn_tname, enc.cte_format,
1765bb525f4SRobert Mustacchi 			    tests[i].cn_flags);
1775bb525f4SRobert Mustacchi 			ret = B_FALSE;
1785bb525f4SRobert Mustacchi 			continue;
1795bb525f4SRobert Mustacchi 		}
1805bb525f4SRobert Mustacchi 
1815bb525f4SRobert Mustacchi 		if (enc.cte_offset != tests[i].cn_offset) {
1825bb525f4SRobert Mustacchi 			warnx("encoding offset mismatch for %s: got 0x%x, "
1835bb525f4SRobert Mustacchi 			    "expected 0x%x", tests[i].cn_tname, enc.cte_offset,
1845bb525f4SRobert Mustacchi 			    tests[i].cn_offset);
1855bb525f4SRobert Mustacchi 			ret = B_FALSE;
1865bb525f4SRobert Mustacchi 			continue;
1875bb525f4SRobert Mustacchi 		}
1885bb525f4SRobert Mustacchi 
1895bb525f4SRobert Mustacchi 		if (enc.cte_bits != tests[i].cn_size) {
1905bb525f4SRobert Mustacchi 			warnx("encoding size mismatch for %s: got 0x%x, "
1915bb525f4SRobert Mustacchi 			    "expected 0x%x", tests[i].cn_tname, enc.cte_bits,
1925bb525f4SRobert Mustacchi 			    tests[i].cn_size);
1935bb525f4SRobert Mustacchi 			ret = B_FALSE;
1945bb525f4SRobert Mustacchi 			continue;
1955bb525f4SRobert Mustacchi 		}
1965bb525f4SRobert Mustacchi 	}
1975bb525f4SRobert Mustacchi 
1985bb525f4SRobert Mustacchi 	return (ret);
1995bb525f4SRobert Mustacchi }
2005bb525f4SRobert Mustacchi 
2015bb525f4SRobert Mustacchi typedef struct ctftests_symbol_cb {
2025bb525f4SRobert Mustacchi 	ctf_file_t	*csc_fp;
2035bb525f4SRobert Mustacchi 	boolean_t	csc_ret;
2045bb525f4SRobert Mustacchi 	const check_symbol_t *csc_tests;
2055bb525f4SRobert Mustacchi } ctftest_symbol_cb_t;
2065bb525f4SRobert Mustacchi 
2075bb525f4SRobert Mustacchi static int
ctftest_check_symbol_cb(const char * obj,ctf_id_t type,ulong_t idx,void * arg)2085bb525f4SRobert Mustacchi ctftest_check_symbol_cb(const char *obj, ctf_id_t type, ulong_t idx, void *arg)
2095bb525f4SRobert Mustacchi {
2105bb525f4SRobert Mustacchi 	ctftest_symbol_cb_t *cb = arg;
2115bb525f4SRobert Mustacchi 	const check_symbol_t *tests = cb->csc_tests;
2125bb525f4SRobert Mustacchi 	ctf_file_t *fp = cb->csc_fp;
2135bb525f4SRobert Mustacchi 	uint_t i;
2145bb525f4SRobert Mustacchi 
2155bb525f4SRobert Mustacchi 	for (i = 0; tests[i].cs_symbol != NULL; i++) {
2165bb525f4SRobert Mustacchi 		ctf_id_t id;
2175bb525f4SRobert Mustacchi 
2185bb525f4SRobert Mustacchi 		if (strcmp(obj, tests[i].cs_symbol) != 0)
2195bb525f4SRobert Mustacchi 			continue;
2205bb525f4SRobert Mustacchi 
2215bb525f4SRobert Mustacchi 		id = ctftest_lookup_type(fp, tests[i].cs_type);
2225bb525f4SRobert Mustacchi 		if (id == CTF_ERR) {
2235bb525f4SRobert Mustacchi 			warnx("failed to lookup type %s for symbol %s",
2245bb525f4SRobert Mustacchi 			    tests[i].cs_type, tests[i].cs_symbol);
2255bb525f4SRobert Mustacchi 			cb->csc_ret = B_FALSE;
2265bb525f4SRobert Mustacchi 			return (0);
2275bb525f4SRobert Mustacchi 		}
2285bb525f4SRobert Mustacchi 
2295bb525f4SRobert Mustacchi 		if (id != type) {
230*8361acf5SRichard Lowe 			warnx("type mismatch for symbol %s, has type id %ld"
231*8361acf5SRichard Lowe 			    ", but specified type %s has id %ld",
2325bb525f4SRobert Mustacchi 			    tests[i].cs_symbol, type, tests[i].cs_type, id);
2335bb525f4SRobert Mustacchi 			cb->csc_ret = B_FALSE;
2345bb525f4SRobert Mustacchi 			return (0);
2355bb525f4SRobert Mustacchi 		}
2365bb525f4SRobert Mustacchi 	}
2375bb525f4SRobert Mustacchi 
2385bb525f4SRobert Mustacchi 	return (0);
2395bb525f4SRobert Mustacchi }
2405bb525f4SRobert Mustacchi 
2415bb525f4SRobert Mustacchi boolean_t
ctftest_check_symbols(ctf_file_t * fp,const check_symbol_t * tests)2425bb525f4SRobert Mustacchi ctftest_check_symbols(ctf_file_t *fp, const check_symbol_t *tests)
2435bb525f4SRobert Mustacchi {
2445bb525f4SRobert Mustacchi 	ctftest_symbol_cb_t cb;
2455bb525f4SRobert Mustacchi 
2465bb525f4SRobert Mustacchi 	cb.csc_fp = fp;
2475bb525f4SRobert Mustacchi 	cb.csc_ret = B_TRUE;
2485bb525f4SRobert Mustacchi 	cb.csc_tests = tests;
2495bb525f4SRobert Mustacchi 	if (ctf_object_iter(fp, ctftest_check_symbol_cb, &cb) != 0)
2505bb525f4SRobert Mustacchi 		return (B_FALSE);
2515bb525f4SRobert Mustacchi 	return (cb.csc_ret);
2525bb525f4SRobert Mustacchi }
2535bb525f4SRobert Mustacchi 
2545bb525f4SRobert Mustacchi 
2555bb525f4SRobert Mustacchi boolean_t
ctftest_check_descent(const char * symbol,ctf_file_t * fp,const check_descent_t * tests,boolean_t quiet)2565bb525f4SRobert Mustacchi ctftest_check_descent(const char *symbol, ctf_file_t *fp,
2576ef284f1SJohn Levon     const check_descent_t *tests, boolean_t quiet)
2585bb525f4SRobert Mustacchi {
2595bb525f4SRobert Mustacchi 	ctf_id_t base;
2605bb525f4SRobert Mustacchi 	uint_t layer = 0;
2615bb525f4SRobert Mustacchi 
2625bb525f4SRobert Mustacchi 	/*
2635bb525f4SRobert Mustacchi 	 * First, find the initial type of the symbol.
2645bb525f4SRobert Mustacchi 	 */
2655bb525f4SRobert Mustacchi 	base = ctftest_lookup_symbol(fp, symbol);
2665bb525f4SRobert Mustacchi 	if (base == CTF_ERR) {
2675bb525f4SRobert Mustacchi 		warnx("failed to lookup type for symbol %s", symbol);
2685bb525f4SRobert Mustacchi 		return (B_FALSE);
2695bb525f4SRobert Mustacchi 	}
2705bb525f4SRobert Mustacchi 
2715bb525f4SRobert Mustacchi 	while (tests->cd_tname != NULL) {
2725bb525f4SRobert Mustacchi 		ctf_id_t tid;
2735bb525f4SRobert Mustacchi 		int kind;
2745bb525f4SRobert Mustacchi 		ctf_arinfo_t ari;
2755bb525f4SRobert Mustacchi 
2765bb525f4SRobert Mustacchi 		if (base == CTF_ERR) {
2776ef284f1SJohn Levon 			if (!quiet) {
2786ef284f1SJohn Levon 				warnx("encountered non-reference type at layer "
2796ef284f1SJohn Levon 				    "%u while still expecting type %s for "
2806ef284f1SJohn Levon 				    "symbol %s", layer,
2816ef284f1SJohn Levon 				    tests->cd_tname, symbol);
2826ef284f1SJohn Levon 			}
2835bb525f4SRobert Mustacchi 			return (B_FALSE);
2845bb525f4SRobert Mustacchi 		}
2855bb525f4SRobert Mustacchi 
2865bb525f4SRobert Mustacchi 		tid = ctftest_lookup_type(fp, tests->cd_tname);
2875bb525f4SRobert Mustacchi 		if (tid == CTF_ERR) {
2886ef284f1SJohn Levon 			if (!quiet) {
2896ef284f1SJohn Levon 				warnx("failed to lookup type %s",
2906ef284f1SJohn Levon 				    tests->cd_tname);
2916ef284f1SJohn Levon 			}
2925bb525f4SRobert Mustacchi 			return (B_FALSE);
2935bb525f4SRobert Mustacchi 		}
2945bb525f4SRobert Mustacchi 
2955bb525f4SRobert Mustacchi 		if (tid != base) {
2966ef284f1SJohn Levon 			if (!quiet) {
297*8361acf5SRichard Lowe 				warnx("type mismatch at layer %u: found "
298*8361acf5SRichard Lowe 				    "id %ld, but expecting type id %ld for "
299*8361acf5SRichard Lowe 				    "type %s, symbol %s", layer, base, tid,
3006ef284f1SJohn Levon 				    tests->cd_tname, symbol);
3016ef284f1SJohn Levon 			}
3025bb525f4SRobert Mustacchi 			return (B_FALSE);
3035bb525f4SRobert Mustacchi 		}
3045bb525f4SRobert Mustacchi 
3055bb525f4SRobert Mustacchi 		kind = ctf_type_kind(fp, base);
3065bb525f4SRobert Mustacchi 		if (kind != tests->cd_kind) {
3076ef284f1SJohn Levon 			if (!quiet) {
3086ef284f1SJohn Levon 				warnx("type kind mismatch at layer %u: found "
3096ef284f1SJohn Levon 				    "kind %u, but expected kind %u for %s, "
3106ef284f1SJohn Levon 				    "symbol %s", layer, kind, tests->cd_kind,
3116ef284f1SJohn Levon 				    tests->cd_tname, symbol);
3126ef284f1SJohn Levon 			}
3135bb525f4SRobert Mustacchi 			return (B_FALSE);
3145bb525f4SRobert Mustacchi 		}
3155bb525f4SRobert Mustacchi 
3165bb525f4SRobert Mustacchi 		switch (kind) {
3175bb525f4SRobert Mustacchi 		case CTF_K_ARRAY:
3185bb525f4SRobert Mustacchi 			if (ctf_array_info(fp, base, &ari) == CTF_ERR) {
3196ef284f1SJohn Levon 				if (!quiet) {
3206ef284f1SJohn Levon 					warnx("failed to lookup array info at "
321*8361acf5SRichard Lowe 					    "layer %ld for type %s, "
3228d195583SRobert Mustacchi 					    "symbol %s: %s", base,
3238d195583SRobert Mustacchi 					    tests->cd_tname, symbol,
3248d195583SRobert Mustacchi 					    ctf_errmsg(ctf_errno(fp)));
3256ef284f1SJohn Levon 				}
3265bb525f4SRobert Mustacchi 				return (B_FALSE);
3275bb525f4SRobert Mustacchi 			}
3285bb525f4SRobert Mustacchi 
3295bb525f4SRobert Mustacchi 			if (tests->cd_nents != ari.ctr_nelems) {
3306ef284f1SJohn Levon 				if (!quiet) {
3316ef284f1SJohn Levon 					warnx("array element mismatch at layer "
3326ef284f1SJohn Levon 					    "%u for type %s, symbol %s: found "
3336ef284f1SJohn Levon 					    "%u, expected %u", layer,
3346ef284f1SJohn Levon 					    tests->cd_tname, symbol,
3356ef284f1SJohn Levon 					    ari.ctr_nelems, tests->cd_nents);
3366ef284f1SJohn Levon 				}
3375bb525f4SRobert Mustacchi 				return (B_FALSE);
3385bb525f4SRobert Mustacchi 			}
3395bb525f4SRobert Mustacchi 
3405bb525f4SRobert Mustacchi 			tid = ctftest_lookup_type(fp, tests->cd_contents);
3415bb525f4SRobert Mustacchi 			if (tid == CTF_ERR) {
3426ef284f1SJohn Levon 				if (!quiet) {
3436ef284f1SJohn Levon 					warnx("failed to look up type %s",
3446ef284f1SJohn Levon 					    tests->cd_contents);
3456ef284f1SJohn Levon 				}
3465bb525f4SRobert Mustacchi 				return (B_FALSE);
3475bb525f4SRobert Mustacchi 			}
3485bb525f4SRobert Mustacchi 
3495bb525f4SRobert Mustacchi 			if (ari.ctr_contents != tid) {
3506ef284f1SJohn Levon 				if (!quiet) {
3516ef284f1SJohn Levon 					warnx("array contents mismatch at "
3526ef284f1SJohn Levon 					    "layer %u for type %s, symbol %s: "
353*8361acf5SRichard Lowe 					    "found %ld, expected %s/%ld",
354*8361acf5SRichard Lowe 					    layer, tests->cd_tname,
3558d195583SRobert Mustacchi 					    symbol, ari.ctr_contents,
3566ef284f1SJohn Levon 					    tests->cd_contents, tid);
3576ef284f1SJohn Levon 				}
3585bb525f4SRobert Mustacchi 				return (B_FALSE);
3595bb525f4SRobert Mustacchi 			}
3605bb525f4SRobert Mustacchi 			base = ari.ctr_contents;
3615bb525f4SRobert Mustacchi 			break;
3625bb525f4SRobert Mustacchi 		default:
3635bb525f4SRobert Mustacchi 			base = ctf_type_reference(fp, base);
3645bb525f4SRobert Mustacchi 			break;
3655bb525f4SRobert Mustacchi 		}
3665bb525f4SRobert Mustacchi 
3675bb525f4SRobert Mustacchi 		tests++;
3685bb525f4SRobert Mustacchi 		layer++;
3695bb525f4SRobert Mustacchi 	}
3705bb525f4SRobert Mustacchi 
3715bb525f4SRobert Mustacchi 	if (base != CTF_ERR) {
3726ef284f1SJohn Levon 		if (!quiet) {
373*8361acf5SRichard Lowe 			warnx("found additional type %ld in chain, "
3746ef284f1SJohn Levon 			    "but expected no more", base);
3756ef284f1SJohn Levon 		}
3765bb525f4SRobert Mustacchi 		return (B_FALSE);
3775bb525f4SRobert Mustacchi 	}
3785bb525f4SRobert Mustacchi 
3795bb525f4SRobert Mustacchi 	return (B_TRUE);
3805bb525f4SRobert Mustacchi }
3815bb525f4SRobert Mustacchi 
3825bb525f4SRobert Mustacchi int
ctftest_check_enum_count(const char * name,int value,void * arg)3835bb525f4SRobert Mustacchi ctftest_check_enum_count(const char *name, int value, void *arg)
3845bb525f4SRobert Mustacchi {
3855bb525f4SRobert Mustacchi 	uint_t *u = arg;
3865bb525f4SRobert Mustacchi 	*u = *u + 1;
3875bb525f4SRobert Mustacchi 	return (0);
3885bb525f4SRobert Mustacchi }
3895bb525f4SRobert Mustacchi 
3905bb525f4SRobert Mustacchi int
ctftest_check_enum_value(const char * name,int value,void * arg)3915bb525f4SRobert Mustacchi ctftest_check_enum_value(const char *name, int value, void *arg)
3925bb525f4SRobert Mustacchi {
3935bb525f4SRobert Mustacchi 	uint_t i;
3945bb525f4SRobert Mustacchi 	const check_enum_t *enums = arg;
3955bb525f4SRobert Mustacchi 
3965bb525f4SRobert Mustacchi 	for (i = 0; enums[i].ce_name != NULL; i++) {
3975bb525f4SRobert Mustacchi 		if (strcmp(enums[i].ce_name, name) != 0)
3985bb525f4SRobert Mustacchi 			continue;
3995bb525f4SRobert Mustacchi 		if (enums[i].ce_value == (int64_t)value)
4005bb525f4SRobert Mustacchi 			return (0);
4015bb525f4SRobert Mustacchi 		warnx("enum %s value mismatch: found %d, expected %" PRId64,
4025bb525f4SRobert Mustacchi 		    name, value, enums[i].ce_value);
4035bb525f4SRobert Mustacchi 		return (1);
4045bb525f4SRobert Mustacchi 	}
4055bb525f4SRobert Mustacchi 
4065bb525f4SRobert Mustacchi 	warnx("found no matching entry for enum member %s", name);
4075bb525f4SRobert Mustacchi 	return (1);
4085bb525f4SRobert Mustacchi }
4095bb525f4SRobert Mustacchi 
4105bb525f4SRobert Mustacchi boolean_t
ctftest_check_enum(const char * type,ctf_file_t * fp,const check_enum_t * enums)4115bb525f4SRobert Mustacchi ctftest_check_enum(const char *type, ctf_file_t *fp, const check_enum_t *enums)
4125bb525f4SRobert Mustacchi {
4135bb525f4SRobert Mustacchi 	int ret;
4145bb525f4SRobert Mustacchi 	uint_t tcount, ecount;
4155bb525f4SRobert Mustacchi 	ctf_id_t base;
4165bb525f4SRobert Mustacchi 
4175bb525f4SRobert Mustacchi 	if ((base = ctftest_lookup_type(fp, type)) == CTF_ERR) {
4185bb525f4SRobert Mustacchi 		warnx("Failed to look up type %s", type);
4195bb525f4SRobert Mustacchi 		return (B_FALSE);
4205bb525f4SRobert Mustacchi 	}
4215bb525f4SRobert Mustacchi 
4225bb525f4SRobert Mustacchi 	if (ctf_type_kind(fp, base) != CTF_K_ENUM) {
4235bb525f4SRobert Mustacchi 		warnx("%s is not an enum", type);
4245bb525f4SRobert Mustacchi 		return (B_FALSE);
4255bb525f4SRobert Mustacchi 	}
4265bb525f4SRobert Mustacchi 
4275bb525f4SRobert Mustacchi 	/*
4285bb525f4SRobert Mustacchi 	 * First count how many entries we have.
4295bb525f4SRobert Mustacchi 	 */
4305bb525f4SRobert Mustacchi 	tcount = 0;
4315bb525f4SRobert Mustacchi 	while (enums[tcount].ce_name != NULL) {
4325bb525f4SRobert Mustacchi 		tcount++;
4335bb525f4SRobert Mustacchi 	}
4345bb525f4SRobert Mustacchi 
4355bb525f4SRobert Mustacchi 	ecount = 0;
4365bb525f4SRobert Mustacchi 	if (ctf_enum_iter(fp, base, ctftest_check_enum_count, &ecount) != 0) {
4375bb525f4SRobert Mustacchi 		warnx("failed to walk enum %s: %s", type,
4385bb525f4SRobert Mustacchi 		    ctf_errmsg(ctf_errno(fp)));
4395bb525f4SRobert Mustacchi 		return (B_FALSE);
4405bb525f4SRobert Mustacchi 	}
4415bb525f4SRobert Mustacchi 
4425bb525f4SRobert Mustacchi 	if (tcount != ecount) {
4435bb525f4SRobert Mustacchi 		warnx("enum value mismatch: expected %u values, but found %u",
4445bb525f4SRobert Mustacchi 		    tcount, ecount);
4455bb525f4SRobert Mustacchi 		return (B_FALSE);
4465bb525f4SRobert Mustacchi 	}
4475bb525f4SRobert Mustacchi 
4485bb525f4SRobert Mustacchi 	if ((ret = ctf_enum_iter(fp, base, ctftest_check_enum_value,
4495bb525f4SRobert Mustacchi 	    (void *)enums)) != 0) {
4505bb525f4SRobert Mustacchi 		if (ret == -1) {
4515bb525f4SRobert Mustacchi 			warnx("failed to walk enum %s: %s", type,
4525bb525f4SRobert Mustacchi 			    ctf_errmsg(ctf_errno(fp)));
4535bb525f4SRobert Mustacchi 		}
4545bb525f4SRobert Mustacchi 		return (B_FALSE);
4555bb525f4SRobert Mustacchi 	}
4565bb525f4SRobert Mustacchi 
4575bb525f4SRobert Mustacchi 	return (B_TRUE);
4585bb525f4SRobert Mustacchi }
4595bb525f4SRobert Mustacchi 
4605bb525f4SRobert Mustacchi int
ctftest_check_member_count(const char * mname,ctf_id_t mtype,ulong_t bitoff,void * arg)4615bb525f4SRobert Mustacchi ctftest_check_member_count(const char *mname, ctf_id_t mtype, ulong_t bitoff,
4625bb525f4SRobert Mustacchi     void *arg)
4635bb525f4SRobert Mustacchi {
4645bb525f4SRobert Mustacchi 	uint_t *countp = arg;
4655bb525f4SRobert Mustacchi 	*countp = *countp + 1;
4665bb525f4SRobert Mustacchi 	return (0);
4675bb525f4SRobert Mustacchi }
4685bb525f4SRobert Mustacchi 
4695bb525f4SRobert Mustacchi int
ctftest_check_members_cb(const char * mname,ctf_id_t mtype,ulong_t bitoff,void * arg)4705bb525f4SRobert Mustacchi ctftest_check_members_cb(const char *mname, ctf_id_t mtype, ulong_t bitoff,
4715bb525f4SRobert Mustacchi     void *arg)
4725bb525f4SRobert Mustacchi {
4735bb525f4SRobert Mustacchi 	uint_t i;
4745bb525f4SRobert Mustacchi 	const ctftest_member_cb_t *cmc = arg;
4755bb525f4SRobert Mustacchi 	const check_member_t *members = cmc->cmc_members;
4765bb525f4SRobert Mustacchi 	ctf_file_t *fp = cmc->cmc_fp;
4775bb525f4SRobert Mustacchi 
4785bb525f4SRobert Mustacchi 	for (i = 0; members[i].cm_name != NULL; i++) {
4795bb525f4SRobert Mustacchi 		boolean_t bad = B_FALSE;
4805bb525f4SRobert Mustacchi 		char buf[2048];
4815bb525f4SRobert Mustacchi 
4825bb525f4SRobert Mustacchi 		if (strcmp(mname, members[i].cm_name) != 0)
4835bb525f4SRobert Mustacchi 			continue;
4845bb525f4SRobert Mustacchi 
4855bb525f4SRobert Mustacchi 		if (bitoff != members[i].cm_offset) {
4865bb525f4SRobert Mustacchi 			warnx("member %s of type %s has mismatched bit offset: "
4875bb525f4SRobert Mustacchi 			    "found %lu, expected %lu", mname, cmc->cmc_name,
4885bb525f4SRobert Mustacchi 			    bitoff, members[i].cm_offset);
4895bb525f4SRobert Mustacchi 			bad = B_TRUE;
4905bb525f4SRobert Mustacchi 		}
4915bb525f4SRobert Mustacchi 
4925bb525f4SRobert Mustacchi 		if (ctf_type_name(fp, mtype, buf, sizeof (buf)) == NULL) {
4938d195583SRobert Mustacchi 			warnx("failed to obtain type name for member %s: %s",
4945bb525f4SRobert Mustacchi 			    mname, ctf_errmsg(ctf_errno(fp)));
4955bb525f4SRobert Mustacchi 			bad = B_TRUE;
4965bb525f4SRobert Mustacchi 		} else if (strcmp(buf, members[i].cm_type) != 0) {
4975bb525f4SRobert Mustacchi 			warnx("member %s has bad type, found %s, expected %s",
4985bb525f4SRobert Mustacchi 			    mname, buf, members[i].cm_type);
4995bb525f4SRobert Mustacchi 			bad = B_TRUE;
5005bb525f4SRobert Mustacchi 		}
5015bb525f4SRobert Mustacchi 
5025bb525f4SRobert Mustacchi 		return (bad ? 1 : 0);
5035bb525f4SRobert Mustacchi 	}
5045bb525f4SRobert Mustacchi 
5055bb525f4SRobert Mustacchi 	warnx("found no matching entry for member %s of type %s", mname,
5065bb525f4SRobert Mustacchi 	    cmc->cmc_name);
5075bb525f4SRobert Mustacchi 	return (1);
5085bb525f4SRobert Mustacchi }
5095bb525f4SRobert Mustacchi 
5105bb525f4SRobert Mustacchi boolean_t
ctftest_check_members(const char * type,ctf_file_t * fp,int kind,size_t size,const check_member_t * members)5115bb525f4SRobert Mustacchi ctftest_check_members(const char *type, ctf_file_t *fp, int kind,
5125bb525f4SRobert Mustacchi     size_t size, const check_member_t *members)
5135bb525f4SRobert Mustacchi {
5145bb525f4SRobert Mustacchi 	int ret;
5155bb525f4SRobert Mustacchi 	uint_t tcount, mcount;
5165bb525f4SRobert Mustacchi 	ctf_id_t base;
5175bb525f4SRobert Mustacchi 	ctftest_member_cb_t cmc;
5185bb525f4SRobert Mustacchi 
5195bb525f4SRobert Mustacchi 	if ((base = ctftest_lookup_type(fp, type)) == CTF_ERR) {
5205bb525f4SRobert Mustacchi 		warnx("failed to look up type %s", type);
5215bb525f4SRobert Mustacchi 		return (B_FALSE);
5225bb525f4SRobert Mustacchi 	}
5235bb525f4SRobert Mustacchi 
5245bb525f4SRobert Mustacchi 	if (ctf_type_kind(fp, base) != kind) {
5255bb525f4SRobert Mustacchi 		warnx("%s has kind %s, expected %s", type,
5265bb525f4SRobert Mustacchi 		    ctf_kind_name(fp, ctf_type_kind(fp, base)),
5275bb525f4SRobert Mustacchi 		    ctf_kind_name(fp, kind));
5285bb525f4SRobert Mustacchi 		return (B_FALSE);
5295bb525f4SRobert Mustacchi 	}
5305bb525f4SRobert Mustacchi 
5315bb525f4SRobert Mustacchi 	if (size != ctf_type_size(fp, base)) {
5328d195583SRobert Mustacchi 		warnx("%s has bad size, expected %zu, found %zd",
5335bb525f4SRobert Mustacchi 		    type, size, ctf_type_size(fp, base));
5345bb525f4SRobert Mustacchi 		return (B_FALSE);
5355bb525f4SRobert Mustacchi 	}
5365bb525f4SRobert Mustacchi 
5375bb525f4SRobert Mustacchi 	/*
5385bb525f4SRobert Mustacchi 	 * First count how many entries we have.
5395bb525f4SRobert Mustacchi 	 */
5405bb525f4SRobert Mustacchi 	tcount = 0;
5415bb525f4SRobert Mustacchi 	while (members[tcount].cm_name != NULL) {
5425bb525f4SRobert Mustacchi 		tcount++;
5435bb525f4SRobert Mustacchi 	}
5445bb525f4SRobert Mustacchi 
5455bb525f4SRobert Mustacchi 	mcount = 0;
5465bb525f4SRobert Mustacchi 	if (ctf_member_iter(fp, base, ctftest_check_member_count, &mcount) !=
5475bb525f4SRobert Mustacchi 	    0) {
5485bb525f4SRobert Mustacchi 		warnx("failed to walk members of %s: %s", type,
5495bb525f4SRobert Mustacchi 		    ctf_errmsg(ctf_errno(fp)));
5505bb525f4SRobert Mustacchi 		return (B_FALSE);
5515bb525f4SRobert Mustacchi 	}
5525bb525f4SRobert Mustacchi 
5535bb525f4SRobert Mustacchi 	if (tcount != mcount) {
5545bb525f4SRobert Mustacchi 		warnx("type member mismatch: expected %u values, but found %u",
5555bb525f4SRobert Mustacchi 		    tcount, mcount);
5565bb525f4SRobert Mustacchi 		return (B_FALSE);
5575bb525f4SRobert Mustacchi 	}
5585bb525f4SRobert Mustacchi 
5595bb525f4SRobert Mustacchi 	cmc.cmc_fp = fp;
5605bb525f4SRobert Mustacchi 	cmc.cmc_members = members;
5615bb525f4SRobert Mustacchi 	cmc.cmc_name = type;
5625bb525f4SRobert Mustacchi 	if ((ret = ctf_member_iter(fp, base, ctftest_check_members_cb,
5635bb525f4SRobert Mustacchi 	    &cmc)) != 0) {
5645bb525f4SRobert Mustacchi 		if (ret == -1) {
5655bb525f4SRobert Mustacchi 			warnx("failed to walk type %s: %s", type,
5665bb525f4SRobert Mustacchi 			    ctf_errmsg(ctf_errno(fp)));
5675bb525f4SRobert Mustacchi 		}
5685bb525f4SRobert Mustacchi 		return (B_FALSE);
5695bb525f4SRobert Mustacchi 	}
5705bb525f4SRobert Mustacchi 
5715bb525f4SRobert Mustacchi 	return (B_TRUE);
5725bb525f4SRobert Mustacchi }
5735bb525f4SRobert Mustacchi 
5745bb525f4SRobert Mustacchi boolean_t
ctftest_check_function(const char * symbol,ctf_file_t * fp,const char * rtype,uint_t nargs,uint_t flags,const char ** argv)5755bb525f4SRobert Mustacchi ctftest_check_function(const char *symbol, ctf_file_t *fp, const char *rtype,
5765bb525f4SRobert Mustacchi     uint_t nargs, uint_t flags, const char **argv)
5775bb525f4SRobert Mustacchi {
5785bb525f4SRobert Mustacchi 	ulong_t sym;
5795bb525f4SRobert Mustacchi 	ctf_funcinfo_t fi;
5805bb525f4SRobert Mustacchi 	uint_t i;
5815bb525f4SRobert Mustacchi 	boolean_t ret = B_TRUE;
5825bb525f4SRobert Mustacchi 	ctf_id_t *args;
5835bb525f4SRobert Mustacchi 	char buf[2048];
5845bb525f4SRobert Mustacchi 
5855bb525f4SRobert Mustacchi 
5865bb525f4SRobert Mustacchi 	if (!ctftest_lookup_function(fp, symbol, &sym, &fi)) {
5875bb525f4SRobert Mustacchi 		warnx("failed to look up function %s", symbol);
5885bb525f4SRobert Mustacchi 		return (B_FALSE);
5895bb525f4SRobert Mustacchi 	}
5905bb525f4SRobert Mustacchi 
5915bb525f4SRobert Mustacchi 	if (ctf_type_name(fp, fi.ctc_return, buf, sizeof (buf)) == NULL) {
5925bb525f4SRobert Mustacchi 		warnx("failed to lookup return type name for function %s",
5935bb525f4SRobert Mustacchi 		    symbol);
5945bb525f4SRobert Mustacchi 		ret = B_FALSE;
5955bb525f4SRobert Mustacchi 	} else if (strcmp(rtype, buf) != 0) {
5965bb525f4SRobert Mustacchi 		warnx("return type has wrong type: found %s, expected %s",
5975bb525f4SRobert Mustacchi 		    buf, rtype);
5985bb525f4SRobert Mustacchi 		ret = B_FALSE;
5995bb525f4SRobert Mustacchi 	}
6005bb525f4SRobert Mustacchi 
6015bb525f4SRobert Mustacchi 	if (nargs != fi.ctc_argc) {
6025bb525f4SRobert Mustacchi 		warnx("function argument mismatch: found %u, expected %u",
6035bb525f4SRobert Mustacchi 		    fi.ctc_argc, nargs);
6045bb525f4SRobert Mustacchi 		ret = B_FALSE;
6055bb525f4SRobert Mustacchi 	}
6065bb525f4SRobert Mustacchi 
6075bb525f4SRobert Mustacchi 	if (flags != fi.ctc_flags) {
6085bb525f4SRobert Mustacchi 		warnx("function flags mismatch, found 0x%x, expected 0x%x",
6095bb525f4SRobert Mustacchi 		    fi.ctc_flags, flags);
6105bb525f4SRobert Mustacchi 		ret = B_FALSE;
6115bb525f4SRobert Mustacchi 	}
6125bb525f4SRobert Mustacchi 
6135bb525f4SRobert Mustacchi 	if (!ret || fi.ctc_argc == 0) {
6145bb525f4SRobert Mustacchi 		return (ret);
6155bb525f4SRobert Mustacchi 	}
6165bb525f4SRobert Mustacchi 
6175bb525f4SRobert Mustacchi 	if ((args = calloc(fi.ctc_argc, sizeof (ctf_id_t))) == NULL) {
6185bb525f4SRobert Mustacchi 		warnx("failed to allocate memory for function arguments");
6195bb525f4SRobert Mustacchi 		return (B_FALSE);
6205bb525f4SRobert Mustacchi 	}
6215bb525f4SRobert Mustacchi 
6225bb525f4SRobert Mustacchi 	if (ctf_func_args(fp, sym, fi.ctc_argc, args) != 0) {
6235bb525f4SRobert Mustacchi 		warnx("failed to get function information: %s",
6245bb525f4SRobert Mustacchi 		    ctf_errmsg(ctf_errno(fp)));
6255bb525f4SRobert Mustacchi 		free(args);
6265bb525f4SRobert Mustacchi 		return (B_FALSE);
6275bb525f4SRobert Mustacchi 	}
6285bb525f4SRobert Mustacchi 
6295bb525f4SRobert Mustacchi 	for (i = 0; i < fi.ctc_argc; i++) {
6305bb525f4SRobert Mustacchi 		if (ctf_type_name(fp, args[i], buf, sizeof (buf)) == NULL) {
6318d195583SRobert Mustacchi 			warnx("failed to obtain type name for argument %u: %s",
6325bb525f4SRobert Mustacchi 			    i, ctf_errmsg(ctf_errno(fp)));
6335bb525f4SRobert Mustacchi 			ret = B_FALSE;
6345bb525f4SRobert Mustacchi 			break;
6355bb525f4SRobert Mustacchi 		}
6365bb525f4SRobert Mustacchi 
6375bb525f4SRobert Mustacchi 		if (strcmp(buf, argv[i]) != 0) {
6385bb525f4SRobert Mustacchi 			warnx("argument %u has wrong type: found %s, "
6395bb525f4SRobert Mustacchi 			    "expected %s", i, buf, argv[i]);
6405bb525f4SRobert Mustacchi 			ret = B_FALSE;
6415bb525f4SRobert Mustacchi 			break;
6425bb525f4SRobert Mustacchi 		}
6435bb525f4SRobert Mustacchi 	}
6445bb525f4SRobert Mustacchi 
6455bb525f4SRobert Mustacchi 	free(args);
6465bb525f4SRobert Mustacchi 	return (ret);
6475bb525f4SRobert Mustacchi }
6485bb525f4SRobert Mustacchi 
6495bb525f4SRobert Mustacchi boolean_t
ctftest_check_fptr(const char * type,ctf_file_t * fp,const char * rtype,uint_t nargs,uint_t flags,const char ** argv)6505bb525f4SRobert Mustacchi ctftest_check_fptr(const char *type, ctf_file_t *fp, const char *rtype,
6515bb525f4SRobert Mustacchi     uint_t nargs, uint_t flags, const char **argv)
6525bb525f4SRobert Mustacchi {
6535bb525f4SRobert Mustacchi 	ctf_id_t tid;
6545bb525f4SRobert Mustacchi 	ctf_funcinfo_t fi;
6555bb525f4SRobert Mustacchi 	uint_t i;
6565bb525f4SRobert Mustacchi 	boolean_t ret = B_TRUE;
6575bb525f4SRobert Mustacchi 	ctf_id_t *args;
6585bb525f4SRobert Mustacchi 	char buf[2048];
6595bb525f4SRobert Mustacchi 
6605bb525f4SRobert Mustacchi 
6615bb525f4SRobert Mustacchi 	if ((tid = ctf_lookup_by_name(fp, type)) == CTF_ERR) {
6625bb525f4SRobert Mustacchi 		warnx("failed to look up type %s: %s", type,
6635bb525f4SRobert Mustacchi 		    ctf_errmsg(ctf_errno(fp)));
6645bb525f4SRobert Mustacchi 		return (B_FALSE);
6655bb525f4SRobert Mustacchi 	}
6665bb525f4SRobert Mustacchi 
6675bb525f4SRobert Mustacchi 	/*
6685bb525f4SRobert Mustacchi 	 * Perform two CTF type resolves, one for the function pointer and one
6695bb525f4SRobert Mustacchi 	 * for the typedef that gets passed in.
6705bb525f4SRobert Mustacchi 	 */
6715bb525f4SRobert Mustacchi 	if ((tid = ctf_type_resolve(fp, tid)) == CTF_ERR) {
6725bb525f4SRobert Mustacchi 		warnx("failed to convert type %s to base type: %s", type,
6735bb525f4SRobert Mustacchi 		    ctf_errmsg(ctf_errno(fp)));
6745bb525f4SRobert Mustacchi 		return (B_FALSE);
6755bb525f4SRobert Mustacchi 	}
6765bb525f4SRobert Mustacchi 
6775bb525f4SRobert Mustacchi 	if (ctf_type_kind(fp, tid) == CTF_K_POINTER &&
6785bb525f4SRobert Mustacchi 	    (tid = ctf_type_reference(fp, tid)) == CTF_ERR) {
6795bb525f4SRobert Mustacchi 		warnx("failed to convert type %s to base type: %s", type,
6805bb525f4SRobert Mustacchi 		    ctf_errmsg(ctf_errno(fp)));
6815bb525f4SRobert Mustacchi 		return (B_FALSE);
6825bb525f4SRobert Mustacchi 	}
6835bb525f4SRobert Mustacchi 
6845bb525f4SRobert Mustacchi 	if (ctf_func_info_by_id(fp, tid, &fi) != 0) {
6855bb525f4SRobert Mustacchi 		warnx("failed to get function information for type %s: %s",
6865bb525f4SRobert Mustacchi 		    type, ctf_errmsg(ctf_errno(fp)));
6875bb525f4SRobert Mustacchi 		return (B_FALSE);
6885bb525f4SRobert Mustacchi 	}
6895bb525f4SRobert Mustacchi 
6905bb525f4SRobert Mustacchi 	if (ctf_type_name(fp, fi.ctc_return, buf, sizeof (buf)) == NULL) {
6915bb525f4SRobert Mustacchi 		warnx("failed to lookup return type name for function %s",
6925bb525f4SRobert Mustacchi 		    type);
6935bb525f4SRobert Mustacchi 		ret = B_FALSE;
6945bb525f4SRobert Mustacchi 	} else if (strcmp(rtype, buf) != 0) {
6955bb525f4SRobert Mustacchi 		warnx("return type has wrong type: found %s, expected %s",
6965bb525f4SRobert Mustacchi 		    buf, rtype);
6975bb525f4SRobert Mustacchi 		ret = B_FALSE;
6985bb525f4SRobert Mustacchi 	}
6995bb525f4SRobert Mustacchi 
7005bb525f4SRobert Mustacchi 	if (nargs != fi.ctc_argc) {
7015bb525f4SRobert Mustacchi 		warnx("function argument mismatch: found %u, expected %u",
7025bb525f4SRobert Mustacchi 		    fi.ctc_argc, nargs);
7035bb525f4SRobert Mustacchi 		ret = B_FALSE;
7045bb525f4SRobert Mustacchi 	}
7055bb525f4SRobert Mustacchi 
7065bb525f4SRobert Mustacchi 	if (flags != fi.ctc_flags) {
7075bb525f4SRobert Mustacchi 		warnx("function flags mismatch, found 0x%x, expected 0x%x",
7085bb525f4SRobert Mustacchi 		    fi.ctc_flags, flags);
7095bb525f4SRobert Mustacchi 		ret = B_FALSE;
7105bb525f4SRobert Mustacchi 	}
7115bb525f4SRobert Mustacchi 
7125bb525f4SRobert Mustacchi 	if (!ret || fi.ctc_argc == 0) {
7135bb525f4SRobert Mustacchi 		return (ret);
7145bb525f4SRobert Mustacchi 	}
7155bb525f4SRobert Mustacchi 
7165bb525f4SRobert Mustacchi 	if ((args = calloc(fi.ctc_argc, sizeof (ctf_id_t))) == NULL) {
7175bb525f4SRobert Mustacchi 		warnx("failed to allocate memory for function arguments");
7185bb525f4SRobert Mustacchi 		return (B_FALSE);
7195bb525f4SRobert Mustacchi 	}
7205bb525f4SRobert Mustacchi 
7215bb525f4SRobert Mustacchi 	if (ctf_func_args_by_id(fp, tid, fi.ctc_argc, args) != 0) {
7225bb525f4SRobert Mustacchi 		warnx("failed to get function information: %s",
7235bb525f4SRobert Mustacchi 		    ctf_errmsg(ctf_errno(fp)));
7245bb525f4SRobert Mustacchi 		free(args);
7255bb525f4SRobert Mustacchi 		return (B_FALSE);
7265bb525f4SRobert Mustacchi 	}
7275bb525f4SRobert Mustacchi 
7285bb525f4SRobert Mustacchi 	for (i = 0; i < fi.ctc_argc; i++) {
7295bb525f4SRobert Mustacchi 		if (ctf_type_name(fp, args[i], buf, sizeof (buf)) == NULL) {
7308d195583SRobert Mustacchi 			warnx("failed to obtain type name for argument %u: %s",
7315bb525f4SRobert Mustacchi 			    i, ctf_errmsg(ctf_errno(fp)));
7325bb525f4SRobert Mustacchi 			ret = B_FALSE;
7335bb525f4SRobert Mustacchi 			break;
7345bb525f4SRobert Mustacchi 		}
7355bb525f4SRobert Mustacchi 
7365bb525f4SRobert Mustacchi 		if (strcmp(buf, argv[i]) != 0) {
7375bb525f4SRobert Mustacchi 			warnx("argument %u has wrong type: found %s, "
7385bb525f4SRobert Mustacchi 			    "expected %s", i, buf, argv[i]);
7395bb525f4SRobert Mustacchi 			ret = B_FALSE;
7405bb525f4SRobert Mustacchi 			break;
7415bb525f4SRobert Mustacchi 		}
7425bb525f4SRobert Mustacchi 	}
7435bb525f4SRobert Mustacchi 
7445bb525f4SRobert Mustacchi 	free(args);
7455bb525f4SRobert Mustacchi 	return (ret);
7465bb525f4SRobert Mustacchi }
7475bb525f4SRobert Mustacchi 
748fe2dc8bdSJohn Levon boolean_t
ctftest_check_size(const char * type,ctf_file_t * fp,size_t size)749fe2dc8bdSJohn Levon ctftest_check_size(const char *type, ctf_file_t *fp, size_t size)
750fe2dc8bdSJohn Levon {
751fe2dc8bdSJohn Levon 	ctf_id_t base;
752fe2dc8bdSJohn Levon 
753fe2dc8bdSJohn Levon 	if ((base = ctftest_lookup_type(fp, type)) == CTF_ERR) {
754fe2dc8bdSJohn Levon 		warnx("Failed to look up type %s", type);
755fe2dc8bdSJohn Levon 		return (B_FALSE);
756fe2dc8bdSJohn Levon 	}
757fe2dc8bdSJohn Levon 
758fe2dc8bdSJohn Levon 	if (size != ctf_type_size(fp, base)) {
7598d195583SRobert Mustacchi 		warnx("%s has bad size, expected %zu, found %zd",
760fe2dc8bdSJohn Levon 		    type, size, ctf_type_size(fp, base));
761fe2dc8bdSJohn Levon 		return (B_FALSE);
762fe2dc8bdSJohn Levon 	}
763fe2dc8bdSJohn Levon 
764fe2dc8bdSJohn Levon 	return (B_TRUE);
765fe2dc8bdSJohn Levon }
766fe2dc8bdSJohn Levon 
7675bb525f4SRobert Mustacchi typedef struct ctftest_duplicates {
7685bb525f4SRobert Mustacchi 	ctf_file_t *ctd_fp;
7695bb525f4SRobert Mustacchi 	char **ctd_names;
7705bb525f4SRobert Mustacchi 	size_t ctd_len;
7715bb525f4SRobert Mustacchi 	size_t ctd_curent;
7725bb525f4SRobert Mustacchi 	boolean_t ctd_ret;
7735bb525f4SRobert Mustacchi } ctftest_duplicates_t;
7745bb525f4SRobert Mustacchi 
7755bb525f4SRobert Mustacchi static int
ctftest_duplicates_cb(ctf_id_t id,boolean_t root,void * arg)7765bb525f4SRobert Mustacchi ctftest_duplicates_cb(ctf_id_t id, boolean_t root, void *arg)
7775bb525f4SRobert Mustacchi {
7785bb525f4SRobert Mustacchi 	char buf[2048];
7795bb525f4SRobert Mustacchi 	ctftest_duplicates_t *dup = arg;
7805bb525f4SRobert Mustacchi 	size_t i;
7815bb525f4SRobert Mustacchi 
7825bb525f4SRobert Mustacchi 	if (ctf_type_name(dup->ctd_fp, id, buf, sizeof (buf)) == NULL) {
7835bb525f4SRobert Mustacchi 		warnx("failed to lookup name for id %ld", id);
7845bb525f4SRobert Mustacchi 		dup->ctd_ret = B_FALSE;
7855bb525f4SRobert Mustacchi 		return (1);
7865bb525f4SRobert Mustacchi 	}
7875bb525f4SRobert Mustacchi 
7885bb525f4SRobert Mustacchi 	for (i = 0; i < dup->ctd_curent; i++) {
7895bb525f4SRobert Mustacchi 		if (strcmp(buf, dup->ctd_names[i]) == 0) {
7905bb525f4SRobert Mustacchi 			warnx("encountered duplicate type '%s'", buf);
7915bb525f4SRobert Mustacchi 			dup->ctd_ret = B_FALSE;
7925bb525f4SRobert Mustacchi 			/*
7935bb525f4SRobert Mustacchi 			 * Don't break out of the loop and keep going in case we
7945bb525f4SRobert Mustacchi 			 * find another duplicate.
7955bb525f4SRobert Mustacchi 			 */
7965bb525f4SRobert Mustacchi 			return (0);
7975bb525f4SRobert Mustacchi 		}
7985bb525f4SRobert Mustacchi 	}
7995bb525f4SRobert Mustacchi 
8005bb525f4SRobert Mustacchi 	if (dup->ctd_curent == dup->ctd_len) {
8015bb525f4SRobert Mustacchi 		char **n;
8025bb525f4SRobert Mustacchi 		size_t newlen = dup->ctd_len * 2;
8035bb525f4SRobert Mustacchi 
8045bb525f4SRobert Mustacchi 		n = recallocarray(dup->ctd_names, dup->ctd_len, newlen,
8055bb525f4SRobert Mustacchi 		    sizeof (char *));
8065bb525f4SRobert Mustacchi 		if (n == NULL) {
8075bb525f4SRobert Mustacchi 			warnx("failed to resize type name array");
8085bb525f4SRobert Mustacchi 			dup->ctd_ret = B_FALSE;
8095bb525f4SRobert Mustacchi 			return (1);
8105bb525f4SRobert Mustacchi 		}
8115bb525f4SRobert Mustacchi 
8125bb525f4SRobert Mustacchi 		dup->ctd_names = n;
8135bb525f4SRobert Mustacchi 		dup->ctd_len = newlen;
8145bb525f4SRobert Mustacchi 	}
8155bb525f4SRobert Mustacchi 
8165bb525f4SRobert Mustacchi 	dup->ctd_names[dup->ctd_curent] = strdup(buf);
8175bb525f4SRobert Mustacchi 	if (dup->ctd_names[dup->ctd_curent] == NULL) {
8185bb525f4SRobert Mustacchi 		warn("failed to duplicate type name");
8195bb525f4SRobert Mustacchi 		dup->ctd_ret = B_FALSE;
8205bb525f4SRobert Mustacchi 		return (1);
8215bb525f4SRobert Mustacchi 	}
8225bb525f4SRobert Mustacchi 	dup->ctd_curent++;
8235bb525f4SRobert Mustacchi 
8245bb525f4SRobert Mustacchi 	return (0);
8255bb525f4SRobert Mustacchi }
8265bb525f4SRobert Mustacchi 
8275bb525f4SRobert Mustacchi boolean_t
ctftest_duplicates(ctf_file_t * fp)8285bb525f4SRobert Mustacchi ctftest_duplicates(ctf_file_t *fp)
8295bb525f4SRobert Mustacchi {
8305bb525f4SRobert Mustacchi 	size_t i;
8315bb525f4SRobert Mustacchi 	ctftest_duplicates_t d;
8325bb525f4SRobert Mustacchi 
8335bb525f4SRobert Mustacchi 	bzero(&d, sizeof (d));
8345bb525f4SRobert Mustacchi 	d.ctd_fp = fp;
8355bb525f4SRobert Mustacchi 	d.ctd_len = 4;
8365bb525f4SRobert Mustacchi 	d.ctd_ret = B_TRUE;
8375bb525f4SRobert Mustacchi 	d.ctd_names = recallocarray(NULL, 0, d.ctd_len, sizeof (char *));
8385bb525f4SRobert Mustacchi 	if (d.ctd_names == NULL) {
8395bb525f4SRobert Mustacchi 		warnx("failed to allocate duplicate name storage");
8405bb525f4SRobert Mustacchi 		return (B_FALSE);
8415bb525f4SRobert Mustacchi 	}
8425bb525f4SRobert Mustacchi 
8435bb525f4SRobert Mustacchi 	(void) ctf_type_iter(fp, B_TRUE, ctftest_duplicates_cb, &d);
8445bb525f4SRobert Mustacchi 
8455bb525f4SRobert Mustacchi 	for (i = 0; i < d.ctd_curent; i++) {
8465bb525f4SRobert Mustacchi 		free(d.ctd_names[i]);
8475bb525f4SRobert Mustacchi 	}
8485bb525f4SRobert Mustacchi 	free(d.ctd_names);
8495bb525f4SRobert Mustacchi 
8505bb525f4SRobert Mustacchi 	return (d.ctd_ret);
8515bb525f4SRobert Mustacchi }
8523cec9822SRobert Mustacchi 
8533cec9822SRobert Mustacchi boolean_t
ctftest_skip(check_skip_t skip)8543cec9822SRobert Mustacchi ctftest_skip(check_skip_t skip)
8553cec9822SRobert Mustacchi {
8563cec9822SRobert Mustacchi 	const char *compiler;
8573cec9822SRobert Mustacchi 
8583cec9822SRobert Mustacchi 	if (skip == 0) {
8593cec9822SRobert Mustacchi 		return (B_FALSE);
8603cec9822SRobert Mustacchi 	}
8613cec9822SRobert Mustacchi 
8623cec9822SRobert Mustacchi 	compiler = getenv("ctf_cc_type");
8633cec9822SRobert Mustacchi 	if (compiler == NULL) {
8643cec9822SRobert Mustacchi 		return (B_FALSE);
8653cec9822SRobert Mustacchi 	}
8663cec9822SRobert Mustacchi 
8673cec9822SRobert Mustacchi 	if ((skip & SKIP_CLANG) != 0 && strcmp(compiler, "clang") == 0)
8683cec9822SRobert Mustacchi 		return (B_TRUE);
8693cec9822SRobert Mustacchi 
8703cec9822SRobert Mustacchi 	return (B_FALSE);
8713cec9822SRobert Mustacchi }
872