1 /* 2 * CDDL HEADER START 3 * 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 7 * with the License. 8 * 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. 13 * 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] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/sysmacros.h> 30 #include <strings.h> 31 #include <stdlib.h> 32 #include <alloca.h> 33 #include <assert.h> 34 #include <ctype.h> 35 #include <errno.h> 36 #include <limits.h> 37 38 #include <dt_printf.h> 39 #include <dt_string.h> 40 #include <dt_impl.h> 41 42 /*ARGSUSED*/ 43 static int 44 pfcheck_addr(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 45 { 46 return (dt_node_is_pointer(dnp) || dt_node_is_integer(dnp)); 47 } 48 49 /*ARGSUSED*/ 50 static int 51 pfcheck_kaddr(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 52 { 53 return (dt_node_is_pointer(dnp) || dt_node_is_integer(dnp) || 54 dt_node_is_symaddr(dnp)); 55 } 56 57 /*ARGSUSED*/ 58 static int 59 pfcheck_uaddr(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 60 { 61 dtrace_hdl_t *dtp = pfv->pfv_dtp; 62 dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); 63 64 if (dt_node_is_usymaddr(dnp)) 65 return (1); 66 67 if (idp == NULL || idp->di_id == 0) 68 return (0); 69 70 return (dt_node_is_pointer(dnp) || dt_node_is_integer(dnp)); 71 } 72 73 /*ARGSUSED*/ 74 static int 75 pfcheck_stack(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 76 { 77 return (dt_node_is_stack(dnp)); 78 } 79 80 /*ARGSUSED*/ 81 static int 82 pfcheck_str(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 83 { 84 ctf_file_t *ctfp; 85 ctf_encoding_t e; 86 ctf_arinfo_t r; 87 ctf_id_t base; 88 uint_t kind; 89 90 if (dt_node_is_string(dnp)) 91 return (1); 92 93 ctfp = dnp->dn_ctfp; 94 base = ctf_type_resolve(ctfp, dnp->dn_type); 95 kind = ctf_type_kind(ctfp, base); 96 97 return (kind == CTF_K_ARRAY && ctf_array_info(ctfp, base, &r) == 0 && 98 (base = ctf_type_resolve(ctfp, r.ctr_contents)) != CTF_ERR && 99 ctf_type_encoding(ctfp, base, &e) == 0 && IS_CHAR(e)); 100 } 101 102 /*ARGSUSED*/ 103 static int 104 pfcheck_wstr(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 105 { 106 ctf_file_t *ctfp = dnp->dn_ctfp; 107 ctf_id_t base = ctf_type_resolve(ctfp, dnp->dn_type); 108 uint_t kind = ctf_type_kind(ctfp, base); 109 110 ctf_encoding_t e; 111 ctf_arinfo_t r; 112 113 return (kind == CTF_K_ARRAY && ctf_array_info(ctfp, base, &r) == 0 && 114 (base = ctf_type_resolve(ctfp, r.ctr_contents)) != CTF_ERR && 115 ctf_type_kind(ctfp, base) == CTF_K_INTEGER && 116 ctf_type_encoding(ctfp, base, &e) == 0 && e.cte_bits == 32); 117 } 118 119 /*ARGSUSED*/ 120 static int 121 pfcheck_csi(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 122 { 123 return (dt_node_is_integer(dnp) && 124 dt_node_type_size(dnp) <= sizeof (int)); 125 } 126 127 /*ARGSUSED*/ 128 static int 129 pfcheck_fp(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 130 { 131 return (dt_node_is_float(dnp)); 132 } 133 134 /*ARGSUSED*/ 135 static int 136 pfcheck_xint(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 137 { 138 return (dt_node_is_integer(dnp)); 139 } 140 141 /*ARGSUSED*/ 142 static int 143 pfcheck_dint(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 144 { 145 if (dnp->dn_flags & DT_NF_SIGNED) 146 pfd->pfd_flags |= DT_PFCONV_SIGNED; 147 else 148 pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'u'; 149 150 return (dt_node_is_integer(dnp)); 151 } 152 153 /*ARGSUSED*/ 154 static int 155 pfcheck_xshort(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 156 { 157 ctf_file_t *ctfp = dnp->dn_ctfp; 158 ctf_id_t type = ctf_type_resolve(ctfp, dnp->dn_type); 159 char n[DT_TYPE_NAMELEN]; 160 161 return (ctf_type_name(ctfp, type, n, sizeof (n)) != NULL && ( 162 strcmp(n, "short") == 0 || strcmp(n, "signed short") == 0 || 163 strcmp(n, "unsigned short") == 0)); 164 } 165 166 /*ARGSUSED*/ 167 static int 168 pfcheck_xlong(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 169 { 170 ctf_file_t *ctfp = dnp->dn_ctfp; 171 ctf_id_t type = ctf_type_resolve(ctfp, dnp->dn_type); 172 char n[DT_TYPE_NAMELEN]; 173 174 return (ctf_type_name(ctfp, type, n, sizeof (n)) != NULL && ( 175 strcmp(n, "long") == 0 || strcmp(n, "signed long") == 0 || 176 strcmp(n, "unsigned long") == 0)); 177 } 178 179 /*ARGSUSED*/ 180 static int 181 pfcheck_xlonglong(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 182 { 183 ctf_file_t *ctfp = dnp->dn_ctfp; 184 ctf_id_t type = dnp->dn_type; 185 char n[DT_TYPE_NAMELEN]; 186 187 if (ctf_type_name(ctfp, ctf_type_resolve(ctfp, type), n, 188 sizeof (n)) != NULL && (strcmp(n, "long long") == 0 || 189 strcmp(n, "signed long long") == 0 || 190 strcmp(n, "unsigned long long") == 0)) 191 return (1); 192 193 /* 194 * If the type used for %llx or %llX is not an [unsigned] long long, we 195 * also permit it to be a [u]int64_t or any typedef thereof. We know 196 * that these typedefs are guaranteed to work with %ll[xX] in either 197 * compilation environment even though they alias to "long" in LP64. 198 */ 199 while (ctf_type_kind(ctfp, type) == CTF_K_TYPEDEF) { 200 if (ctf_type_name(ctfp, type, n, sizeof (n)) != NULL && 201 (strcmp(n, "int64_t") == 0 || strcmp(n, "uint64_t") == 0)) 202 return (1); 203 204 type = ctf_type_reference(ctfp, type); 205 } 206 207 return (0); 208 } 209 210 /*ARGSUSED*/ 211 static int 212 pfcheck_type(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 213 { 214 return (ctf_type_compat(dnp->dn_ctfp, ctf_type_resolve(dnp->dn_ctfp, 215 dnp->dn_type), pfd->pfd_conv->pfc_dctfp, pfd->pfd_conv->pfc_dtype)); 216 } 217 218 /*ARGSUSED*/ 219 static int 220 pfprint_sint(dtrace_hdl_t *dtp, FILE *fp, const char *format, 221 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t unormal) 222 { 223 int64_t normal = (int64_t)unormal; 224 int32_t n = (int32_t)normal; 225 226 switch (size) { 227 case sizeof (int8_t): 228 return (dt_printf(dtp, fp, format, 229 (int32_t)*((int8_t *)addr) / n)); 230 case sizeof (int16_t): 231 return (dt_printf(dtp, fp, format, 232 (int32_t)*((int16_t *)addr) / n)); 233 case sizeof (int32_t): 234 return (dt_printf(dtp, fp, format, 235 *((int32_t *)addr) / n)); 236 case sizeof (int64_t): 237 return (dt_printf(dtp, fp, format, 238 *((int64_t *)addr) / normal)); 239 default: 240 return (dt_set_errno(dtp, EDT_DMISMATCH)); 241 } 242 } 243 244 /*ARGSUSED*/ 245 static int 246 pfprint_uint(dtrace_hdl_t *dtp, FILE *fp, const char *format, 247 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 248 { 249 uint32_t n = (uint32_t)normal; 250 251 switch (size) { 252 case sizeof (uint8_t): 253 return (dt_printf(dtp, fp, format, 254 (uint32_t)*((uint8_t *)addr) / n)); 255 case sizeof (uint16_t): 256 return (dt_printf(dtp, fp, format, 257 (uint32_t)*((uint16_t *)addr) / n)); 258 case sizeof (uint32_t): 259 return (dt_printf(dtp, fp, format, 260 *((uint32_t *)addr) / n)); 261 case sizeof (uint64_t): 262 return (dt_printf(dtp, fp, format, 263 *((uint64_t *)addr) / normal)); 264 default: 265 return (dt_set_errno(dtp, EDT_DMISMATCH)); 266 } 267 } 268 269 static int 270 pfprint_dint(dtrace_hdl_t *dtp, FILE *fp, const char *format, 271 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 272 { 273 if (pfd->pfd_flags & DT_PFCONV_SIGNED) 274 return (pfprint_sint(dtp, fp, format, pfd, addr, size, normal)); 275 else 276 return (pfprint_uint(dtp, fp, format, pfd, addr, size, normal)); 277 } 278 279 /*ARGSUSED*/ 280 static int 281 pfprint_fp(dtrace_hdl_t *dtp, FILE *fp, const char *format, 282 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 283 { 284 double n = (double)normal; 285 long double ldn = (long double)normal; 286 287 switch (size) { 288 case sizeof (float): 289 return (dt_printf(dtp, fp, format, 290 (double)*((float *)addr) / n)); 291 case sizeof (double): 292 return (dt_printf(dtp, fp, format, 293 *((double *)addr) / n)); 294 case sizeof (long double): 295 return (dt_printf(dtp, fp, format, 296 *((long double *)addr) / ldn)); 297 default: 298 return (dt_set_errno(dtp, EDT_DMISMATCH)); 299 } 300 } 301 302 /*ARGSUSED*/ 303 static int 304 pfprint_addr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 305 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 306 { 307 char *s; 308 int n, len = 256; 309 uint64_t val; 310 311 switch (size) { 312 case sizeof (uint32_t): 313 val = *((uint32_t *)addr); 314 break; 315 case sizeof (uint64_t): 316 val = *((uint64_t *)addr); 317 break; 318 default: 319 return (dt_set_errno(dtp, EDT_DMISMATCH)); 320 } 321 322 do { 323 n = len; 324 s = alloca(n); 325 } while ((len = dtrace_addr2str(dtp, val, s, n)) >= n); 326 327 return (dt_printf(dtp, fp, format, s)); 328 } 329 330 /*ARGSUSED*/ 331 static int 332 pfprint_mod(dtrace_hdl_t *dtp, FILE *fp, const char *format, 333 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 334 { 335 return (dt_print_mod(dtp, fp, format, (caddr_t)addr)); 336 } 337 338 /*ARGSUSED*/ 339 static int 340 pfprint_umod(dtrace_hdl_t *dtp, FILE *fp, const char *format, 341 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 342 { 343 return (dt_print_umod(dtp, fp, format, (caddr_t)addr)); 344 } 345 346 /*ARGSUSED*/ 347 static int 348 pfprint_uaddr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 349 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 350 { 351 char *s; 352 int n, len = 256; 353 uint64_t val, pid = 0; 354 355 dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); 356 357 switch (size) { 358 case sizeof (uint32_t): 359 val = (u_longlong_t)*((uint32_t *)addr); 360 break; 361 case sizeof (uint64_t): 362 val = (u_longlong_t)*((uint64_t *)addr); 363 break; 364 case sizeof (uint64_t) * 2: 365 pid = ((uint64_t *)(uintptr_t)addr)[0]; 366 val = ((uint64_t *)(uintptr_t)addr)[1]; 367 break; 368 default: 369 return (dt_set_errno(dtp, EDT_DMISMATCH)); 370 } 371 372 if (pid == 0 && dtp->dt_vector == NULL && idp != NULL) 373 pid = idp->di_id; 374 375 do { 376 n = len; 377 s = alloca(n); 378 } while ((len = dtrace_uaddr2str(dtp, pid, val, s, n)) >= n); 379 380 return (dt_printf(dtp, fp, format, s)); 381 } 382 383 /*ARGSUSED*/ 384 static int 385 pfprint_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format, 386 const dt_pfargd_t *pfd, const void *vaddr, size_t size, uint64_t normal) 387 { 388 int width; 389 dtrace_optval_t saved = dtp->dt_options[DTRACEOPT_STACKINDENT]; 390 const dtrace_recdesc_t *rec = pfd->pfd_rec; 391 caddr_t addr = (caddr_t)vaddr; 392 int err = 0; 393 394 /* 395 * We have stashed the value of the STACKINDENT option, and we will 396 * now override it for the purposes of formatting the stack. If the 397 * field has been specified as left-aligned (i.e. (%-#), we set the 398 * indentation to be the width. This is a slightly odd semantic, but 399 * it's useful functionality -- and it's slightly odd to begin with to 400 * be using a single format specifier to be formatting multiple lines 401 * of text... 402 */ 403 if (pfd->pfd_dynwidth < 0) { 404 assert(pfd->pfd_flags & DT_PFCONV_DYNWIDTH); 405 width = -pfd->pfd_dynwidth; 406 } else if (pfd->pfd_flags & DT_PFCONV_LEFT) { 407 width = pfd->pfd_dynwidth ? pfd->pfd_dynwidth : pfd->pfd_width; 408 } else { 409 width = 0; 410 } 411 412 dtp->dt_options[DTRACEOPT_STACKINDENT] = width; 413 414 switch (rec->dtrd_action) { 415 case DTRACEACT_USTACK: 416 case DTRACEACT_JSTACK: 417 err = dt_print_ustack(dtp, fp, format, addr, rec->dtrd_arg); 418 break; 419 420 case DTRACEACT_STACK: 421 err = dt_print_stack(dtp, fp, format, addr, rec->dtrd_arg, 422 rec->dtrd_size / rec->dtrd_arg); 423 break; 424 425 default: 426 assert(0); 427 } 428 429 dtp->dt_options[DTRACEOPT_STACKINDENT] = saved; 430 431 return (err); 432 } 433 434 /*ARGSUSED*/ 435 static int 436 pfprint_time(dtrace_hdl_t *dtp, FILE *fp, const char *format, 437 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 438 { 439 char src[32], buf[32], *dst = buf; 440 hrtime_t time = *((uint64_t *)addr); 441 time_t sec = (time_t)(time / NANOSEC); 442 int i; 443 444 /* 445 * ctime(3C) returns a string of the form "Dec 3 17:20:00 1973\n\0". 446 * Below, we turn this into the canonical adb/mdb /[yY] format, 447 * "1973 Dec 3 17:20:00". 448 */ 449 (void) ctime_r(&sec, src, sizeof (src)); 450 451 /* 452 * Place the 4-digit year at the head of the string... 453 */ 454 for (i = 20; i < 24; i++) 455 *dst++ = src[i]; 456 457 /* 458 * ...and follow it with the remainder (month, day, hh:mm:ss). 459 */ 460 for (i = 3; i < 19; i++) 461 *dst++ = src[i]; 462 463 *dst = '\0'; 464 return (dt_printf(dtp, fp, format, buf)); 465 } 466 467 /* 468 * This prints the time in RFC 822 standard form. This is useful for emitting 469 * notions of time that are consumed by standard tools (e.g., as part of an 470 * RSS feed). 471 */ 472 /*ARGSUSED*/ 473 static int 474 pfprint_time822(dtrace_hdl_t *dtp, FILE *fp, const char *format, 475 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 476 { 477 hrtime_t time = *((uint64_t *)addr); 478 time_t sec = (time_t)(time / NANOSEC); 479 struct tm tm; 480 char buf[64]; 481 482 (void) localtime_r(&sec, &tm); 483 (void) strftime(buf, sizeof (buf), "%a, %d %b %G %T %Z", &tm); 484 return (dt_printf(dtp, fp, format, buf)); 485 } 486 487 /*ARGSUSED*/ 488 static int 489 pfprint_cstr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 490 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 491 { 492 char *s = alloca(size + 1); 493 494 bcopy(addr, s, size); 495 s[size] = '\0'; 496 return (dt_printf(dtp, fp, format, s)); 497 } 498 499 /*ARGSUSED*/ 500 static int 501 pfprint_wstr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 502 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 503 { 504 wchar_t *ws = alloca(size + sizeof (wchar_t)); 505 506 bcopy(addr, ws, size); 507 ws[size / sizeof (wchar_t)] = L'\0'; 508 return (dt_printf(dtp, fp, format, ws)); 509 } 510 511 /*ARGSUSED*/ 512 static int 513 pfprint_estr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 514 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 515 { 516 char *s; 517 int n; 518 519 if ((s = strchr2esc(addr, size)) == NULL) 520 return (dt_set_errno(dtp, EDT_NOMEM)); 521 522 n = dt_printf(dtp, fp, format, s); 523 free(s); 524 return (n); 525 } 526 527 static int 528 pfprint_echr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 529 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 530 { 531 char c; 532 533 switch (size) { 534 case sizeof (int8_t): 535 c = *(int8_t *)addr; 536 break; 537 case sizeof (int16_t): 538 c = *(int16_t *)addr; 539 break; 540 case sizeof (int32_t): 541 c = *(int32_t *)addr; 542 break; 543 default: 544 return (dt_set_errno(dtp, EDT_DMISMATCH)); 545 } 546 547 return (pfprint_estr(dtp, fp, format, pfd, &c, 1, normal)); 548 } 549 550 /*ARGSUSED*/ 551 static int 552 pfprint_pct(dtrace_hdl_t *dtp, FILE *fp, const char *format, 553 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 554 { 555 return (dt_printf(dtp, fp, "%%")); 556 } 557 558 static const char pfproto_xint[] = "char, short, int, long, or long long"; 559 static const char pfproto_csi[] = "char, short, or int"; 560 static const char pfproto_fp[] = "float, double, or long double"; 561 static const char pfproto_addr[] = "pointer or integer"; 562 static const char pfproto_uaddr[] = 563 "pointer or integer (with -p/-c) or _usymaddr (without -p/-c)"; 564 static const char pfproto_cstr[] = "char [] or string (or use stringof)"; 565 static const char pfproto_wstr[] = "wchar_t []"; 566 567 /* 568 * Printf format conversion dictionary. This table should match the set of 569 * conversions offered by printf(3C), as well as some additional extensions. 570 * The second parameter is an ASCII string which is either an actual type 571 * name we should look up (if pfcheck_type is specified), or just a descriptive 572 * string of the types expected for use in error messages. 573 */ 574 static const dt_pfconv_t _dtrace_conversions[] = { 575 { "a", "s", pfproto_addr, pfcheck_kaddr, pfprint_addr }, 576 { "A", "s", pfproto_uaddr, pfcheck_uaddr, pfprint_uaddr }, 577 { "c", "c", pfproto_csi, pfcheck_csi, pfprint_sint }, 578 { "C", "s", pfproto_csi, pfcheck_csi, pfprint_echr }, 579 { "d", "d", pfproto_xint, pfcheck_dint, pfprint_dint }, 580 { "e", "e", pfproto_fp, pfcheck_fp, pfprint_fp }, 581 { "E", "E", pfproto_fp, pfcheck_fp, pfprint_fp }, 582 { "f", "f", pfproto_fp, pfcheck_fp, pfprint_fp }, 583 { "g", "g", pfproto_fp, pfcheck_fp, pfprint_fp }, 584 { "G", "G", pfproto_fp, pfcheck_fp, pfprint_fp }, 585 { "hd", "d", "short", pfcheck_type, pfprint_sint }, 586 { "hi", "i", "short", pfcheck_type, pfprint_sint }, 587 { "ho", "o", "unsigned short", pfcheck_type, pfprint_uint }, 588 { "hu", "u", "unsigned short", pfcheck_type, pfprint_uint }, 589 { "hx", "x", "short", pfcheck_xshort, pfprint_uint }, 590 { "hX", "X", "short", pfcheck_xshort, pfprint_uint }, 591 { "i", "i", pfproto_xint, pfcheck_dint, pfprint_dint }, 592 { "k", "s", "stack", pfcheck_stack, pfprint_stack }, 593 { "lc", "lc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wint_t */ 594 { "ld", "d", "long", pfcheck_type, pfprint_sint }, 595 { "li", "i", "long", pfcheck_type, pfprint_sint }, 596 { "lo", "o", "unsigned long", pfcheck_type, pfprint_uint }, 597 { "lu", "u", "unsigned long", pfcheck_type, pfprint_uint }, 598 { "ls", "ls", pfproto_wstr, pfcheck_wstr, pfprint_wstr }, 599 { "lx", "x", "long", pfcheck_xlong, pfprint_uint }, 600 { "lX", "X", "long", pfcheck_xlong, pfprint_uint }, 601 { "lld", "d", "long long", pfcheck_type, pfprint_sint }, 602 { "lli", "i", "long long", pfcheck_type, pfprint_sint }, 603 { "llo", "o", "unsigned long long", pfcheck_type, pfprint_uint }, 604 { "llu", "u", "unsigned long long", pfcheck_type, pfprint_uint }, 605 { "llx", "x", "long long", pfcheck_xlonglong, pfprint_uint }, 606 { "llX", "X", "long long", pfcheck_xlonglong, pfprint_uint }, 607 { "Le", "e", "long double", pfcheck_type, pfprint_fp }, 608 { "LE", "E", "long double", pfcheck_type, pfprint_fp }, 609 { "Lf", "f", "long double", pfcheck_type, pfprint_fp }, 610 { "Lg", "g", "long double", pfcheck_type, pfprint_fp }, 611 { "LG", "G", "long double", pfcheck_type, pfprint_fp }, 612 { "o", "o", pfproto_xint, pfcheck_xint, pfprint_uint }, 613 { "p", "x", pfproto_addr, pfcheck_addr, pfprint_uint }, 614 { "s", "s", "char [] or string (or use stringof)", pfcheck_str, pfprint_cstr }, 615 { "S", "s", pfproto_cstr, pfcheck_str, pfprint_estr }, 616 { "T", "s", "uint64_t", pfcheck_type, pfprint_time822 }, 617 { "u", "u", pfproto_xint, pfcheck_xint, pfprint_uint }, 618 { "wc", "wc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wchar_t */ 619 { "ws", "ws", pfproto_wstr, pfcheck_wstr, pfprint_wstr }, 620 { "x", "x", pfproto_xint, pfcheck_xint, pfprint_uint }, 621 { "X", "X", pfproto_xint, pfcheck_xint, pfprint_uint }, 622 { "Y", "s", "uint64_t", pfcheck_type, pfprint_time }, 623 { "%", "%", "void", pfcheck_type, pfprint_pct }, 624 { NULL, NULL, NULL, NULL, NULL } 625 }; 626 627 int 628 dt_pfdict_create(dtrace_hdl_t *dtp) 629 { 630 uint_t n = _dtrace_strbuckets; 631 const dt_pfconv_t *pfd; 632 dt_pfdict_t *pdi; 633 634 if ((pdi = malloc(sizeof (dt_pfdict_t))) == NULL || 635 (pdi->pdi_buckets = malloc(sizeof (dt_pfconv_t *) * n)) == NULL) { 636 free(pdi); 637 return (dt_set_errno(dtp, EDT_NOMEM)); 638 } 639 640 dtp->dt_pfdict = pdi; 641 bzero(pdi->pdi_buckets, sizeof (dt_pfconv_t *) * n); 642 pdi->pdi_nbuckets = n; 643 644 for (pfd = _dtrace_conversions; pfd->pfc_name != NULL; pfd++) { 645 dtrace_typeinfo_t dtt; 646 dt_pfconv_t *pfc; 647 uint_t h; 648 649 if ((pfc = malloc(sizeof (dt_pfconv_t))) == NULL) { 650 dt_pfdict_destroy(dtp); 651 return (dt_set_errno(dtp, EDT_NOMEM)); 652 } 653 654 bcopy(pfd, pfc, sizeof (dt_pfconv_t)); 655 h = dt_strtab_hash(pfc->pfc_name, NULL) % n; 656 pfc->pfc_next = pdi->pdi_buckets[h]; 657 pdi->pdi_buckets[h] = pfc; 658 659 dtt.dtt_ctfp = NULL; 660 dtt.dtt_type = CTF_ERR; 661 662 /* 663 * The "D" container or its parent must contain a definition of 664 * any type referenced by a printf conversion. If none can be 665 * found, we fail to initialize the printf dictionary. 666 */ 667 if (pfc->pfc_check == &pfcheck_type && dtrace_lookup_by_type( 668 dtp, DTRACE_OBJ_DDEFS, pfc->pfc_tstr, &dtt) != 0) { 669 dt_pfdict_destroy(dtp); 670 return (dt_set_errno(dtp, EDT_NOCONV)); 671 } 672 673 pfc->pfc_dctfp = dtt.dtt_ctfp; 674 pfc->pfc_dtype = dtt.dtt_type; 675 676 /* 677 * The "C" container may contain an alternate definition of an 678 * explicit conversion type. If it does, use it; otherwise 679 * just set pfc_ctype to pfc_dtype so it is always valid. 680 */ 681 if (pfc->pfc_check == &pfcheck_type && dtrace_lookup_by_type( 682 dtp, DTRACE_OBJ_CDEFS, pfc->pfc_tstr, &dtt) == 0) { 683 pfc->pfc_cctfp = dtt.dtt_ctfp; 684 pfc->pfc_ctype = dtt.dtt_type; 685 } else { 686 pfc->pfc_cctfp = pfc->pfc_dctfp; 687 pfc->pfc_ctype = pfc->pfc_dtype; 688 } 689 690 if (pfc->pfc_check == NULL || pfc->pfc_print == NULL || 691 pfc->pfc_ofmt == NULL || pfc->pfc_tstr == NULL) { 692 dt_pfdict_destroy(dtp); 693 return (dt_set_errno(dtp, EDT_BADCONV)); 694 } 695 696 dt_dprintf("loaded printf conversion %%%s\n", pfc->pfc_name); 697 } 698 699 return (0); 700 } 701 702 void 703 dt_pfdict_destroy(dtrace_hdl_t *dtp) 704 { 705 dt_pfdict_t *pdi = dtp->dt_pfdict; 706 dt_pfconv_t *pfc, *nfc; 707 uint_t i; 708 709 if (pdi == NULL) 710 return; 711 712 for (i = 0; i < pdi->pdi_nbuckets; i++) { 713 for (pfc = pdi->pdi_buckets[i]; pfc != NULL; pfc = nfc) { 714 nfc = pfc->pfc_next; 715 free(pfc); 716 } 717 } 718 719 free(pdi->pdi_buckets); 720 free(pdi); 721 dtp->dt_pfdict = NULL; 722 } 723 724 static const dt_pfconv_t * 725 dt_pfdict_lookup(dtrace_hdl_t *dtp, const char *name) 726 { 727 dt_pfdict_t *pdi = dtp->dt_pfdict; 728 uint_t h = dt_strtab_hash(name, NULL) % pdi->pdi_nbuckets; 729 const dt_pfconv_t *pfc; 730 731 for (pfc = pdi->pdi_buckets[h]; pfc != NULL; pfc = pfc->pfc_next) { 732 if (strcmp(pfc->pfc_name, name) == 0) 733 break; 734 } 735 736 return (pfc); 737 } 738 739 static dt_pfargv_t * 740 dt_printf_error(dtrace_hdl_t *dtp, int err) 741 { 742 if (yypcb != NULL) 743 longjmp(yypcb->pcb_jmpbuf, err); 744 745 (void) dt_set_errno(dtp, err); 746 return (NULL); 747 } 748 749 dt_pfargv_t * 750 dt_printf_create(dtrace_hdl_t *dtp, const char *s) 751 { 752 dt_pfargd_t *pfd, *nfd = NULL; 753 dt_pfargv_t *pfv; 754 const char *p, *q; 755 char *format; 756 757 if ((pfv = malloc(sizeof (dt_pfargv_t))) == NULL || 758 (format = strdup(s)) == NULL) { 759 free(pfv); 760 return (dt_printf_error(dtp, EDT_NOMEM)); 761 } 762 763 pfv->pfv_format = format; 764 pfv->pfv_argv = NULL; 765 pfv->pfv_argc = 0; 766 pfv->pfv_flags = 0; 767 pfv->pfv_dtp = dtp; 768 769 for (q = format; (p = strchr(q, '%')) != NULL; q = *p ? p + 1 : p) { 770 uint_t namelen = 0; 771 int digits = 0; 772 int dot = 0; 773 774 char name[8]; 775 char c; 776 int n; 777 778 if ((pfd = malloc(sizeof (dt_pfargd_t))) == NULL) { 779 dt_printf_destroy(pfv); 780 return (dt_printf_error(dtp, EDT_NOMEM)); 781 } 782 783 if (pfv->pfv_argv != NULL) 784 nfd->pfd_next = pfd; 785 else 786 pfv->pfv_argv = pfd; 787 788 bzero(pfd, sizeof (dt_pfargd_t)); 789 pfv->pfv_argc++; 790 nfd = pfd; 791 792 if (p > q) { 793 pfd->pfd_preflen = (size_t)(p - q); 794 pfd->pfd_prefix = q; 795 } 796 797 fmt_switch: 798 switch (c = *++p) { 799 case '0': case '1': case '2': case '3': case '4': 800 case '5': case '6': case '7': case '8': case '9': 801 if (dot == 0 && digits == 0 && c == '0') { 802 pfd->pfd_flags |= DT_PFCONV_ZPAD; 803 pfd->pfd_flags &= ~DT_PFCONV_LEFT; 804 goto fmt_switch; 805 } 806 807 for (n = 0; isdigit(c); c = *++p) 808 n = n * 10 + c - '0'; 809 810 if (dot) 811 pfd->pfd_prec = n; 812 else 813 pfd->pfd_width = n; 814 815 p--; 816 digits++; 817 goto fmt_switch; 818 819 case '#': 820 pfd->pfd_flags |= DT_PFCONV_ALT; 821 goto fmt_switch; 822 823 case '*': 824 n = dot ? DT_PFCONV_DYNPREC : DT_PFCONV_DYNWIDTH; 825 826 if (pfd->pfd_flags & n) { 827 yywarn("format conversion #%u has more than " 828 "one '*' specified for the output %s\n", 829 pfv->pfv_argc, n ? "precision" : "width"); 830 831 dt_printf_destroy(pfv); 832 return (dt_printf_error(dtp, EDT_COMPILER)); 833 } 834 835 pfd->pfd_flags |= n; 836 goto fmt_switch; 837 838 case '+': 839 pfd->pfd_flags |= DT_PFCONV_SPOS; 840 goto fmt_switch; 841 842 case '-': 843 pfd->pfd_flags |= DT_PFCONV_LEFT; 844 pfd->pfd_flags &= ~DT_PFCONV_ZPAD; 845 goto fmt_switch; 846 847 case '.': 848 if (dot++ != 0) { 849 yywarn("format conversion #%u has more than " 850 "one '.' specified\n", pfv->pfv_argc); 851 852 dt_printf_destroy(pfv); 853 return (dt_printf_error(dtp, EDT_COMPILER)); 854 } 855 digits = 0; 856 goto fmt_switch; 857 858 case '?': 859 if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64) 860 pfd->pfd_width = 16; 861 else 862 pfd->pfd_width = 8; 863 goto fmt_switch; 864 865 case '@': 866 pfd->pfd_flags |= DT_PFCONV_AGG; 867 goto fmt_switch; 868 869 case '\'': 870 pfd->pfd_flags |= DT_PFCONV_GROUP; 871 goto fmt_switch; 872 873 case ' ': 874 pfd->pfd_flags |= DT_PFCONV_SPACE; 875 goto fmt_switch; 876 877 case '$': 878 yywarn("format conversion #%u uses unsupported " 879 "positional format (%%n$)\n", pfv->pfv_argc); 880 881 dt_printf_destroy(pfv); 882 return (dt_printf_error(dtp, EDT_COMPILER)); 883 884 case '%': 885 if (p[-1] == '%') 886 goto default_lbl; /* if %% then use "%" conv */ 887 888 yywarn("format conversion #%u cannot be combined " 889 "with other format flags: %%%%\n", pfv->pfv_argc); 890 891 dt_printf_destroy(pfv); 892 return (dt_printf_error(dtp, EDT_COMPILER)); 893 894 case '\0': 895 yywarn("format conversion #%u name expected before " 896 "end of format string\n", pfv->pfv_argc); 897 898 dt_printf_destroy(pfv); 899 return (dt_printf_error(dtp, EDT_COMPILER)); 900 901 case 'h': 902 case 'l': 903 case 'L': 904 case 'w': 905 if (namelen < sizeof (name) - 2) 906 name[namelen++] = c; 907 goto fmt_switch; 908 909 default_lbl: 910 default: 911 name[namelen++] = c; 912 name[namelen] = '\0'; 913 } 914 915 pfd->pfd_conv = dt_pfdict_lookup(dtp, name); 916 917 if (pfd->pfd_conv == NULL) { 918 yywarn("format conversion #%u is undefined: %%%s\n", 919 pfv->pfv_argc, name); 920 dt_printf_destroy(pfv); 921 return (dt_printf_error(dtp, EDT_COMPILER)); 922 } 923 } 924 925 if (*q != '\0' || *format == '\0') { 926 if ((pfd = malloc(sizeof (dt_pfargd_t))) == NULL) { 927 dt_printf_destroy(pfv); 928 return (dt_printf_error(dtp, EDT_NOMEM)); 929 } 930 931 if (pfv->pfv_argv != NULL) 932 nfd->pfd_next = pfd; 933 else 934 pfv->pfv_argv = pfd; 935 936 bzero(pfd, sizeof (dt_pfargd_t)); 937 pfv->pfv_argc++; 938 939 pfd->pfd_prefix = q; 940 pfd->pfd_preflen = strlen(q); 941 } 942 943 return (pfv); 944 } 945 946 void 947 dt_printf_destroy(dt_pfargv_t *pfv) 948 { 949 dt_pfargd_t *pfd, *nfd; 950 951 for (pfd = pfv->pfv_argv; pfd != NULL; pfd = nfd) { 952 nfd = pfd->pfd_next; 953 free(pfd); 954 } 955 956 free(pfv->pfv_format); 957 free(pfv); 958 } 959 960 void 961 dt_printf_validate(dt_pfargv_t *pfv, uint_t flags, 962 dt_ident_t *idp, int foff, dtrace_actkind_t kind, dt_node_t *dnp) 963 { 964 dt_pfargd_t *pfd = pfv->pfv_argv; 965 const char *func = idp->di_name; 966 967 char n[DT_TYPE_NAMELEN]; 968 dtrace_typeinfo_t dtt; 969 const char *aggtype; 970 dt_node_t aggnode; 971 int i, j; 972 973 if (pfv->pfv_format[0] == '\0') { 974 xyerror(D_PRINTF_FMT_EMPTY, 975 "%s( ) format string is empty\n", func); 976 } 977 978 pfv->pfv_flags = flags; 979 980 /* 981 * We fake up a parse node representing the type that can be used with 982 * an aggregation result conversion. For now we hardcode the signed 983 * aggregations; this will be fixed later when sign issues are fixed. 984 */ 985 if (kind == DTRACEAGG_QUANTIZE || kind == DTRACEAGG_LQUANTIZE) 986 aggtype = "int64_t"; 987 else 988 aggtype = "uint64_t"; 989 990 if (dt_type_lookup(aggtype, &dtt) != 0) 991 xyerror(D_TYPE_ERR, "failed to lookup agg type %s\n", aggtype); 992 993 bzero(&aggnode, sizeof (aggnode)); 994 dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type); 995 996 for (i = 0, j = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) { 997 const dt_pfconv_t *pfc = pfd->pfd_conv; 998 const char *dyns[2]; 999 int dync = 0; 1000 1001 char vname[64]; 1002 dt_node_t *vnp; 1003 1004 if (pfc == NULL) 1005 continue; /* no checking if argd is just a prefix */ 1006 1007 if (pfc->pfc_print == &pfprint_pct) { 1008 (void) strcat(pfd->pfd_fmt, pfc->pfc_ofmt); 1009 continue; 1010 } 1011 1012 if (pfd->pfd_flags & DT_PFCONV_DYNPREC) 1013 dyns[dync++] = ".*"; 1014 if (pfd->pfd_flags & DT_PFCONV_DYNWIDTH) 1015 dyns[dync++] = "*"; 1016 1017 for (; dync != 0; dync--) { 1018 if (dnp == NULL) { 1019 xyerror(D_PRINTF_DYN_PROTO, 1020 "%s( ) prototype mismatch: conversion " 1021 "#%d (%%%s) is missing a corresponding " 1022 "\"%s\" argument\n", func, i + 1, 1023 pfc->pfc_name, dyns[dync - 1]); 1024 } 1025 1026 if (dt_node_is_integer(dnp) == 0) { 1027 xyerror(D_PRINTF_DYN_TYPE, 1028 "%s( ) argument #%d is incompatible " 1029 "with conversion #%d prototype:\n" 1030 "\tconversion: %% %s %s\n" 1031 "\t prototype: int\n\t argument: %s\n", 1032 func, j + foff + 1, i + 1, 1033 dyns[dync - 1], pfc->pfc_name, 1034 dt_node_type_name(dnp, n, sizeof (n))); 1035 } 1036 1037 dnp = dnp->dn_list; 1038 j++; 1039 } 1040 1041 /* 1042 * If this conversion is consuming the aggregation data, set 1043 * the value node pointer (vnp) to a fake node based on the 1044 * aggregating function result type. Otherwise assign vnp to 1045 * the next parse node in the argument list, if there is one. 1046 */ 1047 if (pfd->pfd_flags & DT_PFCONV_AGG) { 1048 if (!(flags & DT_PRINTF_AGGREGATION)) { 1049 xyerror(D_PRINTF_AGG_CONV, 1050 "%%@ conversion requires an aggregation" 1051 " and is not for use with %s( )\n", func); 1052 } 1053 (void) strlcpy(vname, "aggregating action", 1054 sizeof (vname)); 1055 vnp = &aggnode; 1056 } else if (dnp == NULL) { 1057 xyerror(D_PRINTF_ARG_PROTO, 1058 "%s( ) prototype mismatch: conversion #%d (%%" 1059 "%s) is missing a corresponding value argument\n", 1060 func, i + 1, pfc->pfc_name); 1061 } else { 1062 (void) snprintf(vname, sizeof (vname), 1063 "argument #%d", j + foff + 1); 1064 vnp = dnp; 1065 dnp = dnp->dn_list; 1066 j++; 1067 } 1068 1069 /* 1070 * Fill in the proposed final format string by prepending any 1071 * size-related prefixes to the pfconv's format string. The 1072 * pfc_check() function below may optionally modify the format 1073 * as part of validating the type of the input argument. 1074 */ 1075 if (pfc->pfc_print == &pfprint_sint || 1076 pfc->pfc_print == &pfprint_uint || 1077 pfc->pfc_print == &pfprint_dint) { 1078 if (dt_node_type_size(vnp) == sizeof (uint64_t)) 1079 (void) strcpy(pfd->pfd_fmt, "ll"); 1080 } else if (pfc->pfc_print == &pfprint_fp) { 1081 if (dt_node_type_size(vnp) == sizeof (long double)) 1082 (void) strcpy(pfd->pfd_fmt, "L"); 1083 } 1084 1085 (void) strcat(pfd->pfd_fmt, pfc->pfc_ofmt); 1086 1087 /* 1088 * Validate the format conversion against the value node type. 1089 * If the conversion is good, create the descriptor format 1090 * string by concatenating together any required printf(3C) 1091 * size prefixes with the conversion's native format string. 1092 */ 1093 if (pfc->pfc_check(pfv, pfd, vnp) == 0) { 1094 xyerror(D_PRINTF_ARG_TYPE, 1095 "%s( ) %s is incompatible with " 1096 "conversion #%d prototype:\n\tconversion: %%%s\n" 1097 "\t prototype: %s\n\t argument: %s\n", func, 1098 vname, i + 1, pfc->pfc_name, pfc->pfc_tstr, 1099 dt_node_type_name(vnp, n, sizeof (n))); 1100 } 1101 } 1102 1103 if ((flags & DT_PRINTF_EXACTLEN) && dnp != NULL) { 1104 xyerror(D_PRINTF_ARG_EXTRA, 1105 "%s( ) prototype mismatch: only %d arguments " 1106 "required by this format string\n", func, j); 1107 } 1108 } 1109 1110 static int 1111 dt_printf_getint(dtrace_hdl_t *dtp, const dtrace_recdesc_t *recp, 1112 uint_t nrecs, const void *buf, size_t len, int *ip) 1113 { 1114 uintptr_t addr; 1115 1116 if (nrecs == 0) 1117 return (dt_set_errno(dtp, EDT_DMISMATCH)); 1118 1119 addr = (uintptr_t)buf + recp->dtrd_offset; 1120 1121 if (addr + sizeof (int) > (uintptr_t)buf + len) 1122 return (dt_set_errno(dtp, EDT_DOFFSET)); 1123 1124 if (addr & (recp->dtrd_alignment - 1)) 1125 return (dt_set_errno(dtp, EDT_DALIGN)); 1126 1127 switch (recp->dtrd_size) { 1128 case sizeof (int8_t): 1129 *ip = (int)*((int8_t *)addr); 1130 break; 1131 case sizeof (int16_t): 1132 *ip = (int)*((int16_t *)addr); 1133 break; 1134 case sizeof (int32_t): 1135 *ip = (int)*((int32_t *)addr); 1136 break; 1137 case sizeof (int64_t): 1138 *ip = (int)*((int64_t *)addr); 1139 break; 1140 default: 1141 return (dt_set_errno(dtp, EDT_DMISMATCH)); 1142 } 1143 1144 return (0); 1145 } 1146 1147 /*ARGSUSED*/ 1148 static int 1149 pfprint_average(dtrace_hdl_t *dtp, FILE *fp, const char *format, 1150 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 1151 { 1152 const uint64_t *data = addr; 1153 1154 if (size != sizeof (uint64_t) * 2) 1155 return (dt_set_errno(dtp, EDT_DMISMATCH)); 1156 1157 return (dt_printf(dtp, fp, format, 1158 data[0] ? data[1] / normal / data[0] : 0)); 1159 } 1160 1161 /*ARGSUSED*/ 1162 static int 1163 pfprint_quantize(dtrace_hdl_t *dtp, FILE *fp, const char *format, 1164 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 1165 { 1166 return (dt_print_quantize(dtp, fp, addr, size, normal)); 1167 } 1168 1169 /*ARGSUSED*/ 1170 static int 1171 pfprint_lquantize(dtrace_hdl_t *dtp, FILE *fp, const char *format, 1172 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 1173 { 1174 return (dt_print_lquantize(dtp, fp, addr, size, normal)); 1175 } 1176 1177 static int 1178 dt_printf_format(dtrace_hdl_t *dtp, FILE *fp, const dt_pfargv_t *pfv, 1179 const dtrace_recdesc_t *recs, uint_t nrecs, const void *buf, 1180 size_t len, const dtrace_aggdata_t *adp) 1181 { 1182 dt_pfargd_t *pfd = pfv->pfv_argv; 1183 const dtrace_recdesc_t *recp = recs; 1184 const dtrace_recdesc_t *aggr = NULL; 1185 uchar_t *lim = (uchar_t *)buf + len; 1186 char format[64] = "%"; 1187 uint64_t normal = adp ? adp->dtada_normal : 1; 1188 int i; 1189 1190 /* 1191 * If we are formatting an aggregation, set 'aggr' to the final record 1192 * description (the aggregation result) so we can use this record with 1193 * any conversion where DT_PFCONV_AGG is set. We then decrement nrecs 1194 * to prevent this record from being used with any other conversion. 1195 */ 1196 if (pfv->pfv_flags & DT_PRINTF_AGGREGATION) { 1197 assert(adp != NULL); 1198 if (nrecs == 0) 1199 return (dt_set_errno(dtp, EDT_DMISMATCH)); 1200 aggr = recp + nrecs - 1; 1201 nrecs--; 1202 } 1203 1204 for (i = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) { 1205 const dt_pfconv_t *pfc = pfd->pfd_conv; 1206 int width = pfd->pfd_width; 1207 int prec = pfd->pfd_prec; 1208 int rval; 1209 1210 char *f = format + 1; /* skip initial '%' */ 1211 const dtrace_recdesc_t *rec; 1212 dt_pfprint_f *func; 1213 uchar_t *addr; 1214 size_t size; 1215 1216 if (pfd->pfd_preflen != 0) { 1217 char *tmp = alloca(pfd->pfd_preflen + 1); 1218 1219 bcopy(pfd->pfd_prefix, tmp, pfd->pfd_preflen); 1220 tmp[pfd->pfd_preflen] = '\0'; 1221 1222 if ((rval = dt_printf(dtp, fp, tmp)) < 0) 1223 return (rval); 1224 1225 if (pfv->pfv_flags & DT_PRINTF_AGGREGATION) { 1226 /* 1227 * For printa(), we flush the buffer after each 1228 * prefix, setting the record to NULL to 1229 * indicate that this does not correspond to 1230 * a particular tuple element, but is rather 1231 * part of the format string. 1232 */ 1233 if (dt_buffered_flush(dtp, NULL, NULL, adp) < 0) 1234 return (-1); 1235 } 1236 } 1237 1238 if (pfc == NULL) { 1239 if (pfv->pfv_argc == 1) 1240 return (nrecs != 0); 1241 continue; 1242 } 1243 1244 /* 1245 * If the conversion is %%, just invoke the print callback 1246 * with no data record and continue; it consumes no record. 1247 */ 1248 if (pfc->pfc_print == &pfprint_pct) { 1249 if (pfc->pfc_print(dtp, fp, NULL, pfd, NULL, 0, 1) >= 0) 1250 continue; 1251 return (-1); /* errno is set for us */ 1252 } 1253 1254 if (pfd->pfd_flags & DT_PFCONV_DYNWIDTH) { 1255 if (dt_printf_getint(dtp, recp++, nrecs--, buf, 1256 len, &width) == -1) 1257 return (-1); /* errno is set for us */ 1258 pfd->pfd_dynwidth = width; 1259 } else { 1260 pfd->pfd_dynwidth = 0; 1261 } 1262 1263 if ((pfd->pfd_flags & DT_PFCONV_DYNPREC) && dt_printf_getint( 1264 dtp, recp++, nrecs--, buf, len, &prec) == -1) 1265 return (-1); /* errno is set for us */ 1266 1267 if (pfd->pfd_flags & DT_PFCONV_AGG) { 1268 if (aggr == NULL) 1269 return (dt_set_errno(dtp, EDT_DMISMATCH)); 1270 rec = aggr; 1271 } else { 1272 if (nrecs == 0) 1273 return (dt_set_errno(dtp, EDT_DMISMATCH)); 1274 rec = recp++; 1275 nrecs--; 1276 } 1277 1278 addr = (uchar_t *)buf + rec->dtrd_offset; 1279 size = rec->dtrd_size; 1280 1281 if (addr + size > lim) { 1282 dt_dprintf("bad size: addr=%p size=0x%x lim=%p\n", 1283 (void *)addr, rec->dtrd_size, (void *)lim); 1284 return (dt_set_errno(dtp, EDT_DOFFSET)); 1285 } 1286 1287 if (rec->dtrd_alignment != 0 && 1288 ((uintptr_t)addr & (rec->dtrd_alignment - 1)) != 0) { 1289 dt_dprintf("bad align: addr=%p size=0x%x align=0x%x\n", 1290 (void *)addr, rec->dtrd_size, rec->dtrd_alignment); 1291 return (dt_set_errno(dtp, EDT_DALIGN)); 1292 } 1293 1294 switch (rec->dtrd_action) { 1295 case DTRACEAGG_AVG: 1296 func = pfprint_average; 1297 break; 1298 case DTRACEAGG_QUANTIZE: 1299 func = pfprint_quantize; 1300 break; 1301 case DTRACEAGG_LQUANTIZE: 1302 func = pfprint_lquantize; 1303 break; 1304 case DTRACEACT_MOD: 1305 func = pfprint_mod; 1306 break; 1307 case DTRACEACT_UMOD: 1308 func = pfprint_umod; 1309 break; 1310 default: 1311 func = pfc->pfc_print; 1312 break; 1313 } 1314 1315 if (pfd->pfd_flags & DT_PFCONV_ALT) 1316 *f++ = '#'; 1317 if (pfd->pfd_flags & DT_PFCONV_ZPAD) 1318 *f++ = '0'; 1319 if (pfd->pfd_flags & DT_PFCONV_LEFT) 1320 *f++ = '-'; 1321 if (pfd->pfd_flags & DT_PFCONV_SPOS) 1322 *f++ = '+'; 1323 if (pfd->pfd_flags & DT_PFCONV_GROUP) 1324 *f++ = '\''; 1325 if (pfd->pfd_flags & DT_PFCONV_SPACE) 1326 *f++ = ' '; 1327 1328 /* 1329 * If we're printing a stack and DT_PFCONV_LEFT is set, we 1330 * don't add the width to the format string. See the block 1331 * comment in pfprint_stack() for a description of the 1332 * behavior in this case. 1333 */ 1334 if (func == pfprint_stack && (pfd->pfd_flags & DT_PFCONV_LEFT)) 1335 width = 0; 1336 1337 if (width != 0) 1338 f += snprintf(f, sizeof (format), "%d", width); 1339 1340 if (prec != 0) 1341 f += snprintf(f, sizeof (format), ".%d", prec); 1342 1343 (void) strcpy(f, pfd->pfd_fmt); 1344 pfd->pfd_rec = rec; 1345 1346 if (func(dtp, fp, format, pfd, addr, size, 1347 rec == aggr ? normal : 1) < 0) 1348 return (-1); /* errno is set for us */ 1349 1350 if (pfv->pfv_flags & DT_PRINTF_AGGREGATION) { 1351 /* 1352 * For printa(), we flush the buffer after each tuple 1353 * element. 1354 */ 1355 if (dt_buffered_flush(dtp, NULL, rec, adp) < 0) 1356 return (-1); 1357 } 1358 } 1359 1360 return ((int)(recp - recs)); 1361 } 1362 1363 int 1364 dtrace_sprintf(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata, 1365 const dtrace_recdesc_t *recp, uint_t nrecs, const void *buf, size_t len) 1366 { 1367 dtrace_optval_t size; 1368 int rval; 1369 1370 rval = dtrace_getopt(dtp, "strsize", &size); 1371 assert(rval == 0); 1372 assert(dtp->dt_sprintf_buflen == 0); 1373 1374 if (dtp->dt_sprintf_buf != NULL) 1375 free(dtp->dt_sprintf_buf); 1376 1377 if ((dtp->dt_sprintf_buf = malloc(size)) == NULL) 1378 return (dt_set_errno(dtp, EDT_NOMEM)); 1379 1380 bzero(dtp->dt_sprintf_buf, size); 1381 dtp->dt_sprintf_buflen = size; 1382 rval = dt_printf_format(dtp, fp, fmtdata, recp, nrecs, buf, len, NULL); 1383 dtp->dt_sprintf_buflen = 0; 1384 1385 if (rval == -1) 1386 free(dtp->dt_sprintf_buf); 1387 1388 return (rval); 1389 } 1390 1391 /*ARGSUSED*/ 1392 int 1393 dtrace_system(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata, 1394 const dtrace_probedata_t *data, const dtrace_recdesc_t *recp, 1395 uint_t nrecs, const void *buf, size_t len) 1396 { 1397 int rval = dtrace_sprintf(dtp, fp, fmtdata, recp, nrecs, buf, len); 1398 1399 if (rval == -1) 1400 return (rval); 1401 1402 /* 1403 * Before we execute the specified command, flush fp to assure that 1404 * any prior dt_printf()'s appear before the output of the command 1405 * not after it. 1406 */ 1407 (void) fflush(fp); 1408 1409 if (system(dtp->dt_sprintf_buf) == -1) 1410 return (dt_set_errno(dtp, errno)); 1411 1412 return (rval); 1413 } 1414 1415 int 1416 dtrace_freopen(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata, 1417 const dtrace_probedata_t *data, const dtrace_recdesc_t *recp, 1418 uint_t nrecs, const void *buf, size_t len) 1419 { 1420 char selfbuf[40], restorebuf[40], *filename; 1421 FILE *nfp; 1422 int rval, errval; 1423 dt_pfargv_t *pfv = fmtdata; 1424 dt_pfargd_t *pfd = pfv->pfv_argv; 1425 1426 rval = dtrace_sprintf(dtp, fp, fmtdata, recp, nrecs, buf, len); 1427 1428 if (rval == -1 || fp == NULL) 1429 return (rval); 1430 1431 if (pfd->pfd_preflen != 0 && 1432 strcmp(pfd->pfd_prefix, DT_FREOPEN_RESTORE) == 0) { 1433 /* 1434 * The only way to have the format string set to the value 1435 * DT_FREOPEN_RESTORE is via the empty freopen() string -- 1436 * denoting that we should restore the old stdout. 1437 */ 1438 assert(strcmp(dtp->dt_sprintf_buf, DT_FREOPEN_RESTORE) == 0); 1439 1440 if (dtp->dt_stdout_fd == -1) { 1441 /* 1442 * We could complain here by generating an error, 1443 * but it seems like overkill: it seems that calling 1444 * freopen() to restore stdout when freopen() has 1445 * never before been called should just be a no-op, 1446 * so we just return in this case. 1447 */ 1448 return (rval); 1449 } 1450 1451 (void) snprintf(restorebuf, sizeof (restorebuf), 1452 "/dev/fd/%d", dtp->dt_stdout_fd); 1453 filename = restorebuf; 1454 } else { 1455 filename = dtp->dt_sprintf_buf; 1456 } 1457 1458 /* 1459 * freopen(3C) will always close the specified stream and underlying 1460 * file descriptor -- even if the specified file can't be opened. 1461 * Even for the semantic cesspool that is standard I/O, this is 1462 * surprisingly brain-dead behavior: it means that any failure to 1463 * open the specified file destroys the specified stream in the 1464 * process -- which is particularly relevant when the specified stream 1465 * happens (or rather, happened) to be stdout. This could be resolved 1466 * were there an "fdreopen()" equivalent of freopen() that allowed one 1467 * to pass a file descriptor instead of the name of a file, but there 1468 * is no such thing. However, we can effect this ourselves by first 1469 * fopen()'ing the desired file, and then (assuming that that works), 1470 * freopen()'ing "/dev/fd/[fileno]", where [fileno] is the underlying 1471 * file descriptor for the fopen()'d file. This way, if the fopen() 1472 * fails, we can fail the operation without destroying stdout. 1473 */ 1474 if ((nfp = fopen(filename, "aw")) == NULL) { 1475 char *msg = strerror(errno), *faultstr; 1476 int len = 80; 1477 1478 len += strlen(msg) + strlen(filename); 1479 faultstr = alloca(len); 1480 1481 (void) snprintf(faultstr, len, "couldn't freopen() \"%s\": %s", 1482 filename, strerror(errno)); 1483 1484 if ((errval = dt_handle_liberr(dtp, data, faultstr)) == 0) 1485 return (rval); 1486 1487 return (errval); 1488 } 1489 1490 (void) snprintf(selfbuf, sizeof (selfbuf), "/dev/fd/%d", fileno(nfp)); 1491 1492 if (dtp->dt_stdout_fd == -1) { 1493 /* 1494 * If this is the first time that we're calling freopen(), 1495 * we're going to stash away the file descriptor for stdout. 1496 * We don't expect the dup(2) to fail, so if it does we must 1497 * return failure. 1498 */ 1499 if ((dtp->dt_stdout_fd = dup(fileno(fp))) == -1) { 1500 (void) fclose(nfp); 1501 return (dt_set_errno(dtp, errno)); 1502 } 1503 } 1504 1505 if (freopen(selfbuf, "aw", fp) == NULL) { 1506 (void) fclose(nfp); 1507 return (dt_set_errno(dtp, errno)); 1508 } 1509 1510 (void) fclose(nfp); 1511 1512 return (rval); 1513 } 1514 1515 /*ARGSUSED*/ 1516 int 1517 dtrace_fprintf(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata, 1518 const dtrace_probedata_t *data, const dtrace_recdesc_t *recp, 1519 uint_t nrecs, const void *buf, size_t len) 1520 { 1521 return (dt_printf_format(dtp, fp, fmtdata, 1522 recp, nrecs, buf, len, NULL)); 1523 } 1524 1525 void * 1526 dtrace_printf_create(dtrace_hdl_t *dtp, const char *s) 1527 { 1528 dt_pfargv_t *pfv = dt_printf_create(dtp, s); 1529 dt_pfargd_t *pfd; 1530 int i; 1531 1532 if (pfv == NULL) 1533 return (NULL); /* errno has been set for us */ 1534 1535 pfd = pfv->pfv_argv; 1536 1537 for (i = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) { 1538 const dt_pfconv_t *pfc = pfd->pfd_conv; 1539 1540 if (pfc == NULL) 1541 continue; 1542 1543 /* 1544 * If the output format is not %s then we assume that we have 1545 * been given a correctly-sized format string, so we copy the 1546 * true format name including the size modifier. If the output 1547 * format is %s, then either the input format is %s as well or 1548 * it is one of our custom formats (e.g. pfprint_addr), so we 1549 * must set pfd_fmt to be the output format conversion "s". 1550 */ 1551 if (strcmp(pfc->pfc_ofmt, "s") != 0) 1552 (void) strcat(pfd->pfd_fmt, pfc->pfc_name); 1553 else 1554 (void) strcat(pfd->pfd_fmt, pfc->pfc_ofmt); 1555 } 1556 1557 return (pfv); 1558 } 1559 1560 void * 1561 dtrace_printa_create(dtrace_hdl_t *dtp, const char *s) 1562 { 1563 dt_pfargv_t *pfv = dtrace_printf_create(dtp, s); 1564 1565 if (pfv == NULL) 1566 return (NULL); /* errno has been set for us */ 1567 1568 pfv->pfv_flags |= DT_PRINTF_AGGREGATION; 1569 1570 return (pfv); 1571 } 1572 1573 /*ARGSUSED*/ 1574 size_t 1575 dtrace_printf_format(dtrace_hdl_t *dtp, void *fmtdata, char *s, size_t len) 1576 { 1577 dt_pfargv_t *pfv = fmtdata; 1578 dt_pfargd_t *pfd = pfv->pfv_argv; 1579 1580 /* 1581 * An upper bound on the string length is the length of the original 1582 * format string, plus three times the number of conversions (each 1583 * conversion could add up an additional "ll" and/or pfd_width digit 1584 * in the case of converting %? to %16) plus one for a terminating \0. 1585 */ 1586 size_t formatlen = strlen(pfv->pfv_format) + 3 * pfv->pfv_argc + 1; 1587 char *format = alloca(formatlen); 1588 char *f = format; 1589 int i, j; 1590 1591 for (i = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) { 1592 const dt_pfconv_t *pfc = pfd->pfd_conv; 1593 const char *str; 1594 int width = pfd->pfd_width; 1595 int prec = pfd->pfd_prec; 1596 1597 if (pfd->pfd_preflen != 0) { 1598 for (j = 0; j < pfd->pfd_preflen; j++) 1599 *f++ = pfd->pfd_prefix[j]; 1600 } 1601 1602 if (pfc == NULL) 1603 continue; 1604 1605 *f++ = '%'; 1606 1607 if (pfd->pfd_flags & DT_PFCONV_ALT) 1608 *f++ = '#'; 1609 if (pfd->pfd_flags & DT_PFCONV_ZPAD) 1610 *f++ = '0'; 1611 if (pfd->pfd_flags & DT_PFCONV_LEFT) 1612 *f++ = '-'; 1613 if (pfd->pfd_flags & DT_PFCONV_SPOS) 1614 *f++ = '+'; 1615 if (pfd->pfd_flags & DT_PFCONV_DYNWIDTH) 1616 *f++ = '*'; 1617 if (pfd->pfd_flags & DT_PFCONV_DYNPREC) { 1618 *f++ = '.'; 1619 *f++ = '*'; 1620 } 1621 if (pfd->pfd_flags & DT_PFCONV_GROUP) 1622 *f++ = '\''; 1623 if (pfd->pfd_flags & DT_PFCONV_SPACE) 1624 *f++ = ' '; 1625 if (pfd->pfd_flags & DT_PFCONV_AGG) 1626 *f++ = '@'; 1627 1628 if (width != 0) 1629 f += snprintf(f, sizeof (format), "%d", width); 1630 1631 if (prec != 0) 1632 f += snprintf(f, sizeof (format), ".%d", prec); 1633 1634 /* 1635 * If the output format is %s, then either %s is the underlying 1636 * conversion or the conversion is one of our customized ones, 1637 * e.g. pfprint_addr. In these cases, put the original string 1638 * name of the conversion (pfc_name) into the pickled format 1639 * string rather than the derived conversion (pfd_fmt). 1640 */ 1641 if (strcmp(pfc->pfc_ofmt, "s") == 0) 1642 str = pfc->pfc_name; 1643 else 1644 str = pfd->pfd_fmt; 1645 1646 for (j = 0; str[j] != '\0'; j++) 1647 *f++ = str[j]; 1648 } 1649 1650 *f = '\0'; /* insert nul byte; do not count in return value */ 1651 1652 assert(f < format + formatlen); 1653 (void) strncpy(s, format, len); 1654 1655 return ((size_t)(f - format)); 1656 } 1657 1658 static int 1659 dt_fprinta(const dtrace_aggdata_t *adp, void *arg) 1660 { 1661 const dtrace_aggdesc_t *agg = adp->dtada_desc; 1662 const dtrace_recdesc_t *recp = &agg->dtagd_rec[0]; 1663 uint_t nrecs = agg->dtagd_nrecs; 1664 dt_pfwalk_t *pfw = arg; 1665 dtrace_hdl_t *dtp = pfw->pfw_argv->pfv_dtp; 1666 int id; 1667 1668 if (dt_printf_getint(dtp, recp++, nrecs--, 1669 adp->dtada_data, adp->dtada_size, &id) != 0 || pfw->pfw_aid != id) 1670 return (0); /* no aggregation id or id does not match */ 1671 1672 if (dt_printf_format(dtp, pfw->pfw_fp, pfw->pfw_argv, 1673 recp, nrecs, adp->dtada_data, adp->dtada_size, adp) == -1) 1674 return (pfw->pfw_err = dtp->dt_errno); 1675 1676 /* 1677 * Cast away the const to set the bit indicating that this aggregation 1678 * has been printed. 1679 */ 1680 ((dtrace_aggdesc_t *)agg)->dtagd_flags |= DTRACE_AGD_PRINTED; 1681 1682 return (0); 1683 } 1684 1685 /*ARGSUSED*/ 1686 int 1687 dtrace_fprinta(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata, 1688 const dtrace_probedata_t *data, const dtrace_recdesc_t *recs, 1689 uint_t nrecs, const void *buf, size_t len) 1690 { 1691 const dtrace_recdesc_t *recp = recs; 1692 dt_pfwalk_t pfw; 1693 int id; 1694 1695 if (dt_printf_getint(dtp, recp++, nrecs--, buf, len, &id) == -1) 1696 return (-1); /* errno is set for us */ 1697 1698 pfw.pfw_argv = fmtdata; 1699 pfw.pfw_aid = id; 1700 pfw.pfw_fp = fp; 1701 pfw.pfw_err = 0; 1702 1703 if (dtrace_aggregate_walk_valsorted(dtp, dt_fprinta, &pfw) == -1 || 1704 pfw.pfw_err != 0) 1705 return (-1); /* errno is set for us */ 1706 1707 return ((int)(recp - recs)); 1708 } 1709