xref: /illumos-gate/usr/src/tools/ctf/stabs/common/fth_struct.c (revision 88a08813800ed7ba7c927986421cee437f7f2233)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27*88a08813SAndy Fiddaman /*
28*88a08813SAndy Fiddaman  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
29*88a08813SAndy Fiddaman  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * Used to dump structures and unions in forth mode.
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * structures and unions are a bit more complicated than enums.  To make things
357c478bd9Sstevel@tonic-gate  * just that much more interesting, we have to dump the members in reverse
367c478bd9Sstevel@tonic-gate  * order, which is nice.  But wait!  It gets better!  For compatibility reasons,
377c478bd9Sstevel@tonic-gate  * we need to dump the members in reverse-offset order, even if member-specific
387c478bd9Sstevel@tonic-gate  * mode was used to request the members in something other than that order.
397c478bd9Sstevel@tonic-gate  *
407c478bd9Sstevel@tonic-gate  * The header op prints the macro header and saves the type being printed.
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * In member-specific mode, the member op will be invoked for each structure
437c478bd9Sstevel@tonic-gate  * or union member.  The member op adds the member name, format, type ID,
447c478bd9Sstevel@tonic-gate  * and offset to a list, sorted in reverse order by offset.
457c478bd9Sstevel@tonic-gate  *
467c478bd9Sstevel@tonic-gate  * The trailer op is called when the structure or enum is complete.  If no
477c478bd9Sstevel@tonic-gate  * members were specifically requested, then the trailer iterates through all
487c478bd9Sstevel@tonic-gate  * of the members of the structure, pretending they were.  Each member is thus
497c478bd9Sstevel@tonic-gate  * added, in reverse-offset order, to the list used in specific-member mode.
507c478bd9Sstevel@tonic-gate  * Either way, we then proceed through the list, dumping each member out with
517c478bd9Sstevel@tonic-gate  * fth_print_member.  Structure and union members are printed out differently,
527c478bd9Sstevel@tonic-gate  * depending on member type, as follows:
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  *  Integer:
557c478bd9Sstevel@tonic-gate  *	Normal integers: ' <format> <offset> <type>-field <name>
567c478bd9Sstevel@tonic-gate  *	  <format> defaults to ".d" for enums, ".x" for others
577c478bd9Sstevel@tonic-gate  *	  <offset> is the member offset, in bytes.
587c478bd9Sstevel@tonic-gate  *	  <type> is "byte", "short", "long", or "ext" for 8-, 16-, 32-, and
597c478bd9Sstevel@tonic-gate  *	    64-bit integers, respectively.
607c478bd9Sstevel@tonic-gate  *	  <name> is the name of the member being printed
617c478bd9Sstevel@tonic-gate  *
627c478bd9Sstevel@tonic-gate  *	Bitfields:	 ' <format> <shift> <mask> <offset> bits-field <name>
637c478bd9Sstevel@tonic-gate  *	  <format> defaults to ".x"
647c478bd9Sstevel@tonic-gate  *	  <shift> is the number of times to right-shift the masked value
657c478bd9Sstevel@tonic-gate  *	  <mask> use to extract the bit-field value from the read value
667c478bd9Sstevel@tonic-gate  *	  <offset> is the member offset, in bytes
677c478bd9Sstevel@tonic-gate  *	  <name> is the name of the member being printed
687c478bd9Sstevel@tonic-gate  *
697c478bd9Sstevel@tonic-gate  *  Float:		Ignored
707c478bd9Sstevel@tonic-gate  *
717c478bd9Sstevel@tonic-gate  *  Pointer:		 ' <format> <offset> ptr-field <name>
727c478bd9Sstevel@tonic-gate  *	  <format> defaults to .x
737c478bd9Sstevel@tonic-gate  *	  <offset> is in bytes
747c478bd9Sstevel@tonic-gate  *	  <name> is the name of the member being printed
757c478bd9Sstevel@tonic-gate  *
767c478bd9Sstevel@tonic-gate  *  Array:
777c478bd9Sstevel@tonic-gate  *	Arrays have a content-type-specific prefix, followed by an array
787c478bd9Sstevel@tonic-gate  *	suffix.  The resulting line looks like this if the array contents
797c478bd9Sstevel@tonic-gate  *	type is an integer, a pointer, or an enum:
807c478bd9Sstevel@tonic-gate  *
817c478bd9Sstevel@tonic-gate  *			 ' <fldc> ' <fmt> <sz> <elsz> <off> array-field <name>
827c478bd9Sstevel@tonic-gate  *
837c478bd9Sstevel@tonic-gate  *	The following is printed for array contents that are arrays:
847c478bd9Sstevel@tonic-gate  *
857c478bd9Sstevel@tonic-gate  *			 ' noop ' .x <sz> <elsz> <off> array-field <name>
867c478bd9Sstevel@tonic-gate  *
877c478bd9Sstevel@tonic-gate  *	The following is printed for array contents that are structs:
887c478bd9Sstevel@tonic-gate  *
897c478bd9Sstevel@tonic-gate  *			 ' noop ' <fmt> <sz> <elsz> <off> array-field <name>
907c478bd9Sstevel@tonic-gate  *
917c478bd9Sstevel@tonic-gate  *	  <fldc> is "c@", "w@", "l@", or "x@", depending on whether array
927c478bd9Sstevel@tonic-gate  *	    elements are 8, 16, 32 or 64 bits wide.
937c478bd9Sstevel@tonic-gate  *	  <fmt> defaults to ".x"
947c478bd9Sstevel@tonic-gate  *	  <sz> is the size of the array, in bytes
957c478bd9Sstevel@tonic-gate  *	  <elsz> is the size of the array elements
967c478bd9Sstevel@tonic-gate  *	  <off> is the member offset, in bytes
977c478bd9Sstevel@tonic-gate  *	  <name> is the nam eof the member being printed
987c478bd9Sstevel@tonic-gate  *
997c478bd9Sstevel@tonic-gate  *  Struct/Union:	 ' <format> <offset> struct-field <name>
1007c478bd9Sstevel@tonic-gate  *	  <format> defaults to ".x"
1017c478bd9Sstevel@tonic-gate  *	  <offset> is the member offset, in bytes
1027c478bd9Sstevel@tonic-gate  *	  <name> is the name of the member being printed
1037c478bd9Sstevel@tonic-gate  */
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate #include <stdio.h>
1067c478bd9Sstevel@tonic-gate #include <stdlib.h>
1077c478bd9Sstevel@tonic-gate #include <string.h>
108*88a08813SAndy Fiddaman #include <sys/list.h>
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate #include "ctf_headers.h"
1117c478bd9Sstevel@tonic-gate #include "forth.h"
1127c478bd9Sstevel@tonic-gate #include "memory.h"
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate static ctf_id_t	fth_str_curtid;
115*88a08813SAndy Fiddaman static list_t	fth_str_curmems;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate  * Node type for the member-storage list (fth_str_curmems) built by
1197c478bd9Sstevel@tonic-gate  * fth_struct_members()
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate typedef struct fth_str_mem {
122*88a08813SAndy Fiddaman 	list_node_t	fsm_node;
1237c478bd9Sstevel@tonic-gate 	char		*fsm_memname;
1247c478bd9Sstevel@tonic-gate 	char		*fsm_format;
1257c478bd9Sstevel@tonic-gate 	ctf_id_t	fsm_tid;
1267c478bd9Sstevel@tonic-gate 	ulong_t		fsm_off;
1277c478bd9Sstevel@tonic-gate } fth_str_mem_t;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate typedef struct fth_struct_members_data {
1307c478bd9Sstevel@tonic-gate 	char		*fsmd_strname;
1317c478bd9Sstevel@tonic-gate 	char		*fsmd_memfilter;
1327c478bd9Sstevel@tonic-gate 	char		*fsmd_format;
1337c478bd9Sstevel@tonic-gate 	int		fsmd_matched;
1347c478bd9Sstevel@tonic-gate } fth_struct_members_data_t;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate static int fth_print_member(fth_str_mem_t *, int);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate /* Comparison routined used to insert members into the fth_str_curmems list */
1397c478bd9Sstevel@tonic-gate static int
fth_struct_memcmp(void * m1,void * m2)1407c478bd9Sstevel@tonic-gate fth_struct_memcmp(void *m1, void *m2)
1417c478bd9Sstevel@tonic-gate {
1427c478bd9Sstevel@tonic-gate 	fth_str_mem_t *mem1 = m1, *mem2 = m2;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	if (mem1->fsm_off < mem2->fsm_off)
1457c478bd9Sstevel@tonic-gate 		return (1);
1467c478bd9Sstevel@tonic-gate 	else if (mem1->fsm_off > mem2->fsm_off)
1477c478bd9Sstevel@tonic-gate 		return (-1);
1487c478bd9Sstevel@tonic-gate 	else
1497c478bd9Sstevel@tonic-gate 		return (0);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate static void
fth_slist_add(fth_str_mem_t * mem)153*88a08813SAndy Fiddaman fth_slist_add(fth_str_mem_t *mem)
154*88a08813SAndy Fiddaman {
155*88a08813SAndy Fiddaman 	fth_str_mem_t *l;
156*88a08813SAndy Fiddaman 
157*88a08813SAndy Fiddaman 	for (l = list_head(&fth_str_curmems); l != NULL;
158*88a08813SAndy Fiddaman 	    l = list_next(&fth_str_curmems, l)) {
159*88a08813SAndy Fiddaman 		if (fth_struct_memcmp(l, mem) > 0) {
160*88a08813SAndy Fiddaman 			list_insert_before(&fth_str_curmems, l, mem);
161*88a08813SAndy Fiddaman 			return;
162*88a08813SAndy Fiddaman 		}
163*88a08813SAndy Fiddaman 	}
164*88a08813SAndy Fiddaman 	list_insert_tail(&fth_str_curmems, mem);
165*88a08813SAndy Fiddaman }
166*88a08813SAndy Fiddaman 
167*88a08813SAndy Fiddaman static void
fth_free_str_mem(fth_str_mem_t * mem)1687c478bd9Sstevel@tonic-gate fth_free_str_mem(fth_str_mem_t *mem)
1697c478bd9Sstevel@tonic-gate {
1707c478bd9Sstevel@tonic-gate 	free(mem->fsm_memname);
1717c478bd9Sstevel@tonic-gate 	if (mem->fsm_format)
1727c478bd9Sstevel@tonic-gate 		free(mem->fsm_format);
1737c478bd9Sstevel@tonic-gate 	free(mem);
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate static int
fth_struct_header(ctf_id_t tid)1777c478bd9Sstevel@tonic-gate fth_struct_header(ctf_id_t tid)
1787c478bd9Sstevel@tonic-gate {
1797c478bd9Sstevel@tonic-gate 	ssize_t sz;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	fth_str_curtid = tid;
182*88a08813SAndy Fiddaman 	list_create(&fth_str_curmems, sizeof (fth_str_mem_t),
183*88a08813SAndy Fiddaman 	    offsetof(fth_str_mem_t, fsm_node));
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	if ((sz = ctf_type_size(ctf, fth_str_curtid)) == CTF_ERR)
1867c478bd9Sstevel@tonic-gate 		return (parse_warn("Can't get size for %s", fth_curtype));
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n");
1897c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "vocabulary %s-words\n", fth_curtype);
1907c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "h# %x constant %s-sz\n", sz, fth_curtype);
1917c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "%x ' %s-words c-struct .%s\n", sz, fth_curtype,
1927c478bd9Sstevel@tonic-gate 	    fth_curtype);
1937c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "also %s-words definitions\n\n", fth_curtype);
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	return (0);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate /* Print the array prefix for integer and pointer members */
1997c478bd9Sstevel@tonic-gate static int
fth_print_level(uint_t bits,char * format)2007c478bd9Sstevel@tonic-gate fth_print_level(uint_t bits, char *format)
2017c478bd9Sstevel@tonic-gate {
2027c478bd9Sstevel@tonic-gate 	if ((bits & (bits - 1)) != 0 ||(bits % 8) != 0 || bits > 64) {
2037c478bd9Sstevel@tonic-gate 		return (parse_warn("Unexpected bit size %d in %s",
2047c478bd9Sstevel@tonic-gate 		    bits, fth_curtype));
2057c478bd9Sstevel@tonic-gate 	}
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "' %c@ ' %s", " cw l   x"[bits / 8], format);
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	return (0);
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate /*
2137c478bd9Sstevel@tonic-gate  * Return the format to be used to print the member.  If one of the builtin
2147c478bd9Sstevel@tonic-gate  * formats "d" or "x" were specified, return ".d" or ".x", respectively.
2157c478bd9Sstevel@tonic-gate  * Otherwise, use the user-provided format as is, or use the default if none
2167c478bd9Sstevel@tonic-gate  * was provided.
2177c478bd9Sstevel@tonic-gate  */
2187c478bd9Sstevel@tonic-gate static char *
fth_convert_format(char * format,char * def)2197c478bd9Sstevel@tonic-gate fth_convert_format(char *format, char *def)
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate 	static char dot[3] = ".";
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	if (format == NULL)
2247c478bd9Sstevel@tonic-gate 		return (def);
2257c478bd9Sstevel@tonic-gate 	else if (strlen(format) == 1) {
2267c478bd9Sstevel@tonic-gate 		dot[1] = *format;
2277c478bd9Sstevel@tonic-gate 		return (dot);
2287c478bd9Sstevel@tonic-gate 	} else
2297c478bd9Sstevel@tonic-gate 		return (format);
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate static int
fth_print_integer(const char * memname,ulong_t off,uint_t bits,char * format,int level)2337c478bd9Sstevel@tonic-gate fth_print_integer(const char *memname, ulong_t off, uint_t bits, char *format,
2347c478bd9Sstevel@tonic-gate     int level)
2357c478bd9Sstevel@tonic-gate {
2367c478bd9Sstevel@tonic-gate 	format = fth_convert_format(format, ".x");
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	if (bits > 64) {
2397c478bd9Sstevel@tonic-gate 		return (parse_warn("%s.%s is too large (>8 bytes)",
2407c478bd9Sstevel@tonic-gate 		    fth_curtype, memname));
2417c478bd9Sstevel@tonic-gate 	}
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	if (level != 0)
2447c478bd9Sstevel@tonic-gate 		return (fth_print_level(bits, format));
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	if ((bits % NBBY) != 0 || (bits & (bits - 1)) != 0) {
2477c478bd9Sstevel@tonic-gate 		/* bit field */
2487c478bd9Sstevel@tonic-gate 		uint_t offset, shift, mask;
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 		offset = (off / 32) * 4;
2517c478bd9Sstevel@tonic-gate 		shift = 32 - ((off % 32) + bits);
2527c478bd9Sstevel@tonic-gate 		mask = ((1 << bits) - 1) << shift;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "' %s %x %x %x bits-field %s\n",
2557c478bd9Sstevel@tonic-gate 		    format, shift, mask, offset, memname);
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	} else {
2587c478bd9Sstevel@tonic-gate 		char *type[] = {
2597c478bd9Sstevel@tonic-gate 			NULL, "byte", "short", NULL, "long",
2607c478bd9Sstevel@tonic-gate 			NULL, NULL, NULL, "ext"
2617c478bd9Sstevel@tonic-gate 		};
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "' %s %lx %s-field %s\n", format, off / 8,
2647c478bd9Sstevel@tonic-gate 		    type[bits / 8], memname);
2657c478bd9Sstevel@tonic-gate 	}
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	return (0);
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate static int
fth_print_pointer(const char * memname,ulong_t off,uint_t bits,char * format,int level)2717c478bd9Sstevel@tonic-gate fth_print_pointer(const char *memname, ulong_t off, uint_t bits, char *format,
2727c478bd9Sstevel@tonic-gate     int level)
2737c478bd9Sstevel@tonic-gate {
2747c478bd9Sstevel@tonic-gate 	format = fth_convert_format(format, ".x");
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	if (level != 0)
2777c478bd9Sstevel@tonic-gate 		return (fth_print_level(bits, format));
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "' %s %lx ptr-field %s\n", format, off / 8,
2807c478bd9Sstevel@tonic-gate 	    memname);
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	return (0);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate static int
fth_print_struct(char * memname,ulong_t off,char * format,int level)2867c478bd9Sstevel@tonic-gate fth_print_struct(char *memname, ulong_t off, char *format,
2877c478bd9Sstevel@tonic-gate     int level)
2887c478bd9Sstevel@tonic-gate {
2897c478bd9Sstevel@tonic-gate 	format = fth_convert_format(format, ".x");
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	if (level != 0)
2927c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "' noop ' %s", format);
2937c478bd9Sstevel@tonic-gate 	else {
2947c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "' %s %lx struct-field %s\n", format,
2957c478bd9Sstevel@tonic-gate 		    off / 8, memname);
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	return (0);
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate static int
fth_print_enum(char * memname,ulong_t off,char * format,int level)3027c478bd9Sstevel@tonic-gate fth_print_enum(char *memname, ulong_t off, char *format,
3037c478bd9Sstevel@tonic-gate     int level)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate 	format = fth_convert_format(format, ".d");
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	if (level != 0)
3087c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "' l@ ' %s", format);
3097c478bd9Sstevel@tonic-gate 	else {
3107c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "' %s %lx long-field %s\n", format, off / 8,
3117c478bd9Sstevel@tonic-gate 		    memname);
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	return (0);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate static int
fth_print_array(char * memname,ctf_id_t tid,ulong_t off,ssize_t sz,char * format,int level)3187c478bd9Sstevel@tonic-gate fth_print_array(char *memname, ctf_id_t tid, ulong_t off, ssize_t sz,
3197c478bd9Sstevel@tonic-gate     char *format, int level)
3207c478bd9Sstevel@tonic-gate {
3217c478bd9Sstevel@tonic-gate 	if (level != 0)
3227c478bd9Sstevel@tonic-gate 		(void) fprintf(out, "' noop ' .x");
3237c478bd9Sstevel@tonic-gate 	else {
3247c478bd9Sstevel@tonic-gate 		fth_str_mem_t mem;
3257c478bd9Sstevel@tonic-gate 		ctf_arinfo_t ar;
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 		/*
3287c478bd9Sstevel@tonic-gate 		 * print the prefix for the array contents type, then print
3297c478bd9Sstevel@tonic-gate 		 * the array macro
3307c478bd9Sstevel@tonic-gate 		 */
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 		if (ctf_array_info(ctf, tid, &ar) == CTF_ERR) {
3337c478bd9Sstevel@tonic-gate 			return (parse_warn("Can't read array in %s.%s",
3347c478bd9Sstevel@tonic-gate 			    fth_curtype, memname));
3357c478bd9Sstevel@tonic-gate 		}
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 		mem.fsm_memname = memname;
3387c478bd9Sstevel@tonic-gate 		mem.fsm_format = format;
3397c478bd9Sstevel@tonic-gate 		mem.fsm_tid = ar.ctr_contents;
3407c478bd9Sstevel@tonic-gate 		mem.fsm_off = off;
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 		if (fth_print_member(&mem, level + 1) < 0)
3437c478bd9Sstevel@tonic-gate 			return (-1);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 		(void) fprintf(out, " %x %x %lx array-field %s\n", sz,
3467c478bd9Sstevel@tonic-gate 		    (sz / ar.ctr_nelems), off / 8, memname);
3477c478bd9Sstevel@tonic-gate 	}
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	return (0);
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate /* dump a structure or union member */
3537c478bd9Sstevel@tonic-gate static int
fth_print_member(fth_str_mem_t * mem,int level)3547c478bd9Sstevel@tonic-gate fth_print_member(fth_str_mem_t *mem, int level)
3557c478bd9Sstevel@tonic-gate {
3567c478bd9Sstevel@tonic-gate 	ctf_encoding_t e;
3577c478bd9Sstevel@tonic-gate 	ctf_id_t tid;
3587c478bd9Sstevel@tonic-gate 	int kind;
3597c478bd9Sstevel@tonic-gate 	ssize_t sz;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	if ((tid = ctf_type_resolve(ctf, mem->fsm_tid)) == CTF_ERR) {
3627c478bd9Sstevel@tonic-gate 		return (parse_warn("Can't resolve %s.%s", fth_curtype,
3637c478bd9Sstevel@tonic-gate 		    mem->fsm_memname));
3647c478bd9Sstevel@tonic-gate 	}
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	if ((kind = ctf_type_kind(ctf, tid)) == CTF_ERR) {
3677c478bd9Sstevel@tonic-gate 		return (parse_warn("Can't get kind for %s.%s",
3687c478bd9Sstevel@tonic-gate 		    fth_curtype, mem->fsm_memname));
3697c478bd9Sstevel@tonic-gate 	}
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	if ((sz = ctf_type_size(ctf, tid)) == CTF_ERR) {
3727c478bd9Sstevel@tonic-gate 		return (parse_warn("Can't get size for %s.%s",
3737c478bd9Sstevel@tonic-gate 		    fth_curtype, mem->fsm_memname));
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	switch (kind) {
3777c478bd9Sstevel@tonic-gate 	case CTF_K_INTEGER:
3787c478bd9Sstevel@tonic-gate 		if (ctf_type_encoding(ctf, tid, &e) == CTF_ERR)
3797c478bd9Sstevel@tonic-gate 			return (parse_warn("Can't get encoding for %ld", tid));
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 		return (fth_print_integer(mem->fsm_memname, mem->fsm_off,
3827c478bd9Sstevel@tonic-gate 		    e.cte_bits, mem->fsm_format, level));
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	case CTF_K_FLOAT:
3857c478bd9Sstevel@tonic-gate 		(void) parse_warn("Ignoring floating point member %s.%s",
3867c478bd9Sstevel@tonic-gate 		    fth_curtype, mem->fsm_memname);
3877c478bd9Sstevel@tonic-gate 		return (0);
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	case CTF_K_POINTER:
3907c478bd9Sstevel@tonic-gate 		return (fth_print_pointer(mem->fsm_memname, mem->fsm_off,
3917c478bd9Sstevel@tonic-gate 		    sz * 8, mem->fsm_format, level));
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	case CTF_K_ARRAY:
3947c478bd9Sstevel@tonic-gate 		return (fth_print_array(mem->fsm_memname, tid, mem->fsm_off, sz,
3957c478bd9Sstevel@tonic-gate 		    mem->fsm_format, level));
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	case CTF_K_STRUCT:
3987c478bd9Sstevel@tonic-gate 	case CTF_K_UNION:
3997c478bd9Sstevel@tonic-gate 		return (fth_print_struct(mem->fsm_memname, mem->fsm_off,
4007c478bd9Sstevel@tonic-gate 		    mem->fsm_format, level));
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	case CTF_K_ENUM:
4037c478bd9Sstevel@tonic-gate 		return (fth_print_enum(mem->fsm_memname, mem->fsm_off,
4047c478bd9Sstevel@tonic-gate 		    mem->fsm_format, level));
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	case CTF_K_FORWARD:
4077c478bd9Sstevel@tonic-gate 		return (parse_warn("Type %ld in %s.%s is undefined", tid,
4087c478bd9Sstevel@tonic-gate 		    fth_curtype, mem->fsm_memname));
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	default:
4117c478bd9Sstevel@tonic-gate 		return (parse_warn("Unexpected kind %d for %s.%s", kind,
4127c478bd9Sstevel@tonic-gate 		    fth_curtype, mem->fsm_memname));
4137c478bd9Sstevel@tonic-gate 	}
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate /*
4177c478bd9Sstevel@tonic-gate  * Add a member to list of members to be printed (fth_str_curmems).  If
4187c478bd9Sstevel@tonic-gate  * fsmd_memfilter is non-null, only add this member if its name matches that
4197c478bd9Sstevel@tonic-gate  * in the filter.
4207c478bd9Sstevel@tonic-gate  */
4217c478bd9Sstevel@tonic-gate static int
fth_struct_members_cb(const char * memname,ctf_id_t tid,ulong_t off,void * arg)4227c478bd9Sstevel@tonic-gate fth_struct_members_cb(const char *memname, ctf_id_t tid, ulong_t off, void *arg)
4237c478bd9Sstevel@tonic-gate {
4247c478bd9Sstevel@tonic-gate 	fth_struct_members_data_t *fsmd = arg;
4257c478bd9Sstevel@tonic-gate 	fth_str_mem_t *mem;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	if (fsmd->fsmd_memfilter != NULL && strcmp(fsmd->fsmd_memfilter,
4287c478bd9Sstevel@tonic-gate 	    memname) != 0)
4297c478bd9Sstevel@tonic-gate 		return (0);
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	fsmd->fsmd_matched = 1;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	mem = xcalloc(sizeof (fth_str_mem_t));
4347c478bd9Sstevel@tonic-gate 	mem->fsm_memname = xstrdup(memname);
4357c478bd9Sstevel@tonic-gate 	if (fsmd->fsmd_format)
4367c478bd9Sstevel@tonic-gate 		mem->fsm_format = xstrdup(fsmd->fsmd_format);
4377c478bd9Sstevel@tonic-gate 	mem->fsm_tid = tid;
4387c478bd9Sstevel@tonic-gate 	mem->fsm_off = off;
4397c478bd9Sstevel@tonic-gate 
440*88a08813SAndy Fiddaman 	fth_slist_add(mem);
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	return (0);
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate /*
4467c478bd9Sstevel@tonic-gate  * If memfilter is non-null, iterate through the members of this type, causing
4477c478bd9Sstevel@tonic-gate  * every member to be added to the list.  Otherwise, use the iterator and
4487c478bd9Sstevel@tonic-gate  * the callback to add only the specified member.
4497c478bd9Sstevel@tonic-gate  */
4507c478bd9Sstevel@tonic-gate static int
fth_struct_members(char * memfilter,char * format)4517c478bd9Sstevel@tonic-gate fth_struct_members(char *memfilter, char *format)
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate 	fth_struct_members_data_t fsmd;
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	fsmd.fsmd_strname = fth_curtype;
4567c478bd9Sstevel@tonic-gate 	fsmd.fsmd_memfilter = memfilter;
4577c478bd9Sstevel@tonic-gate 	fsmd.fsmd_format = format;
4587c478bd9Sstevel@tonic-gate 	fsmd.fsmd_matched = 0;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	if (ctf_member_iter(ctf, fth_str_curtid, fth_struct_members_cb,
4617c478bd9Sstevel@tonic-gate 	    &fsmd) != 0)
4627c478bd9Sstevel@tonic-gate 		return (-1);
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 	if (memfilter != NULL && fsmd.fsmd_matched == 0) {
4657c478bd9Sstevel@tonic-gate 		return (parse_warn("Invalid member %s.%s", fth_curtype,
4667c478bd9Sstevel@tonic-gate 		    memfilter));
4677c478bd9Sstevel@tonic-gate 	}
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	return (0);
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate static int
fth_struct_trailer(void)4737c478bd9Sstevel@tonic-gate fth_struct_trailer(void)
4747c478bd9Sstevel@tonic-gate {
475*88a08813SAndy Fiddaman 	fth_str_mem_t *mem;
476*88a08813SAndy Fiddaman 
477*88a08813SAndy Fiddaman 	if (list_is_empty(&fth_str_curmems)) {
4787c478bd9Sstevel@tonic-gate 		if (fth_struct_members(NULL, NULL) < 0)
4797c478bd9Sstevel@tonic-gate 			return (-1);
4807c478bd9Sstevel@tonic-gate 	}
4817c478bd9Sstevel@tonic-gate 
482*88a08813SAndy Fiddaman 	while ((mem = list_remove_head(&fth_str_curmems)) != NULL) {
4837c478bd9Sstevel@tonic-gate 		if (fth_print_member(mem, 0) < 0)
4847c478bd9Sstevel@tonic-gate 			return (-1);
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 		fth_free_str_mem(mem);
4877c478bd9Sstevel@tonic-gate 	}
488*88a08813SAndy Fiddaman 	list_destroy(&fth_str_curmems);
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n");
4917c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "kdbg-words definitions\n");
4927c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "previous\n");
4937c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n");
4947c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\\ end %s section\n", fth_curtype);
4957c478bd9Sstevel@tonic-gate 	(void) fprintf(out, "\n");
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	return (0);
4987c478bd9Sstevel@tonic-gate }
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate fth_type_ops_t fth_struct_ops = {
5017c478bd9Sstevel@tonic-gate 	fth_struct_header,
5027c478bd9Sstevel@tonic-gate 	fth_struct_members,
5037c478bd9Sstevel@tonic-gate 	fth_struct_trailer
5047c478bd9Sstevel@tonic-gate };
505