4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Used to dump structures and unions in forth mode.
32 * structures and unions are a bit more complicated than enums. To make things
33 * just that much more interesting, we have to dump the members in reverse
34 * order, which is nice. But wait! It gets better! For compatibility reasons,
35 * we need to dump the members in reverse-offset order, even if member-specific
36 * mode was used to request the members in something other than that order.
38 * The header op prints the macro header and saves the type being printed.
40 * In member-specific mode, the member op will be invoked for each structure
41 * or union member. The member op adds the member name, format, type ID,
42 * and offset to a list, sorted in reverse order by offset.
44 * The trailer op is called when the structure or enum is complete. If no
45 * members were specifically requested, then the trailer iterates through all
46 * of the members of the structure, pretending they were. Each member is thus
47 * added, in reverse-offset order, to the list used in specific-member mode.
48 * Either way, we then proceed through the list, dumping each member out with
49 * fth_print_member. Structure and union members are printed out differently,
50 * depending on member type, as follows:
53 * Normal integers: ' <format> <offset> <type>-field <name>
54 * <format> defaults to ".d" for enums, ".x" for others
55 * <offset> is the member offset, in bytes.
56 * <type> is "byte", "short", "long", or "ext" for 8-, 16-, 32-, and
57 * 64-bit integers, respectively.
58 * <name> is the name of the member being printed
60 * Bitfields: ' <format> <shift> <mask> <offset> bits-field <name>
61 * <format> defaults to ".x"
62 * <shift> is the number of times to right-shift the masked value
63 * <mask> use to extract the bit-field value from the read value
64 * <offset> is the member offset, in bytes
65 * <name> is the name of the member being printed
69 * Pointer: ' <format> <offset> ptr-field <name>
70 * <format> defaults to .x
71 * <offset> is in bytes
72 * <name> is the name of the member being printed
75 * Arrays have a content-type-specific prefix, followed by an array
76 * suffix. The resulting line looks like this if the array contents
77 * type is an integer, a pointer, or an enum:
79 * ' <fldc> ' <fmt> <sz> <elsz> <off> array-field <name>
81 * The following is printed for array contents that are arrays:
83 * ' noop ' .x <sz> <elsz> <off> array-field <name>
85 * The following is printed for array contents that are structs:
87 * ' noop ' <fmt> <sz> <elsz> <off> array-field <name>
89 * <fldc> is "c@", "w@", "l@", or "x@", depending on whether array
90 * elements are 8, 16, 32 or 64 bits wide.
91 * <fmt> defaults to ".x"
92 * <sz> is the size of the array, in bytes
93 * <elsz> is the size of the array elements
94 * <off> is the member offset, in bytes
95 * <name> is the nam eof the member being printed
97 * Struct/Union: ' <format> <offset> struct-field <name>
98 * <format> defaults to ".x"
99 * <offset> is the member offset, in bytes
100 * <name> is the name of the member being printed
107 #include "ctf_headers.h"
112 static ctf_id_t fth_str_curtid
;
113 static list_t
*fth_str_curmems
;
116 * Node type for the member-storage list (fth_str_curmems) built by
117 * fth_struct_members()
119 typedef struct fth_str_mem
{
126 typedef struct fth_struct_members_data
{
128 char *fsmd_memfilter
;
131 } fth_struct_members_data_t
;
133 static int fth_print_member(fth_str_mem_t
*, int);
135 /* Comparison routined used to insert members into the fth_str_curmems list */
137 fth_struct_memcmp(void *m1
, void *m2
)
139 fth_str_mem_t
*mem1
= m1
, *mem2
= m2
;
141 if (mem1
->fsm_off
< mem2
->fsm_off
)
143 else if (mem1
->fsm_off
> mem2
->fsm_off
)
150 fth_free_str_mem(fth_str_mem_t
*mem
)
152 free(mem
->fsm_memname
);
154 free(mem
->fsm_format
);
159 fth_struct_header(ctf_id_t tid
)
163 fth_str_curtid
= tid
;
164 fth_str_curmems
= NULL
;
166 if ((sz
= ctf_type_size(ctf
, fth_str_curtid
)) == CTF_ERR
)
167 return (parse_warn("Can't get size for %s", fth_curtype
));
169 (void) fprintf(out
, "\n");
170 (void) fprintf(out
, "vocabulary %s-words\n", fth_curtype
);
171 (void) fprintf(out
, "h# %x constant %s-sz\n", sz
, fth_curtype
);
172 (void) fprintf(out
, "%x ' %s-words c-struct .%s\n", sz
, fth_curtype
,
174 (void) fprintf(out
, "also %s-words definitions\n\n", fth_curtype
);
179 /* Print the array prefix for integer and pointer members */
181 fth_print_level(uint_t bits
, char *format
)
183 if ((bits
& (bits
- 1)) != 0 ||(bits
% 8) != 0 || bits
> 64) {
184 return (parse_warn("Unexpected bit size %d in %s",
188 (void) fprintf(out
, "' %c@ ' %s", " cw l x"[bits
/ 8], format
);
194 * Return the format to be used to print the member. If one of the builtin
195 * formats "d" or "x" were specified, return ".d" or ".x", respectively.
196 * Otherwise, use the user-provided format as is, or use the default if none
200 fth_convert_format(char *format
, char *def
)
202 static char dot
[3] = ".";
206 else if (strlen(format
) == 1) {
214 fth_print_integer(const char *memname
, ulong_t off
, uint_t bits
, char *format
,
217 format
= fth_convert_format(format
, ".x");
220 return (parse_warn("%s.%s is too large (>8 bytes)",
221 fth_curtype
, memname
));
225 return (fth_print_level(bits
, format
));
227 if ((bits
% NBBY
) != 0 || (bits
& (bits
- 1)) != 0) {
229 uint_t offset
, shift
, mask
;
231 offset
= (off
/ 32) * 4;
232 shift
= 32 - ((off
% 32) + bits
);
233 mask
= ((1 << bits
) - 1) << shift
;
235 (void) fprintf(out
, "' %s %x %x %x bits-field %s\n",
236 format
, shift
, mask
, offset
, memname
);
240 NULL
, "byte", "short", NULL
, "long",
241 NULL
, NULL
, NULL
, "ext"
244 (void) fprintf(out
, "' %s %lx %s-field %s\n", format
, off
/ 8,
245 type
[bits
/ 8], memname
);
252 fth_print_pointer(const char *memname
, ulong_t off
, uint_t bits
, char *format
,
255 format
= fth_convert_format(format
, ".x");
258 return (fth_print_level(bits
, format
));
260 (void) fprintf(out
, "' %s %lx ptr-field %s\n", format
, off
/ 8,
267 fth_print_struct(char *memname
, ulong_t off
, char *format
,
270 format
= fth_convert_format(format
, ".x");
273 (void) fprintf(out
, "' noop ' %s", format
);
275 (void) fprintf(out
, "' %s %lx struct-field %s\n", format
,
283 fth_print_enum(char *memname
, ulong_t off
, char *format
,
286 format
= fth_convert_format(format
, ".d");
289 (void) fprintf(out
, "' l@ ' %s", format
);
291 (void) fprintf(out
, "' %s %lx long-field %s\n", format
, off
/ 8,
299 fth_print_array(char *memname
, ctf_id_t tid
, ulong_t off
, ssize_t sz
,
300 char *format
, int level
)
303 (void) fprintf(out
, "' noop ' .x");
309 * print the prefix for the array contents type, then print
313 if (ctf_array_info(ctf
, tid
, &ar
) == CTF_ERR
) {
314 return (parse_warn("Can't read array in %s.%s",
315 fth_curtype
, memname
));
318 mem
.fsm_memname
= memname
;
319 mem
.fsm_format
= format
;
320 mem
.fsm_tid
= ar
.ctr_contents
;
323 if (fth_print_member(&mem
, level
+ 1) < 0)
326 (void) fprintf(out
, " %x %x %lx array-field %s\n", sz
,
327 (sz
/ ar
.ctr_nelems
), off
/ 8, memname
);
333 /* dump a structure or union member */
335 fth_print_member(fth_str_mem_t
*mem
, int level
)
342 if ((tid
= ctf_type_resolve(ctf
, mem
->fsm_tid
)) == CTF_ERR
) {
343 return (parse_warn("Can't resolve %s.%s", fth_curtype
,
347 if ((kind
= ctf_type_kind(ctf
, tid
)) == CTF_ERR
) {
348 return (parse_warn("Can't get kind for %s.%s",
349 fth_curtype
, mem
->fsm_memname
));
352 if ((sz
= ctf_type_size(ctf
, tid
)) == CTF_ERR
) {
353 return (parse_warn("Can't get size for %s.%s",
354 fth_curtype
, mem
->fsm_memname
));
359 if (ctf_type_encoding(ctf
, tid
, &e
) == CTF_ERR
)
360 return (parse_warn("Can't get encoding for %ld", tid
));
362 return (fth_print_integer(mem
->fsm_memname
, mem
->fsm_off
,
363 e
.cte_bits
, mem
->fsm_format
, level
));
366 (void) parse_warn("Ignoring floating point member %s.%s",
367 fth_curtype
, mem
->fsm_memname
);
371 return (fth_print_pointer(mem
->fsm_memname
, mem
->fsm_off
,
372 sz
* 8, mem
->fsm_format
, level
));
375 return (fth_print_array(mem
->fsm_memname
, tid
, mem
->fsm_off
, sz
,
376 mem
->fsm_format
, level
));
380 return (fth_print_struct(mem
->fsm_memname
, mem
->fsm_off
,
381 mem
->fsm_format
, level
));
384 return (fth_print_enum(mem
->fsm_memname
, mem
->fsm_off
,
385 mem
->fsm_format
, level
));
388 return (parse_warn("Type %ld in %s.%s is undefined", tid
,
389 fth_curtype
, mem
->fsm_memname
));
392 return (parse_warn("Unexpected kind %d for %s.%s", kind
,
393 fth_curtype
, mem
->fsm_memname
));
398 * Add a member to list of members to be printed (fth_str_curmems). If
399 * fsmd_memfilter is non-null, only add this member if its name matches that
403 fth_struct_members_cb(const char *memname
, ctf_id_t tid
, ulong_t off
, void *arg
)
405 fth_struct_members_data_t
*fsmd
= arg
;
408 if (fsmd
->fsmd_memfilter
!= NULL
&& strcmp(fsmd
->fsmd_memfilter
,
412 fsmd
->fsmd_matched
= 1;
414 mem
= xcalloc(sizeof (fth_str_mem_t
));
415 mem
->fsm_memname
= xstrdup(memname
);
416 if (fsmd
->fsmd_format
)
417 mem
->fsm_format
= xstrdup(fsmd
->fsmd_format
);
421 slist_add(&fth_str_curmems
, mem
, fth_struct_memcmp
);
427 * If memfilter is non-null, iterate through the members of this type, causing
428 * every member to be added to the list. Otherwise, use the iterator and
429 * the callback to add only the specified member.
432 fth_struct_members(char *memfilter
, char *format
)
434 fth_struct_members_data_t fsmd
;
436 fsmd
.fsmd_strname
= fth_curtype
;
437 fsmd
.fsmd_memfilter
= memfilter
;
438 fsmd
.fsmd_format
= format
;
439 fsmd
.fsmd_matched
= 0;
441 if (ctf_member_iter(ctf
, fth_str_curtid
, fth_struct_members_cb
,
445 if (memfilter
!= NULL
&& fsmd
.fsmd_matched
== 0) {
446 return (parse_warn("Invalid member %s.%s", fth_curtype
,
454 fth_struct_trailer(void)
456 if (list_count(fth_str_curmems
) == 0) {
457 if (fth_struct_members(NULL
, NULL
) < 0)
461 while (!list_empty(fth_str_curmems
)) {
462 fth_str_mem_t
*mem
= list_remove(&fth_str_curmems
,
463 list_first(fth_str_curmems
), NULL
, NULL
);
465 if (fth_print_member(mem
, 0) < 0)
468 fth_free_str_mem(mem
);
471 (void) fprintf(out
, "\n");
472 (void) fprintf(out
, "kdbg-words definitions\n");
473 (void) fprintf(out
, "previous\n");
474 (void) fprintf(out
, "\n");
475 (void) fprintf(out
, "\\ end %s section\n", fth_curtype
);
476 (void) fprintf(out
, "\n");
481 fth_type_ops_t fth_struct_ops
= {