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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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