1207753Smm/* 2207753Smm * CDDL HEADER START 3207753Smm * 4207753Smm * The contents of this file are subject to the terms of the 5207753Smm * Common Development and Distribution License (the "License"). 6207753Smm * You may not use this file except in compliance with the License. 7207753Smm * 8207753Smm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9207753Smm * or http://www.opensolaris.org/os/licensing. 10207753Smm * See the License for the specific language governing permissions 11207753Smm * and limitations under the License. 12207753Smm * 13207753Smm * When distributing Covered Code, include this CDDL HEADER in each 14207753Smm * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15207753Smm * If applicable, add the following below this CDDL HEADER, with the 16207753Smm * fields enclosed by brackets "[]" replaced with your own identifying 17207753Smm * information: Portions Copyright [yyyy] [name of copyright owner] 18207753Smm * 19207753Smm * CDDL HEADER END 20207753Smm */ 21207753Smm/* 22207753Smm * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23207753Smm * Use is subject to license terms. 24207753Smm */ 25207753Smm/* 26207753Smm * Copyright (c) 2011 by Delphix. All rights reserved. 27207753Smm */ 28207753Smm/* 29207753Smm * Copyright (c) 2013, Joyent, Inc. All rights reserved. 30207753Smm */ 31207753Smm 32207753Smm/* 33207753Smm * DTrace print() action 34207753Smm * 35207753Smm * This file contains the post-processing logic for the print() action. The 36207753Smm * print action behaves identically to trace() in that it generates a 37207753Smm * DTRACEACT_DIFEXPR action, but the action argument field refers to a CTF type 38207753Smm * string stored in the DOF string table (similar to printf formats). We 39207753Smm * take the result of the trace action and post-process it in the fashion of 40207753Smm * MDB's ::print dcmd. 41207753Smm * 42207753Smm * This implementation differs from MDB's in the following ways: 43207753Smm * 44207753Smm * - We do not expose any options or flags. The behavior of print() is 45207753Smm * equivalent to "::print -tn". 46207753Smm * 47207753Smm * - MDB will display "holes" in structures (unused padding between 48207753Smm * members). 49207753Smm * 50207753Smm * - When printing arrays of structures, MDB will leave a trailing ',' 51207753Smm * after the last element. 52207753Smm * 53207753Smm * - MDB will print time_t types as date and time. 54207753Smm * 55207753Smm * - MDB will detect when an enum is actually the OR of several flags, 56207753Smm * and print it out with the constituent flags separated. 57207753Smm * 58207753Smm * - For large arrays, MDB will print the first few members and then 59207753Smm * print a "..." continuation line. 60207753Smm * 61207753Smm * - MDB will break and wrap arrays at 80 columns. 62207753Smm * 63207753Smm * - MDB prints out floats and doubles by hand, as it must run in kmdb 64207753Smm * context. We're able to leverage the printf() format strings, 65207753Smm * but the result is a slightly different format. 66207753Smm */ 67207753Smm 68207753Smm#include <sys/sysmacros.h> 69207753Smm#include <strings.h> 70207753Smm#include <stdlib.h> 71207753Smm#include <alloca.h> 72207753Smm#include <assert.h> 73207753Smm#include <ctype.h> 74207753Smm#include <errno.h> 75207753Smm#include <limits.h> 76207753Smm#include <sys/socket.h> 77207753Smm#include <netdb.h> 78207753Smm#include <netinet/in.h> 79207753Smm#include <arpa/inet.h> 80207753Smm#include <arpa/nameser.h> 81207753Smm 82207753Smm#include <dt_module.h> 83207753Smm#include <dt_printf.h> 84207753Smm#include <dt_string.h> 85207753Smm#include <dt_impl.h> 86207753Smm 87207753Smm/* determines whether the given integer CTF encoding is a character */ 88207753Smm#define CTF_IS_CHAR(e) \ 89207753Smm (((e).cte_format & (CTF_INT_CHAR | CTF_INT_SIGNED)) == \ 90207753Smm (CTF_INT_CHAR | CTF_INT_SIGNED) && (e).cte_bits == NBBY) 91207753Smm/* determines whether the given CTF kind is a struct or union */ 92207753Smm#define CTF_IS_STRUCTLIKE(k) \ 93207753Smm ((k) == CTF_K_STRUCT || (k) == CTF_K_UNION) 94207753Smm 95207753Smm/* 96207753Smm * Print structure passed down recursively through printing algorithm. 97207753Smm */ 98207753Smmtypedef struct dt_printarg { 99207753Smm dtrace_hdl_t *pa_dtp; /* libdtrace handle */ 100207753Smm caddr_t pa_addr; /* base address of trace data */ 101207753Smm ctf_file_t *pa_ctfp; /* CTF container */ 102207753Smm int pa_depth; /* member depth */ 103207753Smm int pa_nest; /* nested array depth */ 104207753Smm FILE *pa_file; /* output file */ 105207753Smm} dt_printarg_t; 106207753Smm 107207753Smmstatic int dt_print_member(const char *, ctf_id_t, ulong_t, int, void *); 108207753Smm 109207753Smm/* 110207753Smm * Safe version of ctf_type_name() that will fall back to just "<ctfid>" if it 111207753Smm * can't resolve the type. 112207753Smm */ 113207753Smmstatic void 114207753Smmdt_print_type_name(ctf_file_t *ctfp, ctf_id_t id, char *buf, size_t buflen) 115207753Smm{ 116207753Smm if (ctf_type_name(ctfp, id, buf, buflen) == NULL) 117207753Smm (void) snprintf(buf, buflen, "<%ld>", id); 118207753Smm} 119207753Smm 120207753Smm/* 121207753Smm * Print any necessary trailing braces for structures or unions. We don't get 122207753Smm * invoked when a struct or union ends, so we infer the need to print braces 123207753Smm * based on the depth the last time we printed something and the new depth. 124207753Smm */ 125207753Smmstatic void 126207753Smmdt_print_trailing_braces(dt_printarg_t *pap, int depth) 127207753Smm{ 128207753Smm int d; 129207753Smm 130207753Smm for (d = pap->pa_depth; d > depth; d--) { 131207753Smm (void) fprintf(pap->pa_file, "%*s}%s", 132207753Smm (d + pap->pa_nest - 1) * 4, "", 133207753Smm d == depth + 1 ? "" : "\n"); 134207753Smm } 135207753Smm} 136207753Smm 137207753Smm/* 138207753Smm * Print the appropriate amount of indentation given the current depth and 139207753Smm * array nesting. 140207753Smm */ 141207753Smmstatic void 142207753Smmdt_print_indent(dt_printarg_t *pap) 143207753Smm{ 144207753Smm (void) fprintf(pap->pa_file, "%*s", 145207753Smm (pap->pa_depth + pap->pa_nest) * 4, ""); 146207753Smm} 147207753Smm 148207753Smm/* 149207753Smm * Print a bitfield. It's worth noting that the D compiler support for 150207753Smm * bitfields is currently broken; printing "D`user_desc_t" (pulled in by the 151207753Smm * various D provider files) will produce incorrect results compared to 152207753Smm * "genunix`user_desc_t". 153207753Smm */ 154207753Smmstatic void 155207753Smmprint_bitfield(dt_printarg_t *pap, ulong_t off, ctf_encoding_t *ep) 156207753Smm{ 157207753Smm FILE *fp = pap->pa_file; 158207753Smm caddr_t addr = pap->pa_addr + off / NBBY; 159207753Smm uint64_t mask = (1ULL << ep->cte_bits) - 1; 160207753Smm uint64_t value = 0; 161207753Smm size_t size = (ep->cte_bits + (NBBY - 1)) / NBBY; 162207753Smm uint8_t *buf = (uint8_t *)&value; 163207753Smm uint8_t shift; 164207753Smm 165207753Smm /* 166207753Smm * On big-endian machines, we need to adjust the buf pointer to refer 167207753Smm * to the lowest 'size' bytes in 'value', and we need to shift based on 168207753Smm * the offset from the end of the data, not the offset of the start. 169207753Smm */ 170207753Smm#if BYTE_ORDER == _BIG_ENDIAN 171207753Smm buf += sizeof (value) - size; 172207753Smm off += ep->cte_bits; 173207753Smm#endif 174207753Smm bcopy(addr, buf, size); 175207753Smm shift = off % NBBY; 176207753Smm 177207753Smm /* 178207753Smm * Offsets are counted from opposite ends on little- and 179207753Smm * big-endian machines. 180207753Smm */ 181207753Smm#if BYTE_ORDER == _BIG_ENDIAN 182207753Smm shift = NBBY - shift; 183207753Smm#endif 184207753Smm 185207753Smm /* 186207753Smm * If the bits we want do not begin on a byte boundary, shift the data 187207753Smm * right so that the value is in the lowest 'cte_bits' of 'value'. 188207753Smm */ 189207753Smm if (off % NBBY != 0) 190207753Smm value >>= shift; 191207753Smm value &= mask; 192207753Smm 193207753Smm (void) fprintf(fp, "%#llx", (u_longlong_t)value); 194207753Smm} 195207753Smm 196207753Smm/* 197207753Smm * Dump the contents of memory as a fixed-size integer in hex. 198207753Smm */ 199207753Smmstatic void 200207753Smmdt_print_hex(FILE *fp, caddr_t addr, size_t size) 201207753Smm{ 202207753Smm switch (size) { 203207753Smm case sizeof (uint8_t): 204207753Smm (void) fprintf(fp, "%#x", *(uint8_t *)addr); 205207753Smm break; 206207753Smm case sizeof (uint16_t): 207207753Smm /* LINTED - alignment */ 208207753Smm (void) fprintf(fp, "%#x", *(uint16_t *)addr); 209207753Smm break; 210207753Smm case sizeof (uint32_t): 211207753Smm /* LINTED - alignment */ 212207753Smm (void) fprintf(fp, "%#x", *(uint32_t *)addr); 213207753Smm break; 214207753Smm case sizeof (uint64_t): 215207753Smm (void) fprintf(fp, "%#llx", 216207753Smm /* LINTED - alignment */ 217207753Smm (unsigned long long)*(uint64_t *)addr); 218207753Smm break; 219207753Smm default: 220207753Smm (void) fprintf(fp, "<invalid size %u>", (uint_t)size); 221207753Smm } 222207753Smm} 223207753Smm 224207753Smm/* 225207753Smm * Print an integer type. Before dumping the contents via dt_print_hex(), we 226207753Smm * first check the encoding to see if it's part of a bitfield or a character. 227207753Smm */ 228207753Smmstatic void 229207753Smmdt_print_int(ctf_id_t base, ulong_t off, dt_printarg_t *pap) 230207753Smm{ 231207753Smm FILE *fp = pap->pa_file; 232207753Smm ctf_file_t *ctfp = pap->pa_ctfp; 233207753Smm ctf_encoding_t e; 234207753Smm size_t size; 235207753Smm caddr_t addr = pap->pa_addr + off / NBBY; 236207753Smm 237207753Smm if (ctf_type_encoding(ctfp, base, &e) == CTF_ERR) { 238207753Smm (void) fprintf(fp, "<unknown encoding>"); 239207753Smm return; 240207753Smm } 241207753Smm 242207753Smm /* 243207753Smm * This comes from MDB - it's not clear under what circumstances this 244207753Smm * would be found. 245207753Smm */ 246207753Smm if (e.cte_format & CTF_INT_VARARGS) { 247207753Smm (void) fprintf(fp, "..."); 248207753Smm return; 249207753Smm } 250207753Smm 251207753Smm /* 252207753Smm * We print this as a bitfield if the bit encoding indicates it's not 253207753Smm * an even power of two byte size, or is larger than 8 bytes. 254207753Smm */ 255207753Smm size = e.cte_bits / NBBY; 256207753Smm if (size > 8 || (e.cte_bits % NBBY) != 0 || (size & (size - 1)) != 0) { 257207753Smm print_bitfield(pap, off, &e); 258207753Smm return; 259207753Smm } 260207753Smm 261207753Smm /* 262207753Smm * If this is a character, print it out as such. 263207753Smm */ 264207753Smm if (CTF_IS_CHAR(e)) { 265207753Smm char c = *(char *)addr; 266207753Smm if (isprint(c)) 267207753Smm (void) fprintf(fp, "'%c'", c); 268207753Smm else if (c == 0) 269207753Smm (void) fprintf(fp, "'\\0'"); 270207753Smm else 271207753Smm (void) fprintf(fp, "'\\%03o'", c); 272207753Smm return; 273207753Smm } 274207753Smm 275207753Smm dt_print_hex(fp, addr, size); 276207753Smm} 277207753Smm 278207753Smm/* 279207753Smm * Print a floating point (float, double, long double) value. 280207753Smm */ 281207753Smm/* ARGSUSED */ 282207753Smmstatic void 283207753Smmdt_print_float(ctf_id_t base, ulong_t off, dt_printarg_t *pap) 284207753Smm{ 285207753Smm FILE *fp = pap->pa_file; 286207753Smm ctf_file_t *ctfp = pap->pa_ctfp; 287207753Smm ctf_encoding_t e; 288207753Smm caddr_t addr = pap->pa_addr + off / NBBY; 289207753Smm 290207753Smm if (ctf_type_encoding(ctfp, base, &e) == 0) { 291207753Smm if (e.cte_format == CTF_FP_SINGLE && 292207753Smm e.cte_bits == sizeof (float) * NBBY) { 293207753Smm /* LINTED - alignment */ 294207753Smm (void) fprintf(fp, "%+.7e", *((float *)addr)); 295207753Smm } else if (e.cte_format == CTF_FP_DOUBLE && 296207753Smm e.cte_bits == sizeof (double) * NBBY) { 297207753Smm /* LINTED - alignment */ 298207753Smm (void) fprintf(fp, "%+.7e", *((double *)addr)); 299207753Smm } else if (e.cte_format == CTF_FP_LDOUBLE && 300207753Smm e.cte_bits == sizeof (long double) * NBBY) { 301207753Smm /* LINTED - alignment */ 302207753Smm (void) fprintf(fp, "%+.16LE", *((long double *)addr)); 303207753Smm } else { 304207753Smm (void) fprintf(fp, "<unknown encoding>"); 305207753Smm } 306207753Smm } 307207753Smm} 308207753Smm 309207753Smm/* 310207753Smm * A pointer is generally printed as a fixed-size integer. If we have a 311207753Smm * function pointer, we try to look up its name. 312207753Smm */ 313207753Smmstatic void 314207753Smmdt_print_ptr(ctf_id_t base, ulong_t off, dt_printarg_t *pap) 315207753Smm{ 316207753Smm FILE *fp = pap->pa_file; 317207753Smm ctf_file_t *ctfp = pap->pa_ctfp; 318207753Smm caddr_t addr = pap->pa_addr + off / NBBY; 319207753Smm size_t size = ctf_type_size(ctfp, base); 320207753Smm ctf_id_t bid = ctf_type_reference(ctfp, base); 321215187Smm uint64_t pc; 322215187Smm dtrace_syminfo_t dts; 323207753Smm GElf_Sym sym; 324207753Smm 325207753Smm if (bid == CTF_ERR || ctf_type_kind(ctfp, bid) != CTF_K_FUNCTION) { 326207753Smm dt_print_hex(fp, addr, size); 327207753Smm } else { 328207753Smm /* LINTED - alignment */ 329207753Smm pc = *((uint64_t *)addr); 330207753Smm if (dtrace_lookup_by_addr(pap->pa_dtp, pc, &sym, &dts) != 0) { 331207753Smm dt_print_hex(fp, addr, size); 332207753Smm } else { 333207753Smm (void) fprintf(fp, "%s`%s", dts.dts_object, 334207753Smm dts.dts_name); 335207753Smm } 336207753Smm } 337207753Smm} 338207753Smm 339207753Smm/* 340207753Smm * Print out an array. This is somewhat complex, as we must manually visit 341207753Smm * each member, and recursively invoke ctf_type_visit() for each member. If 342207753Smm * the members are non-structs, then we print them out directly: 343207753Smm * 344207753Smm * [ 0x14, 0x2e, 0 ] 345207753Smm * 346207753Smm * If they are structs, then we print out the necessary leading and trailing 347207753Smm * braces, to end up with: 348207753Smm * 349207753Smm * [ 350207753Smm * type { 351207753Smm * ... 352207753Smm * }, 353207753Smm * type { 354207753Smm * ... 355207753Smm * } 356207753Smm * ] 357207753Smm * 358207753Smm * We also use a heuristic to detect whether the array looks like a character 359207753Smm * array. If the encoding indicates it's a character, and we have all 360207753Smm * printable characters followed by a null byte, then we display it as a 361207753Smm * string: 362207753Smm * 363207753Smm * [ "string" ] 364207753Smm */ 365207753Smmstatic void 366207753Smmdt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap) 367207753Smm{ 368207753Smm FILE *fp = pap->pa_file; 369207753Smm ctf_file_t *ctfp = pap->pa_ctfp; 370207753Smm caddr_t addr = pap->pa_addr + off / NBBY; 371207753Smm ctf_arinfo_t car; 372207753Smm ssize_t eltsize; 373207753Smm ctf_encoding_t e; 374207753Smm int i; 375207753Smm boolean_t isstring; 376207753Smm int kind; 377207753Smm ctf_id_t rtype; 378207753Smm 379207753Smm if (ctf_array_info(ctfp, base, &car) == CTF_ERR) { 380207753Smm (void) fprintf(fp, "0x%p", (void *)addr); 381207753Smm return; 382207753Smm } 383207753Smm 384207753Smm if ((eltsize = ctf_type_size(ctfp, car.ctr_contents)) < 0 || 385207753Smm (rtype = ctf_type_resolve(ctfp, car.ctr_contents)) == CTF_ERR || 386207753Smm (kind = ctf_type_kind(ctfp, rtype)) == CTF_ERR) { 387207753Smm (void) fprintf(fp, "<invalid type %lu>", car.ctr_contents); 388207753Smm return; 389207753Smm } 390207753Smm 391207753Smm /* see if this looks like a string */ 392207753Smm isstring = B_FALSE; 393207753Smm if (kind == CTF_K_INTEGER && 394207753Smm ctf_type_encoding(ctfp, rtype, &e) != CTF_ERR && CTF_IS_CHAR(e)) { 395207753Smm char c; 396207753Smm for (i = 0; i < car.ctr_nelems; i++) { 397207753Smm c = *((char *)addr + eltsize * i); 398207753Smm if (!isprint(c) || c == '\0') 399207753Smm break; 400207753Smm } 401207753Smm 402207753Smm if (i != car.ctr_nelems && c == '\0') 403207753Smm isstring = B_TRUE; 404207753Smm } 405207753Smm 406207753Smm /* 407207753Smm * As a slight aesthetic optimization, if we are a top-level type, then 408207753Smm * don't bother printing out the brackets. This lets print("foo") look 409207753Smm * like: 410207753Smm * 411207753Smm * string "foo" 412207753Smm * 413207753Smm * As D will internally represent this as a char[256] array. 414207753Smm */ 415207753Smm if (!isstring || pap->pa_depth != 0) 416207753Smm (void) fprintf(fp, "[ "); 417207753Smm 418207753Smm if (isstring) 419207753Smm (void) fprintf(fp, "\""); 420207753Smm 421207753Smm for (i = 0; i < car.ctr_nelems; i++) { 422207753Smm if (isstring) { 423207753Smm char c = *((char *)addr + eltsize * i); 424207753Smm if (c == '\0') 425207753Smm break; 426207753Smm (void) fprintf(fp, "%c", c); 427207753Smm } else { 428207753Smm /* 429207753Smm * Recursively invoke ctf_type_visit() on each member. 430207753Smm * We setup a new printarg struct with 'pa_nest' set to 431207753Smm * indicate that we are within a nested array. 432207753Smm */ 433207753Smm dt_printarg_t pa = *pap; 434207753Smm pa.pa_nest += pap->pa_depth + 1; 435207753Smm pa.pa_depth = 0; 436207753Smm pa.pa_addr = addr + eltsize * i; 437207753Smm (void) ctf_type_visit(ctfp, car.ctr_contents, 438207753Smm dt_print_member, &pa); 439207753Smm 440207753Smm dt_print_trailing_braces(&pa, 0); 441207753Smm if (i != car.ctr_nelems - 1) 442207753Smm (void) fprintf(fp, ", "); 443207753Smm else if (CTF_IS_STRUCTLIKE(kind)) 444207753Smm (void) fprintf(fp, "\n"); 445207753Smm } 446207753Smm } 447207753Smm 448207753Smm if (isstring) 449207753Smm (void) fprintf(fp, "\""); 450207753Smm 451207753Smm if (!isstring || pap->pa_depth != 0) { 452207753Smm if (CTF_IS_STRUCTLIKE(kind)) 453207753Smm dt_print_indent(pap); 454207753Smm else 455207753Smm (void) fprintf(fp, " "); 456207753Smm (void) fprintf(fp, "]"); 457207753Smm } 458207753Smm} 459207753Smm 460207753Smm/* 461207753Smm * This isued by both structs and unions to print the leading brace. 462207753Smm */ 463207753Smm/* ARGSUSED */ 464207753Smmstatic void 465207753Smmdt_print_structlike(ctf_id_t id, ulong_t off, dt_printarg_t *pap) 466207753Smm{ 467207753Smm (void) fprintf(pap->pa_file, "{"); 468207753Smm} 469207753Smm 470207753Smm/* 471207753Smm * For enums, we try to print the enum name, and fall back to the value if it 472207753Smm * can't be determined. We do not do any fancy flag processing like mdb. 473207753Smm */ 474207753Smm/* ARGSUSED */ 475207753Smmstatic void 476207753Smmdt_print_enum(ctf_id_t base, ulong_t off, dt_printarg_t *pap) 477207753Smm{ 478207753Smm FILE *fp = pap->pa_file; 479207753Smm ctf_file_t *ctfp = pap->pa_ctfp; 480207753Smm const char *ename; 481207753Smm ssize_t size; 482207753Smm caddr_t addr = pap->pa_addr + off / NBBY; 483207753Smm int value = 0; 484207753Smm 485207753Smm /* 486207753Smm * The C standard says that an enum will be at most the sizeof (int). 487207753Smm * But if all the values are less than that, the compiler can use a 488207753Smm * smaller size. Thanks standards. 489207753Smm */ 490207753Smm size = ctf_type_size(ctfp, base); 491207753Smm switch (size) { 492207753Smm case sizeof (uint8_t): 493207753Smm value = *(uint8_t *)addr; 494207753Smm break; 495207753Smm case sizeof (uint16_t): 496207753Smm value = *(uint16_t *)addr; 497207753Smm break; 498207753Smm case sizeof (int32_t): 499207753Smm value = *(int32_t *)addr; 500207753Smm break; 501207753Smm default: 502207753Smm (void) fprintf(fp, "<invalid enum size %u>", (uint_t)size); 503207753Smm return; 504207753Smm } 505207753Smm 506207753Smm if ((ename = ctf_enum_name(ctfp, base, value)) != NULL) 507207753Smm (void) fprintf(fp, "%s", ename); 508207753Smm else 509207753Smm (void) fprintf(fp, "%d", value); 510207753Smm} 511207753Smm 512207753Smm/* 513207753Smm * Forward declaration. There's not much to do here without the complete 514207753Smm * type information, so just print out this fact and drive on. 515207753Smm */ 516207753Smm/* ARGSUSED */ 517207753Smmstatic void 518207753Smmdt_print_tag(ctf_id_t base, ulong_t off, dt_printarg_t *pap) 519207753Smm{ 520207753Smm (void) fprintf(pap->pa_file, "<forward decl>"); 521207753Smm} 522207753Smm 523207753Smmtypedef void dt_printarg_f(ctf_id_t, ulong_t, dt_printarg_t *); 524207753Smm 525207753Smmstatic dt_printarg_f *const dt_printfuncs[] = { 526207753Smm dt_print_int, /* CTF_K_INTEGER */ 527207753Smm dt_print_float, /* CTF_K_FLOAT */ 528207753Smm dt_print_ptr, /* CTF_K_POINTER */ 529207753Smm dt_print_array, /* CTF_K_ARRAY */ 530 dt_print_ptr, /* CTF_K_FUNCTION */ 531 dt_print_structlike, /* CTF_K_STRUCT */ 532 dt_print_structlike, /* CTF_K_UNION */ 533 dt_print_enum, /* CTF_K_ENUM */ 534 dt_print_tag /* CTF_K_FORWARD */ 535}; 536 537/* 538 * Print one member of a structure. This callback is invoked from 539 * ctf_type_visit() recursively. 540 */ 541static int 542dt_print_member(const char *name, ctf_id_t id, ulong_t off, int depth, 543 void *data) 544{ 545 char type[DT_TYPE_NAMELEN]; 546 int kind; 547 dt_printarg_t *pap = data; 548 FILE *fp = pap->pa_file; 549 ctf_file_t *ctfp = pap->pa_ctfp; 550 boolean_t arraymember; 551 boolean_t brief; 552 ctf_encoding_t e; 553 ctf_id_t rtype; 554 555 dt_print_trailing_braces(pap, depth); 556 /* 557 * dt_print_trailing_braces() doesn't include the trailing newline; add 558 * it here if necessary. 559 */ 560 if (depth < pap->pa_depth) 561 (void) fprintf(fp, "\n"); 562 pap->pa_depth = depth; 563 564 if ((rtype = ctf_type_resolve(ctfp, id)) == CTF_ERR || 565 (kind = ctf_type_kind(ctfp, rtype)) == CTF_ERR || 566 kind < CTF_K_INTEGER || kind > CTF_K_FORWARD) { 567 dt_print_indent(pap); 568 (void) fprintf(fp, "%s = <invalid type %lu>", name, id); 569 return (0); 570 } 571 572 dt_print_type_name(ctfp, id, type, sizeof (type)); 573 574 arraymember = (pap->pa_nest != 0 && depth == 0); 575 brief = (arraymember && !CTF_IS_STRUCTLIKE(kind)); 576 577 if (!brief) { 578 /* 579 * If this is a direct array member and a struct (otherwise 580 * brief would be true), then print a trailing newline, as the 581 * array printing code doesn't include it because it might be a 582 * simple type. 583 */ 584 if (arraymember) 585 (void) fprintf(fp, "\n"); 586 dt_print_indent(pap); 587 588 /* always print the type */ 589 (void) fprintf(fp, "%s", type); 590 if (name[0] != '\0') { 591 /* 592 * For aesthetics, we don't include a space between the 593 * type name and member name if the type is a pointer. 594 * This will give us "void *foo =" instead of "void * 595 * foo =". Unions also have the odd behavior that the 596 * type name is returned as "union ", with a trailing 597 * space, so we also avoid printing a space if the type 598 * name already ends with a space. 599 */ 600 if (type[strlen(type) - 1] != '*' && 601 type[strlen(type) -1] != ' ') { 602 (void) fprintf(fp, " "); 603 } 604 (void) fprintf(fp, "%s", name); 605 606 /* 607 * If this looks like a bitfield, or is an integer not 608 * aligned on a byte boundary, print the number of 609 * bits after the name. 610 */ 611 if (kind == CTF_K_INTEGER && 612 ctf_type_encoding(ctfp, id, &e) == 0) { 613 ulong_t bits = e.cte_bits; 614 ulong_t size = bits / NBBY; 615 616 if (bits % NBBY != 0 || 617 off % NBBY != 0 || 618 size > 8 || 619 size != ctf_type_size(ctfp, id)) { 620 (void) fprintf(fp, " :%lu", bits); 621 } 622 } 623 624 (void) fprintf(fp, " ="); 625 } 626 (void) fprintf(fp, " "); 627 } 628 629 dt_printfuncs[kind - 1](rtype, off, pap); 630 631 /* direct simple array members are not separated by newlines */ 632 if (!brief) 633 (void) fprintf(fp, "\n"); 634 635 return (0); 636} 637 638/* 639 * Main print function invoked by dt_consume_cpu(). 640 */ 641int 642dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename, 643 caddr_t addr, size_t len) 644{ 645 const char *s; 646 char *object; 647 dt_printarg_t pa; 648 ctf_id_t id; 649 dt_module_t *dmp; 650 ctf_file_t *ctfp; 651 int libid; 652 653 /* 654 * Split the fully-qualified type ID (module`id). This should 655 * always be the format, but if for some reason we don't find the 656 * expected value, return 0 to fall back to the generic trace() 657 * behavior. In the case of userland CTF modules this will actually be 658 * of the format (module`lib`id). This is due to the fact that those 659 * modules have multiple CTF containers which `lib` identifies. 660 */ 661 for (s = typename; *s != '\0' && *s != '`'; s++) 662 ; 663 664 if (*s != '`') 665 return (0); 666 667 object = alloca(s - typename + 1); 668 bcopy(typename, object, s - typename); 669 object[s - typename] = '\0'; 670 dmp = dt_module_lookup_by_name(dtp, object); 671 if (dmp == NULL) 672 return (0); 673 674 if (dmp->dm_pid != 0) { 675 libid = atoi(s + 1); 676 s = strchr(s + 1, '`'); 677 if (s == NULL || libid > dmp->dm_nctflibs) 678 return (0); 679 ctfp = dmp->dm_libctfp[libid]; 680 } else { 681 ctfp = dt_module_getctf(dtp, dmp); 682 } 683 684 id = atoi(s + 1); 685 686 /* 687 * Try to get the CTF kind for this id. If something has gone horribly 688 * wrong and we can't resolve the ID, bail out and let trace() do the 689 * work. 690 */ 691 if (ctfp == NULL || ctf_type_kind(ctfp, id) == CTF_ERR) 692 return (0); 693 694 /* setup the print structure and kick off the main print routine */ 695 pa.pa_dtp = dtp; 696 pa.pa_addr = addr; 697 pa.pa_ctfp = ctfp; 698 pa.pa_nest = 0; 699 pa.pa_depth = 0; 700 pa.pa_file = fp; 701 (void) ctf_type_visit(pa.pa_ctfp, id, dt_print_member, &pa); 702 703 dt_print_trailing_braces(&pa, 0); 704 705 return (len); 706} 707