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