xref: /titanic_44/usr/src/cmd/tnf/tnfdump/cooked.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  *	Copyright (c) 1994, by Sun Microsytems, Inc.
24*7c478bd9Sstevel@tonic-gate  */
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate #include <unistd.h>
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
31*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/mman.h>
33*7c478bd9Sstevel@tonic-gate #include <stdio.h>
34*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
35*7c478bd9Sstevel@tonic-gate #include <string.h>
36*7c478bd9Sstevel@tonic-gate #include <unistd.h>
37*7c478bd9Sstevel@tonic-gate #include <tnf/tnf.h>
38*7c478bd9Sstevel@tonic-gate #include <errno.h>
39*7c478bd9Sstevel@tonic-gate #include <libintl.h>
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include "state.h"
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate #define	STREQ(s1, s2, n)	(strncmp(s1, s2, n) == 0)
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #define	IS_64BIT(kind)	((1 << kind) &	\
46*7c478bd9Sstevel@tonic-gate 				((1 << TNF_K_UINT64) | (1 << TNF_K_INT64)))
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #define	PROBE_TYPE	"tnf_probe_type"
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate static void print_event			(entry_t *ent);
51*7c478bd9Sstevel@tonic-gate static void insert_event		(tnf_datum_t, tnf_datum_t);
52*7c478bd9Sstevel@tonic-gate static void describe_c_brief		(tnf_datum_t);
53*7c478bd9Sstevel@tonic-gate static void describe_target		(tnf_datum_t);
54*7c478bd9Sstevel@tonic-gate static void describe_c_struct		(tnf_datum_t);
55*7c478bd9Sstevel@tonic-gate static void describe_probe_type		(tnf_datum_t);
56*7c478bd9Sstevel@tonic-gate static void describe_event		(tnf_datum_t, tnf_datum_t, hrtime_t);
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate static hrtime_t		base_time = 0;
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate void
print_c_header(void)61*7c478bd9Sstevel@tonic-gate print_c_header(void)
62*7c478bd9Sstevel@tonic-gate {
63*7c478bd9Sstevel@tonic-gate 	(void) printf("%16s %16s %5s %5s %10s %3s %-25s %s\n",
64*7c478bd9Sstevel@tonic-gate 		"----------------", "----------------", "-----", "-----",
65*7c478bd9Sstevel@tonic-gate 		"----------", "---", "-------------------------",
66*7c478bd9Sstevel@tonic-gate 		"------------------------");
67*7c478bd9Sstevel@tonic-gate 	(void) printf("%16s %16s %5s %5s %10s %3s %-25s %s\n",
68*7c478bd9Sstevel@tonic-gate 		"Elapsed (ms)", "Delta (ms)", "PID", "LWPID",
69*7c478bd9Sstevel@tonic-gate 		"   TID    ", "CPU", "Probe Name", "Data / Description . . .");
70*7c478bd9Sstevel@tonic-gate 	(void) printf("%16s %16s %5s %5s %10s %3s %-25s %s\n",
71*7c478bd9Sstevel@tonic-gate 		"----------------", "----------------", "-----", "-----",
72*7c478bd9Sstevel@tonic-gate 		"----------", "---", "-------------------------",
73*7c478bd9Sstevel@tonic-gate 		"------------------------");
74*7c478bd9Sstevel@tonic-gate }
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate static void
print_event(entry_t * ent)77*7c478bd9Sstevel@tonic-gate print_event(entry_t *ent)
78*7c478bd9Sstevel@tonic-gate {
79*7c478bd9Sstevel@tonic-gate 	tnf_datum_t	evt, sched;
80*7c478bd9Sstevel@tonic-gate 	hrtime_t	normalized_time;
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate 	evt = ent->record;
83*7c478bd9Sstevel@tonic-gate 	sched = tnf_get_tag_arg(evt);
84*7c478bd9Sstevel@tonic-gate 	if (sched == TNF_DATUM_NULL) {
85*7c478bd9Sstevel@tonic-gate 		/*
86*7c478bd9Sstevel@tonic-gate 		 * should never happen because it had a schedule
87*7c478bd9Sstevel@tonic-gate 		 * record earlier
88*7c478bd9Sstevel@tonic-gate 		 */
89*7c478bd9Sstevel@tonic-gate 		fail(0, gettext("event without a schedule record"));
90*7c478bd9Sstevel@tonic-gate 	}
91*7c478bd9Sstevel@tonic-gate 	normalized_time = ent->time - base_time;
92*7c478bd9Sstevel@tonic-gate 	describe_event(evt, sched, normalized_time);
93*7c478bd9Sstevel@tonic-gate }
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate void
print_sorted_events(void)96*7c478bd9Sstevel@tonic-gate print_sorted_events(void)
97*7c478bd9Sstevel@tonic-gate {
98*7c478bd9Sstevel@tonic-gate 	entry_t 	*ent;
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 	table_sort();
101*7c478bd9Sstevel@tonic-gate 	ent = table_get_entry_indexed(0);
102*7c478bd9Sstevel@tonic-gate 	if (ent) {
103*7c478bd9Sstevel@tonic-gate 		base_time = ent->time;
104*7c478bd9Sstevel@tonic-gate 	}
105*7c478bd9Sstevel@tonic-gate 	table_print(&print_event);
106*7c478bd9Sstevel@tonic-gate }
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate void
describe_c_record(tnf_datum_t datum)109*7c478bd9Sstevel@tonic-gate describe_c_record(tnf_datum_t datum)
110*7c478bd9Sstevel@tonic-gate {
111*7c478bd9Sstevel@tonic-gate 	char		*name_str;
112*7c478bd9Sstevel@tonic-gate 	tnf_datum_t	schedule_rec;
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 	switch (tnf_get_kind(datum)) {
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	case TNF_K_STRUCT:
117*7c478bd9Sstevel@tonic-gate 		/* print only event records */
118*7c478bd9Sstevel@tonic-gate 		schedule_rec = tnf_get_tag_arg(datum);
119*7c478bd9Sstevel@tonic-gate 		if (schedule_rec != TNF_DATUM_NULL) {
120*7c478bd9Sstevel@tonic-gate 			/* event record */
121*7c478bd9Sstevel@tonic-gate 			insert_event(datum, schedule_rec);
122*7c478bd9Sstevel@tonic-gate 		}
123*7c478bd9Sstevel@tonic-gate 		break;
124*7c478bd9Sstevel@tonic-gate 	case TNF_K_STRING:
125*7c478bd9Sstevel@tonic-gate 	case TNF_K_ARRAY:
126*7c478bd9Sstevel@tonic-gate 		/* Skip arrays at top level */
127*7c478bd9Sstevel@tonic-gate 		break;
128*7c478bd9Sstevel@tonic-gate 	case TNF_K_TYPE:
129*7c478bd9Sstevel@tonic-gate 		name_str = tnf_get_type_name(datum);
130*7c478bd9Sstevel@tonic-gate 		/* REMIND: filter based on property */
131*7c478bd9Sstevel@tonic-gate 		if (STREQ(name_str, PROBE_TYPE, strlen(name_str)))
132*7c478bd9Sstevel@tonic-gate 			describe_probe_type(datum);
133*7c478bd9Sstevel@tonic-gate 		break;
134*7c478bd9Sstevel@tonic-gate 	default:
135*7c478bd9Sstevel@tonic-gate 		fail(0, gettext("illegal record at %x (%d)"),
136*7c478bd9Sstevel@tonic-gate 			tnf_get_raw(datum), tnf_get_kind(datum));
137*7c478bd9Sstevel@tonic-gate 		break;
138*7c478bd9Sstevel@tonic-gate 	}
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate }
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate static void
describe_probe_type(tnf_datum_t datum)143*7c478bd9Sstevel@tonic-gate describe_probe_type(tnf_datum_t datum)
144*7c478bd9Sstevel@tonic-gate {
145*7c478bd9Sstevel@tonic-gate 	unsigned 	n, i;
146*7c478bd9Sstevel@tonic-gate 	char 		*slotname;
147*7c478bd9Sstevel@tonic-gate 	size_t		slot_len;
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 	n = tnf_get_slot_count(datum);
150*7c478bd9Sstevel@tonic-gate #if 0
151*7c478bd9Sstevel@tonic-gate 	/* print the OUTPUT PAD */
152*7c478bd9Sstevel@tonic-gate 	(void) printf("%16s %14s %5s %5s %8s %3s %-25s",
153*7c478bd9Sstevel@tonic-gate 			"-", "-", "-", "-", "-", "-", "-");
154*7c478bd9Sstevel@tonic-gate #endif
155*7c478bd9Sstevel@tonic-gate 	(void) printf("probe\t");
156*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
157*7c478bd9Sstevel@tonic-gate 		slotname = tnf_get_slot_name(datum, i);
158*7c478bd9Sstevel@tonic-gate 		slot_len = strlen(slotname);
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 		/* print all fields except ... */
161*7c478bd9Sstevel@tonic-gate 		if ((!STREQ(slotname, TNF_N_TAG, slot_len)) &&
162*7c478bd9Sstevel@tonic-gate 			(!STREQ(slotname, TNF_N_PROPERTIES, slot_len)) &&
163*7c478bd9Sstevel@tonic-gate 			(!STREQ(slotname, TNF_N_SLOT_TYPES, slot_len)) &&
164*7c478bd9Sstevel@tonic-gate 			(!STREQ(slotname, TNF_N_TYPE_SIZE, slot_len)) &&
165*7c478bd9Sstevel@tonic-gate 			(!STREQ(slotname, TNF_N_SLOT_NAMES, slot_len))) {
166*7c478bd9Sstevel@tonic-gate 				(void) printf(" ");
167*7c478bd9Sstevel@tonic-gate 				(void) printf("%s: ", slotname);
168*7c478bd9Sstevel@tonic-gate 				describe_c_brief(tnf_get_slot_indexed(datum,
169*7c478bd9Sstevel@tonic-gate 							i));
170*7c478bd9Sstevel@tonic-gate 		}
171*7c478bd9Sstevel@tonic-gate 	}
172*7c478bd9Sstevel@tonic-gate 	(void) printf("\n");
173*7c478bd9Sstevel@tonic-gate }
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate static void
insert_event(tnf_datum_t datum,tnf_datum_t schedule_rec)176*7c478bd9Sstevel@tonic-gate insert_event(tnf_datum_t datum, tnf_datum_t schedule_rec)
177*7c478bd9Sstevel@tonic-gate {
178*7c478bd9Sstevel@tonic-gate 	tnf_datum_t	temp;
179*7c478bd9Sstevel@tonic-gate 	hrtime_t	evt_time;
180*7c478bd9Sstevel@tonic-gate 	unsigned	time_delta = 0;
181*7c478bd9Sstevel@tonic-gate 	entry_t		element;
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	temp = tnf_get_slot_named(schedule_rec, TNF_N_TIME_BASE);
184*7c478bd9Sstevel@tonic-gate 	evt_time = tnf_get_int64(temp);
185*7c478bd9Sstevel@tonic-gate 	temp = tnf_get_slot_named(datum, TNF_N_TIME_DELTA);
186*7c478bd9Sstevel@tonic-gate 	time_delta = (unsigned) tnf_get_int32(temp);
187*7c478bd9Sstevel@tonic-gate 	evt_time = evt_time + time_delta;
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	element.time = evt_time;
190*7c478bd9Sstevel@tonic-gate 	element.record = datum;
191*7c478bd9Sstevel@tonic-gate 	table_insert(&element);
192*7c478bd9Sstevel@tonic-gate }
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate #define	K_TID	"tnf_kthread_id"
195*7c478bd9Sstevel@tonic-gate #define	CPUID	"cpuid"
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate static void
describe_event(tnf_datum_t datum,tnf_datum_t schedule_rec,hrtime_t evt_time)198*7c478bd9Sstevel@tonic-gate describe_event(tnf_datum_t datum, tnf_datum_t schedule_rec, hrtime_t evt_time)
199*7c478bd9Sstevel@tonic-gate {
200*7c478bd9Sstevel@tonic-gate 	unsigned 	n, i;
201*7c478bd9Sstevel@tonic-gate 	char 		*slotname, *eventname, *tidtype;
202*7c478bd9Sstevel@tonic-gate 	tnf_datum_t	temp;
203*7c478bd9Sstevel@tonic-gate 	int		lwpid = 0, pid = 0;
204*7c478bd9Sstevel@tonic-gate 	int		start_slots = 0;
205*7c478bd9Sstevel@tonic-gate 	static hrtime_t	last_time = 0;
206*7c478bd9Sstevel@tonic-gate 	unsigned long long	tid = 0;
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	temp = tnf_get_slot_named(schedule_rec, TNF_N_TID);
209*7c478bd9Sstevel@tonic-gate 	if (IS_64BIT(tnf_get_kind(temp))) {
210*7c478bd9Sstevel@tonic-gate 		tid = tnf_get_int64(temp);
211*7c478bd9Sstevel@tonic-gate 	} else {
212*7c478bd9Sstevel@tonic-gate 		tid = (unsigned int)tnf_get_int32(temp);
213*7c478bd9Sstevel@tonic-gate 	}
214*7c478bd9Sstevel@tonic-gate 	tidtype = tnf_get_type_name(temp);
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 	temp = tnf_get_slot_named(schedule_rec, TNF_N_LWPID);
217*7c478bd9Sstevel@tonic-gate 	lwpid = tnf_get_int32(temp);
218*7c478bd9Sstevel@tonic-gate 	temp = tnf_get_slot_named(schedule_rec, TNF_N_PID);
219*7c478bd9Sstevel@tonic-gate 	pid = tnf_get_int32(temp);
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate 	/* XXX should use TNF_N_KERNEL_SCHEDULE, TNF_N_USER_SCHEDULE */
222*7c478bd9Sstevel@tonic-gate 	if (strcmp(tidtype, K_TID) == 0) {
223*7c478bd9Sstevel@tonic-gate 		int 	cpuid;
224*7c478bd9Sstevel@tonic-gate 		/* XXX Assumes cpuid always exists in kernel schedule */
225*7c478bd9Sstevel@tonic-gate 		cpuid = tnf_get_int32(tnf_get_slot_named(schedule_rec, CPUID));
226*7c478bd9Sstevel@tonic-gate 		/* print the OUTPUT schedule record for Kernel case */
227*7c478bd9Sstevel@tonic-gate 		(void) printf("%16.6f %16.6f %5u %5u 0x%-8llx %3d",
228*7c478bd9Sstevel@tonic-gate 			evt_time / 1000000.0,
229*7c478bd9Sstevel@tonic-gate 			(evt_time - last_time)/1000000.0,
230*7c478bd9Sstevel@tonic-gate 			pid, lwpid, tid, cpuid);
231*7c478bd9Sstevel@tonic-gate 	} else {
232*7c478bd9Sstevel@tonic-gate 		/* print the OUTPUT schedule record */
233*7c478bd9Sstevel@tonic-gate 		(void) printf("%16.6f %16.6f %5u %5u %10llu %3s",
234*7c478bd9Sstevel@tonic-gate 			evt_time / 1000000.0,
235*7c478bd9Sstevel@tonic-gate 			(evt_time - last_time)/1000000.0,
236*7c478bd9Sstevel@tonic-gate 			pid, lwpid, tid, "-");
237*7c478bd9Sstevel@tonic-gate 	}
238*7c478bd9Sstevel@tonic-gate 	/* print the tag */
239*7c478bd9Sstevel@tonic-gate 	eventname = tnf_type_get_name(tnf_get_slot_named(datum, TNF_N_TAG));
240*7c478bd9Sstevel@tonic-gate 	(void) printf(" %-25s", eventname);
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	/* heuristic - start of data is after TIME_DELTA field */
243*7c478bd9Sstevel@tonic-gate 	start_slots = tnf_get_slot_index(datum, TNF_N_TIME_DELTA);
244*7c478bd9Sstevel@tonic-gate 	start_slots++;
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	n = tnf_get_slot_count(datum);
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 	/* print the rest of the fields */
249*7c478bd9Sstevel@tonic-gate 	for (i = start_slots; i < n; i++) {
250*7c478bd9Sstevel@tonic-gate 		(void) printf(" ");
251*7c478bd9Sstevel@tonic-gate 		slotname = tnf_get_slot_name(datum, i);
252*7c478bd9Sstevel@tonic-gate 		(void) printf("%s: ", slotname);
253*7c478bd9Sstevel@tonic-gate 		describe_target(tnf_get_slot_indexed(datum, i));
254*7c478bd9Sstevel@tonic-gate 	}
255*7c478bd9Sstevel@tonic-gate 	(void) printf("\n");
256*7c478bd9Sstevel@tonic-gate 	last_time = evt_time;
257*7c478bd9Sstevel@tonic-gate }
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate static void
describe_c_struct(tnf_datum_t datum)260*7c478bd9Sstevel@tonic-gate describe_c_struct(tnf_datum_t datum)
261*7c478bd9Sstevel@tonic-gate {
262*7c478bd9Sstevel@tonic-gate 	unsigned 	n, i, tag_index;
263*7c478bd9Sstevel@tonic-gate 	char 		*slotname;
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	n = tnf_get_slot_count(datum);
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate 	/* print the tag */
268*7c478bd9Sstevel@tonic-gate 	(void) printf(" ");
269*7c478bd9Sstevel@tonic-gate 	(void) printf("%s: ", "type");
270*7c478bd9Sstevel@tonic-gate 	describe_c_brief(tnf_get_slot_named(datum, TNF_N_TAG));
271*7c478bd9Sstevel@tonic-gate 	tag_index = tnf_get_slot_index(datum, TNF_N_TAG);
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
274*7c478bd9Sstevel@tonic-gate 		/* print the rest of the members */
275*7c478bd9Sstevel@tonic-gate 		if (i != tag_index) {
276*7c478bd9Sstevel@tonic-gate 			(void) printf(" ");
277*7c478bd9Sstevel@tonic-gate 			slotname = tnf_get_slot_name(datum, i);
278*7c478bd9Sstevel@tonic-gate 			(void) printf("%s: ", slotname);
279*7c478bd9Sstevel@tonic-gate 			describe_target(tnf_get_slot_indexed(datum, i));
280*7c478bd9Sstevel@tonic-gate 		}
281*7c478bd9Sstevel@tonic-gate 	}
282*7c478bd9Sstevel@tonic-gate }
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate static void
describe_c_brief(tnf_datum_t datum)285*7c478bd9Sstevel@tonic-gate describe_c_brief(tnf_datum_t datum)
286*7c478bd9Sstevel@tonic-gate {
287*7c478bd9Sstevel@tonic-gate 	if (datum == TNF_DATUM_NULL) /* allowed */
288*7c478bd9Sstevel@tonic-gate 		(void) printf("0x%-8x <NULL>", 0);
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate 	else if (tnf_is_scalar(datum))
291*7c478bd9Sstevel@tonic-gate 		describe_scalar(datum);
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 	else if (tnf_is_record(datum)) {
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 		switch (tnf_get_kind(datum)) {
296*7c478bd9Sstevel@tonic-gate 		case TNF_K_TYPE:
297*7c478bd9Sstevel@tonic-gate 			(void) printf("%s", tnf_type_get_name(datum));
298*7c478bd9Sstevel@tonic-gate 			break;
299*7c478bd9Sstevel@tonic-gate 		case TNF_K_STRING:
300*7c478bd9Sstevel@tonic-gate 			(void) printf("\"%s\"", tnf_get_chars(datum));
301*7c478bd9Sstevel@tonic-gate 			break;
302*7c478bd9Sstevel@tonic-gate 		default:
303*7c478bd9Sstevel@tonic-gate 			(void) printf("<%s>", tnf_get_type_name(datum));
304*7c478bd9Sstevel@tonic-gate 		}
305*7c478bd9Sstevel@tonic-gate 	} else
306*7c478bd9Sstevel@tonic-gate 		fail(0, gettext("inline aggregate slots/elements unhandled"));
307*7c478bd9Sstevel@tonic-gate }
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate static void
describe_target(tnf_datum_t datum)310*7c478bd9Sstevel@tonic-gate describe_target(tnf_datum_t datum)
311*7c478bd9Sstevel@tonic-gate {
312*7c478bd9Sstevel@tonic-gate 	if (datum == TNF_DATUM_NULL) /* allowed */
313*7c478bd9Sstevel@tonic-gate 		(void) printf("0x%-8x <NULL>", 0);
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate 	else if (tnf_is_scalar(datum))
316*7c478bd9Sstevel@tonic-gate 		describe_scalar(datum);
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	else if (tnf_is_record(datum)) {
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 		switch (tnf_get_kind(datum)) {
321*7c478bd9Sstevel@tonic-gate 		case TNF_K_STRUCT:
322*7c478bd9Sstevel@tonic-gate 			(void) printf("{");
323*7c478bd9Sstevel@tonic-gate 			describe_c_struct(datum);
324*7c478bd9Sstevel@tonic-gate 			(void) printf(" }");
325*7c478bd9Sstevel@tonic-gate 			break;
326*7c478bd9Sstevel@tonic-gate 		case TNF_K_TYPE:
327*7c478bd9Sstevel@tonic-gate 			(void) printf("%s", tnf_type_get_name(datum));
328*7c478bd9Sstevel@tonic-gate 			break;
329*7c478bd9Sstevel@tonic-gate 		case TNF_K_STRING:
330*7c478bd9Sstevel@tonic-gate 			(void) printf("\"%s\"", tnf_get_chars(datum));
331*7c478bd9Sstevel@tonic-gate 			break;
332*7c478bd9Sstevel@tonic-gate 		default:
333*7c478bd9Sstevel@tonic-gate 			(void) printf("<%s>", tnf_get_type_name(datum));
334*7c478bd9Sstevel@tonic-gate 		}
335*7c478bd9Sstevel@tonic-gate 	} else
336*7c478bd9Sstevel@tonic-gate 		fail(0, gettext("inline aggregate slots/elements unhandled"));
337*7c478bd9Sstevel@tonic-gate }
338