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