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