xref: /onnv-gate/usr/src/tools/ctf/stabs/common/fth_struct.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * Used to dump structures and unions in forth mode.
31*0Sstevel@tonic-gate  *
32*0Sstevel@tonic-gate  * structures and unions are a bit more complicated than enums.  To make things
33*0Sstevel@tonic-gate  * just that much more interesting, we have to dump the members in reverse
34*0Sstevel@tonic-gate  * order, which is nice.  But wait!  It gets better!  For compatibility reasons,
35*0Sstevel@tonic-gate  * we need to dump the members in reverse-offset order, even if member-specific
36*0Sstevel@tonic-gate  * mode was used to request the members in something other than that order.
37*0Sstevel@tonic-gate  *
38*0Sstevel@tonic-gate  * The header op prints the macro header and saves the type being printed.
39*0Sstevel@tonic-gate  *
40*0Sstevel@tonic-gate  * In member-specific mode, the member op will be invoked for each structure
41*0Sstevel@tonic-gate  * or union member.  The member op adds the member name, format, type ID,
42*0Sstevel@tonic-gate  * and offset to a list, sorted in reverse order by offset.
43*0Sstevel@tonic-gate  *
44*0Sstevel@tonic-gate  * The trailer op is called when the structure or enum is complete.  If no
45*0Sstevel@tonic-gate  * members were specifically requested, then the trailer iterates through all
46*0Sstevel@tonic-gate  * of the members of the structure, pretending they were.  Each member is thus
47*0Sstevel@tonic-gate  * added, in reverse-offset order, to the list used in specific-member mode.
48*0Sstevel@tonic-gate  * Either way, we then proceed through the list, dumping each member out with
49*0Sstevel@tonic-gate  * fth_print_member.  Structure and union members are printed out differently,
50*0Sstevel@tonic-gate  * depending on member type, as follows:
51*0Sstevel@tonic-gate  *
52*0Sstevel@tonic-gate  *  Integer:
53*0Sstevel@tonic-gate  *	Normal integers: ' <format> <offset> <type>-field <name>
54*0Sstevel@tonic-gate  *	  <format> defaults to ".d" for enums, ".x" for others
55*0Sstevel@tonic-gate  *	  <offset> is the member offset, in bytes.
56*0Sstevel@tonic-gate  *	  <type> is "byte", "short", "long", or "ext" for 8-, 16-, 32-, and
57*0Sstevel@tonic-gate  *	    64-bit integers, respectively.
58*0Sstevel@tonic-gate  *	  <name> is the name of the member being printed
59*0Sstevel@tonic-gate  *
60*0Sstevel@tonic-gate  *	Bitfields:	 ' <format> <shift> <mask> <offset> bits-field <name>
61*0Sstevel@tonic-gate  *	  <format> defaults to ".x"
62*0Sstevel@tonic-gate  *	  <shift> is the number of times to right-shift the masked value
63*0Sstevel@tonic-gate  *	  <mask> use to extract the bit-field value from the read value
64*0Sstevel@tonic-gate  *	  <offset> is the member offset, in bytes
65*0Sstevel@tonic-gate  *	  <name> is the name of the member being printed
66*0Sstevel@tonic-gate  *
67*0Sstevel@tonic-gate  *  Float:		Ignored
68*0Sstevel@tonic-gate  *
69*0Sstevel@tonic-gate  *  Pointer:		 ' <format> <offset> ptr-field <name>
70*0Sstevel@tonic-gate  *	  <format> defaults to .x
71*0Sstevel@tonic-gate  *	  <offset> is in bytes
72*0Sstevel@tonic-gate  *	  <name> is the name of the member being printed
73*0Sstevel@tonic-gate  *
74*0Sstevel@tonic-gate  *  Array:
75*0Sstevel@tonic-gate  *	Arrays have a content-type-specific prefix, followed by an array
76*0Sstevel@tonic-gate  *	suffix.  The resulting line looks like this if the array contents
77*0Sstevel@tonic-gate  *	type is an integer, a pointer, or an enum:
78*0Sstevel@tonic-gate  *
79*0Sstevel@tonic-gate  *			 ' <fldc> ' <fmt> <sz> <elsz> <off> array-field <name>
80*0Sstevel@tonic-gate  *
81*0Sstevel@tonic-gate  *	The following is printed for array contents that are arrays:
82*0Sstevel@tonic-gate  *
83*0Sstevel@tonic-gate  *			 ' noop ' .x <sz> <elsz> <off> array-field <name>
84*0Sstevel@tonic-gate  *
85*0Sstevel@tonic-gate  *	The following is printed for array contents that are structs:
86*0Sstevel@tonic-gate  *
87*0Sstevel@tonic-gate  *			 ' noop ' <fmt> <sz> <elsz> <off> array-field <name>
88*0Sstevel@tonic-gate  *
89*0Sstevel@tonic-gate  *	  <fldc> is "c@", "w@", "l@", or "x@", depending on whether array
90*0Sstevel@tonic-gate  *	    elements are 8, 16, 32 or 64 bits wide.
91*0Sstevel@tonic-gate  *	  <fmt> defaults to ".x"
92*0Sstevel@tonic-gate  *	  <sz> is the size of the array, in bytes
93*0Sstevel@tonic-gate  *	  <elsz> is the size of the array elements
94*0Sstevel@tonic-gate  *	  <off> is the member offset, in bytes
95*0Sstevel@tonic-gate  *	  <name> is the nam eof the member being printed
96*0Sstevel@tonic-gate  *
97*0Sstevel@tonic-gate  *  Struct/Union:	 ' <format> <offset> struct-field <name>
98*0Sstevel@tonic-gate  *	  <format> defaults to ".x"
99*0Sstevel@tonic-gate  *	  <offset> is the member offset, in bytes
100*0Sstevel@tonic-gate  *	  <name> is the name of the member being printed
101*0Sstevel@tonic-gate  */
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate #include <stdio.h>
104*0Sstevel@tonic-gate #include <stdlib.h>
105*0Sstevel@tonic-gate #include <string.h>
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate #include "ctf_headers.h"
108*0Sstevel@tonic-gate #include "forth.h"
109*0Sstevel@tonic-gate #include "list.h"
110*0Sstevel@tonic-gate #include "memory.h"
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate static ctf_id_t	fth_str_curtid;
113*0Sstevel@tonic-gate static list_t	*fth_str_curmems;
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate /*
116*0Sstevel@tonic-gate  * Node type for the member-storage list (fth_str_curmems) built by
117*0Sstevel@tonic-gate  * fth_struct_members()
118*0Sstevel@tonic-gate  */
119*0Sstevel@tonic-gate typedef struct fth_str_mem {
120*0Sstevel@tonic-gate 	char		*fsm_memname;
121*0Sstevel@tonic-gate 	char		*fsm_format;
122*0Sstevel@tonic-gate 	ctf_id_t	fsm_tid;
123*0Sstevel@tonic-gate 	ulong_t		fsm_off;
124*0Sstevel@tonic-gate } fth_str_mem_t;
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate typedef struct fth_struct_members_data {
127*0Sstevel@tonic-gate 	char		*fsmd_strname;
128*0Sstevel@tonic-gate 	char		*fsmd_memfilter;
129*0Sstevel@tonic-gate 	char		*fsmd_format;
130*0Sstevel@tonic-gate 	int		fsmd_matched;
131*0Sstevel@tonic-gate } fth_struct_members_data_t;
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate static int fth_print_member(fth_str_mem_t *, int);
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate /* Comparison routined used to insert members into the fth_str_curmems list */
136*0Sstevel@tonic-gate static int
fth_struct_memcmp(void * m1,void * m2)137*0Sstevel@tonic-gate fth_struct_memcmp(void *m1, void *m2)
138*0Sstevel@tonic-gate {
139*0Sstevel@tonic-gate 	fth_str_mem_t *mem1 = m1, *mem2 = m2;
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate 	if (mem1->fsm_off < mem2->fsm_off)
142*0Sstevel@tonic-gate 		return (1);
143*0Sstevel@tonic-gate 	else if (mem1->fsm_off > mem2->fsm_off)
144*0Sstevel@tonic-gate 		return (-1);
145*0Sstevel@tonic-gate 	else
146*0Sstevel@tonic-gate 		return (0);
147*0Sstevel@tonic-gate }
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate static void
fth_free_str_mem(fth_str_mem_t * mem)150*0Sstevel@tonic-gate fth_free_str_mem(fth_str_mem_t *mem)
151*0Sstevel@tonic-gate {
152*0Sstevel@tonic-gate 	free(mem->fsm_memname);
153*0Sstevel@tonic-gate 	if (mem->fsm_format)
154*0Sstevel@tonic-gate 		free(mem->fsm_format);
155*0Sstevel@tonic-gate 	free(mem);
156*0Sstevel@tonic-gate }
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate static int
fth_struct_header(ctf_id_t tid)159*0Sstevel@tonic-gate fth_struct_header(ctf_id_t tid)
160*0Sstevel@tonic-gate {
161*0Sstevel@tonic-gate 	ssize_t sz;
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate 	fth_str_curtid = tid;
164*0Sstevel@tonic-gate 	fth_str_curmems = NULL;
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	if ((sz = ctf_type_size(ctf, fth_str_curtid)) == CTF_ERR)
167*0Sstevel@tonic-gate 		return (parse_warn("Can't get size for %s", fth_curtype));
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	(void) fprintf(out, "\n");
170*0Sstevel@tonic-gate 	(void) fprintf(out, "vocabulary %s-words\n", fth_curtype);
171*0Sstevel@tonic-gate 	(void) fprintf(out, "h# %x constant %s-sz\n", sz, fth_curtype);
172*0Sstevel@tonic-gate 	(void) fprintf(out, "%x ' %s-words c-struct .%s\n", sz, fth_curtype,
173*0Sstevel@tonic-gate 	    fth_curtype);
174*0Sstevel@tonic-gate 	(void) fprintf(out, "also %s-words definitions\n\n", fth_curtype);
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	return (0);
177*0Sstevel@tonic-gate }
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate /* Print the array prefix for integer and pointer members */
180*0Sstevel@tonic-gate static int
fth_print_level(uint_t bits,char * format)181*0Sstevel@tonic-gate fth_print_level(uint_t bits, char *format)
182*0Sstevel@tonic-gate {
183*0Sstevel@tonic-gate 	if ((bits & (bits - 1)) != 0 ||(bits % 8) != 0 || bits > 64) {
184*0Sstevel@tonic-gate 		return (parse_warn("Unexpected bit size %d in %s",
185*0Sstevel@tonic-gate 		    bits, fth_curtype));
186*0Sstevel@tonic-gate 	}
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	(void) fprintf(out, "' %c@ ' %s", " cw l   x"[bits / 8], format);
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate 	return (0);
191*0Sstevel@tonic-gate }
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate /*
194*0Sstevel@tonic-gate  * Return the format to be used to print the member.  If one of the builtin
195*0Sstevel@tonic-gate  * formats "d" or "x" were specified, return ".d" or ".x", respectively.
196*0Sstevel@tonic-gate  * Otherwise, use the user-provided format as is, or use the default if none
197*0Sstevel@tonic-gate  * was provided.
198*0Sstevel@tonic-gate  */
199*0Sstevel@tonic-gate static char *
fth_convert_format(char * format,char * def)200*0Sstevel@tonic-gate fth_convert_format(char *format, char *def)
201*0Sstevel@tonic-gate {
202*0Sstevel@tonic-gate 	static char dot[3] = ".";
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 	if (format == NULL)
205*0Sstevel@tonic-gate 		return (def);
206*0Sstevel@tonic-gate 	else if (strlen(format) == 1) {
207*0Sstevel@tonic-gate 		dot[1] = *format;
208*0Sstevel@tonic-gate 		return (dot);
209*0Sstevel@tonic-gate 	} else
210*0Sstevel@tonic-gate 		return (format);
211*0Sstevel@tonic-gate }
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate static int
fth_print_integer(const char * memname,ulong_t off,uint_t bits,char * format,int level)214*0Sstevel@tonic-gate fth_print_integer(const char *memname, ulong_t off, uint_t bits, char *format,
215*0Sstevel@tonic-gate     int level)
216*0Sstevel@tonic-gate {
217*0Sstevel@tonic-gate 	format = fth_convert_format(format, ".x");
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate 	if (bits > 64) {
220*0Sstevel@tonic-gate 		return (parse_warn("%s.%s is too large (>8 bytes)",
221*0Sstevel@tonic-gate 		    fth_curtype, memname));
222*0Sstevel@tonic-gate 	}
223*0Sstevel@tonic-gate 
224*0Sstevel@tonic-gate 	if (level != 0)
225*0Sstevel@tonic-gate 		return (fth_print_level(bits, format));
226*0Sstevel@tonic-gate 
227*0Sstevel@tonic-gate 	if ((bits % NBBY) != 0 || (bits & (bits - 1)) != 0) {
228*0Sstevel@tonic-gate 		/* bit field */
229*0Sstevel@tonic-gate 		uint_t offset, shift, mask;
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate 		offset = (off / 32) * 4;
232*0Sstevel@tonic-gate 		shift = 32 - ((off % 32) + bits);
233*0Sstevel@tonic-gate 		mask = ((1 << bits) - 1) << shift;
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 		(void) fprintf(out, "' %s %x %x %x bits-field %s\n",
236*0Sstevel@tonic-gate 		    format, shift, mask, offset, memname);
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 	} else {
239*0Sstevel@tonic-gate 		char *type[] = {
240*0Sstevel@tonic-gate 			NULL, "byte", "short", NULL, "long",
241*0Sstevel@tonic-gate 			NULL, NULL, NULL, "ext"
242*0Sstevel@tonic-gate 		};
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate 		(void) fprintf(out, "' %s %lx %s-field %s\n", format, off / 8,
245*0Sstevel@tonic-gate 		    type[bits / 8], memname);
246*0Sstevel@tonic-gate 	}
247*0Sstevel@tonic-gate 
248*0Sstevel@tonic-gate 	return (0);
249*0Sstevel@tonic-gate }
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate static int
fth_print_pointer(const char * memname,ulong_t off,uint_t bits,char * format,int level)252*0Sstevel@tonic-gate fth_print_pointer(const char *memname, ulong_t off, uint_t bits, char *format,
253*0Sstevel@tonic-gate     int level)
254*0Sstevel@tonic-gate {
255*0Sstevel@tonic-gate 	format = fth_convert_format(format, ".x");
256*0Sstevel@tonic-gate 
257*0Sstevel@tonic-gate 	if (level != 0)
258*0Sstevel@tonic-gate 		return (fth_print_level(bits, format));
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	(void) fprintf(out, "' %s %lx ptr-field %s\n", format, off / 8,
261*0Sstevel@tonic-gate 	    memname);
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 	return (0);
264*0Sstevel@tonic-gate }
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate static int
fth_print_struct(char * memname,ulong_t off,char * format,int level)267*0Sstevel@tonic-gate fth_print_struct(char *memname, ulong_t off, char *format,
268*0Sstevel@tonic-gate     int level)
269*0Sstevel@tonic-gate {
270*0Sstevel@tonic-gate 	format = fth_convert_format(format, ".x");
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate 	if (level != 0)
273*0Sstevel@tonic-gate 		(void) fprintf(out, "' noop ' %s", format);
274*0Sstevel@tonic-gate 	else {
275*0Sstevel@tonic-gate 		(void) fprintf(out, "' %s %lx struct-field %s\n", format,
276*0Sstevel@tonic-gate 		    off / 8, memname);
277*0Sstevel@tonic-gate 	}
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate 	return (0);
280*0Sstevel@tonic-gate }
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate static int
fth_print_enum(char * memname,ulong_t off,char * format,int level)283*0Sstevel@tonic-gate fth_print_enum(char *memname, ulong_t off, char *format,
284*0Sstevel@tonic-gate     int level)
285*0Sstevel@tonic-gate {
286*0Sstevel@tonic-gate 	format = fth_convert_format(format, ".d");
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate 	if (level != 0)
289*0Sstevel@tonic-gate 		(void) fprintf(out, "' l@ ' %s", format);
290*0Sstevel@tonic-gate 	else {
291*0Sstevel@tonic-gate 		(void) fprintf(out, "' %s %lx long-field %s\n", format, off / 8,
292*0Sstevel@tonic-gate 		    memname);
293*0Sstevel@tonic-gate 	}
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate 	return (0);
296*0Sstevel@tonic-gate }
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate static int
fth_print_array(char * memname,ctf_id_t tid,ulong_t off,ssize_t sz,char * format,int level)299*0Sstevel@tonic-gate fth_print_array(char *memname, ctf_id_t tid, ulong_t off, ssize_t sz,
300*0Sstevel@tonic-gate     char *format, int level)
301*0Sstevel@tonic-gate {
302*0Sstevel@tonic-gate 	if (level != 0)
303*0Sstevel@tonic-gate 		(void) fprintf(out, "' noop ' .x");
304*0Sstevel@tonic-gate 	else {
305*0Sstevel@tonic-gate 		fth_str_mem_t mem;
306*0Sstevel@tonic-gate 		ctf_arinfo_t ar;
307*0Sstevel@tonic-gate 
308*0Sstevel@tonic-gate 		/*
309*0Sstevel@tonic-gate 		 * print the prefix for the array contents type, then print
310*0Sstevel@tonic-gate 		 * the array macro
311*0Sstevel@tonic-gate 		 */
312*0Sstevel@tonic-gate 
313*0Sstevel@tonic-gate 		if (ctf_array_info(ctf, tid, &ar) == CTF_ERR) {
314*0Sstevel@tonic-gate 			return (parse_warn("Can't read array in %s.%s",
315*0Sstevel@tonic-gate 			    fth_curtype, memname));
316*0Sstevel@tonic-gate 		}
317*0Sstevel@tonic-gate 
318*0Sstevel@tonic-gate 		mem.fsm_memname = memname;
319*0Sstevel@tonic-gate 		mem.fsm_format = format;
320*0Sstevel@tonic-gate 		mem.fsm_tid = ar.ctr_contents;
321*0Sstevel@tonic-gate 		mem.fsm_off = off;
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate 		if (fth_print_member(&mem, level + 1) < 0)
324*0Sstevel@tonic-gate 			return (-1);
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate 		(void) fprintf(out, " %x %x %lx array-field %s\n", sz,
327*0Sstevel@tonic-gate 		    (sz / ar.ctr_nelems), off / 8, memname);
328*0Sstevel@tonic-gate 	}
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate 	return (0);
331*0Sstevel@tonic-gate }
332*0Sstevel@tonic-gate 
333*0Sstevel@tonic-gate /* dump a structure or union member */
334*0Sstevel@tonic-gate static int
fth_print_member(fth_str_mem_t * mem,int level)335*0Sstevel@tonic-gate fth_print_member(fth_str_mem_t *mem, int level)
336*0Sstevel@tonic-gate {
337*0Sstevel@tonic-gate 	ctf_encoding_t e;
338*0Sstevel@tonic-gate 	ctf_id_t tid;
339*0Sstevel@tonic-gate 	int kind;
340*0Sstevel@tonic-gate 	ssize_t sz;
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 	if ((tid = ctf_type_resolve(ctf, mem->fsm_tid)) == CTF_ERR) {
343*0Sstevel@tonic-gate 		return (parse_warn("Can't resolve %s.%s", fth_curtype,
344*0Sstevel@tonic-gate 		    mem->fsm_memname));
345*0Sstevel@tonic-gate 	}
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 	if ((kind = ctf_type_kind(ctf, tid)) == CTF_ERR) {
348*0Sstevel@tonic-gate 		return (parse_warn("Can't get kind for %s.%s",
349*0Sstevel@tonic-gate 		    fth_curtype, mem->fsm_memname));
350*0Sstevel@tonic-gate 	}
351*0Sstevel@tonic-gate 
352*0Sstevel@tonic-gate 	if ((sz = ctf_type_size(ctf, tid)) == CTF_ERR) {
353*0Sstevel@tonic-gate 		return (parse_warn("Can't get size for %s.%s",
354*0Sstevel@tonic-gate 		    fth_curtype, mem->fsm_memname));
355*0Sstevel@tonic-gate 	}
356*0Sstevel@tonic-gate 
357*0Sstevel@tonic-gate 	switch (kind) {
358*0Sstevel@tonic-gate 	case CTF_K_INTEGER:
359*0Sstevel@tonic-gate 		if (ctf_type_encoding(ctf, tid, &e) == CTF_ERR)
360*0Sstevel@tonic-gate 			return (parse_warn("Can't get encoding for %ld", tid));
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 		return (fth_print_integer(mem->fsm_memname, mem->fsm_off,
363*0Sstevel@tonic-gate 		    e.cte_bits, mem->fsm_format, level));
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 	case CTF_K_FLOAT:
366*0Sstevel@tonic-gate 		(void) parse_warn("Ignoring floating point member %s.%s",
367*0Sstevel@tonic-gate 		    fth_curtype, mem->fsm_memname);
368*0Sstevel@tonic-gate 		return (0);
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate 	case CTF_K_POINTER:
371*0Sstevel@tonic-gate 		return (fth_print_pointer(mem->fsm_memname, mem->fsm_off,
372*0Sstevel@tonic-gate 		    sz * 8, mem->fsm_format, level));
373*0Sstevel@tonic-gate 
374*0Sstevel@tonic-gate 	case CTF_K_ARRAY:
375*0Sstevel@tonic-gate 		return (fth_print_array(mem->fsm_memname, tid, mem->fsm_off, sz,
376*0Sstevel@tonic-gate 		    mem->fsm_format, level));
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate 	case CTF_K_STRUCT:
379*0Sstevel@tonic-gate 	case CTF_K_UNION:
380*0Sstevel@tonic-gate 		return (fth_print_struct(mem->fsm_memname, mem->fsm_off,
381*0Sstevel@tonic-gate 		    mem->fsm_format, level));
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate 	case CTF_K_ENUM:
384*0Sstevel@tonic-gate 		return (fth_print_enum(mem->fsm_memname, mem->fsm_off,
385*0Sstevel@tonic-gate 		    mem->fsm_format, level));
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate 	case CTF_K_FORWARD:
388*0Sstevel@tonic-gate 		return (parse_warn("Type %ld in %s.%s is undefined", tid,
389*0Sstevel@tonic-gate 		    fth_curtype, mem->fsm_memname));
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 	default:
392*0Sstevel@tonic-gate 		return (parse_warn("Unexpected kind %d for %s.%s", kind,
393*0Sstevel@tonic-gate 		    fth_curtype, mem->fsm_memname));
394*0Sstevel@tonic-gate 	}
395*0Sstevel@tonic-gate }
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate /*
398*0Sstevel@tonic-gate  * Add a member to list of members to be printed (fth_str_curmems).  If
399*0Sstevel@tonic-gate  * fsmd_memfilter is non-null, only add this member if its name matches that
400*0Sstevel@tonic-gate  * in the filter.
401*0Sstevel@tonic-gate  */
402*0Sstevel@tonic-gate static int
fth_struct_members_cb(const char * memname,ctf_id_t tid,ulong_t off,void * arg)403*0Sstevel@tonic-gate fth_struct_members_cb(const char *memname, ctf_id_t tid, ulong_t off, void *arg)
404*0Sstevel@tonic-gate {
405*0Sstevel@tonic-gate 	fth_struct_members_data_t *fsmd = arg;
406*0Sstevel@tonic-gate 	fth_str_mem_t *mem;
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate 	if (fsmd->fsmd_memfilter != NULL && strcmp(fsmd->fsmd_memfilter,
409*0Sstevel@tonic-gate 	    memname) != 0)
410*0Sstevel@tonic-gate 		return (0);
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 	fsmd->fsmd_matched = 1;
413*0Sstevel@tonic-gate 
414*0Sstevel@tonic-gate 	mem = xcalloc(sizeof (fth_str_mem_t));
415*0Sstevel@tonic-gate 	mem->fsm_memname = xstrdup(memname);
416*0Sstevel@tonic-gate 	if (fsmd->fsmd_format)
417*0Sstevel@tonic-gate 		mem->fsm_format = xstrdup(fsmd->fsmd_format);
418*0Sstevel@tonic-gate 	mem->fsm_tid = tid;
419*0Sstevel@tonic-gate 	mem->fsm_off = off;
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate 	slist_add(&fth_str_curmems, mem, fth_struct_memcmp);
422*0Sstevel@tonic-gate 
423*0Sstevel@tonic-gate 	return (0);
424*0Sstevel@tonic-gate }
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate /*
427*0Sstevel@tonic-gate  * If memfilter is non-null, iterate through the members of this type, causing
428*0Sstevel@tonic-gate  * every member to be added to the list.  Otherwise, use the iterator and
429*0Sstevel@tonic-gate  * the callback to add only the specified member.
430*0Sstevel@tonic-gate  */
431*0Sstevel@tonic-gate static int
fth_struct_members(char * memfilter,char * format)432*0Sstevel@tonic-gate fth_struct_members(char *memfilter, char *format)
433*0Sstevel@tonic-gate {
434*0Sstevel@tonic-gate 	fth_struct_members_data_t fsmd;
435*0Sstevel@tonic-gate 
436*0Sstevel@tonic-gate 	fsmd.fsmd_strname = fth_curtype;
437*0Sstevel@tonic-gate 	fsmd.fsmd_memfilter = memfilter;
438*0Sstevel@tonic-gate 	fsmd.fsmd_format = format;
439*0Sstevel@tonic-gate 	fsmd.fsmd_matched = 0;
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate 	if (ctf_member_iter(ctf, fth_str_curtid, fth_struct_members_cb,
442*0Sstevel@tonic-gate 	    &fsmd) != 0)
443*0Sstevel@tonic-gate 		return (-1);
444*0Sstevel@tonic-gate 
445*0Sstevel@tonic-gate 	if (memfilter != NULL && fsmd.fsmd_matched == 0) {
446*0Sstevel@tonic-gate 		return (parse_warn("Invalid member %s.%s", fth_curtype,
447*0Sstevel@tonic-gate 		    memfilter));
448*0Sstevel@tonic-gate 	}
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate 	return (0);
451*0Sstevel@tonic-gate }
452*0Sstevel@tonic-gate 
453*0Sstevel@tonic-gate static int
fth_struct_trailer(void)454*0Sstevel@tonic-gate fth_struct_trailer(void)
455*0Sstevel@tonic-gate {
456*0Sstevel@tonic-gate 	if (list_count(fth_str_curmems) == 0) {
457*0Sstevel@tonic-gate 		if (fth_struct_members(NULL, NULL) < 0)
458*0Sstevel@tonic-gate 			return (-1);
459*0Sstevel@tonic-gate 	}
460*0Sstevel@tonic-gate 
461*0Sstevel@tonic-gate 	while (!list_empty(fth_str_curmems)) {
462*0Sstevel@tonic-gate 		fth_str_mem_t *mem = list_remove(&fth_str_curmems,
463*0Sstevel@tonic-gate 		    list_first(fth_str_curmems), NULL, NULL);
464*0Sstevel@tonic-gate 
465*0Sstevel@tonic-gate 		if (fth_print_member(mem, 0) < 0)
466*0Sstevel@tonic-gate 			return (-1);
467*0Sstevel@tonic-gate 
468*0Sstevel@tonic-gate 		fth_free_str_mem(mem);
469*0Sstevel@tonic-gate 	}
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 	(void) fprintf(out, "\n");
472*0Sstevel@tonic-gate 	(void) fprintf(out, "kdbg-words definitions\n");
473*0Sstevel@tonic-gate 	(void) fprintf(out, "previous\n");
474*0Sstevel@tonic-gate 	(void) fprintf(out, "\n");
475*0Sstevel@tonic-gate 	(void) fprintf(out, "\\ end %s section\n", fth_curtype);
476*0Sstevel@tonic-gate 	(void) fprintf(out, "\n");
477*0Sstevel@tonic-gate 
478*0Sstevel@tonic-gate 	return (0);
479*0Sstevel@tonic-gate }
480*0Sstevel@tonic-gate 
481*0Sstevel@tonic-gate fth_type_ops_t fth_struct_ops = {
482*0Sstevel@tonic-gate 	fth_struct_header,
483*0Sstevel@tonic-gate 	fth_struct_members,
484*0Sstevel@tonic-gate 	fth_struct_trailer
485*0Sstevel@tonic-gate };
486