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