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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/sysmacros.h> 30 #include <strings.h> 31 #include <stdlib.h> 32 #include <alloca.h> 33 #include <assert.h> 34 #include <ctype.h> 35 #include <errno.h> 36 #include <limits.h> 37 38 #include <dt_printf.h> 39 #include <dt_string.h> 40 #include <dt_impl.h> 41 42 /*ARGSUSED*/ 43 static int 44 pfcheck_addr(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 45 { 46 return (dt_node_is_pointer(dnp) || dt_node_is_integer(dnp)); 47 } 48 49 /*ARGSUSED*/ 50 static int 51 pfcheck_kaddr(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 52 { 53 return (dt_node_is_pointer(dnp) || dt_node_is_integer(dnp) || 54 dt_node_is_symaddr(dnp)); 55 } 56 57 /*ARGSUSED*/ 58 static int 59 pfcheck_uaddr(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 60 { 61 dtrace_hdl_t *dtp = pfv->pfv_dtp; 62 dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); 63 64 if (dt_node_is_usymaddr(dnp)) 65 return (1); 66 67 if (idp == NULL || idp->di_id == 0) 68 return (0); 69 70 return (dt_node_is_pointer(dnp) || dt_node_is_integer(dnp)); 71 } 72 73 /*ARGSUSED*/ 74 static int 75 pfcheck_stack(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 76 { 77 return (dt_node_is_stack(dnp)); 78 } 79 80 /*ARGSUSED*/ 81 static int 82 pfcheck_time(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 83 { 84 return (dt_node_is_integer(dnp) && 85 dt_node_type_size(dnp) == sizeof (uint64_t)); 86 } 87 88 /*ARGSUSED*/ 89 static int 90 pfcheck_str(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 91 { 92 ctf_file_t *ctfp; 93 ctf_encoding_t e; 94 ctf_arinfo_t r; 95 ctf_id_t base; 96 uint_t kind; 97 98 if (dt_node_is_string(dnp)) 99 return (1); 100 101 ctfp = dnp->dn_ctfp; 102 base = ctf_type_resolve(ctfp, dnp->dn_type); 103 kind = ctf_type_kind(ctfp, base); 104 105 return (kind == CTF_K_ARRAY && ctf_array_info(ctfp, base, &r) == 0 && 106 (base = ctf_type_resolve(ctfp, r.ctr_contents)) != CTF_ERR && 107 ctf_type_encoding(ctfp, base, &e) == 0 && IS_CHAR(e)); 108 } 109 110 /*ARGSUSED*/ 111 static int 112 pfcheck_wstr(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 113 { 114 ctf_file_t *ctfp = dnp->dn_ctfp; 115 ctf_id_t base = ctf_type_resolve(ctfp, dnp->dn_type); 116 uint_t kind = ctf_type_kind(ctfp, base); 117 118 ctf_encoding_t e; 119 ctf_arinfo_t r; 120 121 return (kind == CTF_K_ARRAY && ctf_array_info(ctfp, base, &r) == 0 && 122 (base = ctf_type_resolve(ctfp, r.ctr_contents)) != CTF_ERR && 123 ctf_type_kind(ctfp, base) == CTF_K_INTEGER && 124 ctf_type_encoding(ctfp, base, &e) == 0 && e.cte_bits == 32); 125 } 126 127 /*ARGSUSED*/ 128 static int 129 pfcheck_csi(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 130 { 131 return (dt_node_is_integer(dnp) && 132 dt_node_type_size(dnp) <= sizeof (int)); 133 } 134 135 /*ARGSUSED*/ 136 static int 137 pfcheck_fp(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 138 { 139 return (dt_node_is_float(dnp)); 140 } 141 142 /*ARGSUSED*/ 143 static int 144 pfcheck_xint(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 145 { 146 return (dt_node_is_integer(dnp)); 147 } 148 149 /*ARGSUSED*/ 150 static int 151 pfcheck_dint(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 152 { 153 if (dnp->dn_flags & DT_NF_SIGNED) 154 pfd->pfd_flags |= DT_PFCONV_SIGNED; 155 else 156 pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'u'; 157 158 return (dt_node_is_integer(dnp)); 159 } 160 161 /*ARGSUSED*/ 162 static int 163 pfcheck_xshort(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 164 { 165 ctf_file_t *ctfp = dnp->dn_ctfp; 166 ctf_id_t type = ctf_type_resolve(ctfp, dnp->dn_type); 167 char n[DT_TYPE_NAMELEN]; 168 169 return (ctf_type_name(ctfp, type, n, sizeof (n)) != NULL && ( 170 strcmp(n, "short") == 0 || strcmp(n, "signed short") == 0 || 171 strcmp(n, "unsigned short") == 0)); 172 } 173 174 /*ARGSUSED*/ 175 static int 176 pfcheck_xlong(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 177 { 178 ctf_file_t *ctfp = dnp->dn_ctfp; 179 ctf_id_t type = ctf_type_resolve(ctfp, dnp->dn_type); 180 char n[DT_TYPE_NAMELEN]; 181 182 return (ctf_type_name(ctfp, type, n, sizeof (n)) != NULL && ( 183 strcmp(n, "long") == 0 || strcmp(n, "signed long") == 0 || 184 strcmp(n, "unsigned long") == 0)); 185 } 186 187 /*ARGSUSED*/ 188 static int 189 pfcheck_xlonglong(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 190 { 191 ctf_file_t *ctfp = dnp->dn_ctfp; 192 ctf_id_t type = dnp->dn_type; 193 char n[DT_TYPE_NAMELEN]; 194 195 if (ctf_type_name(ctfp, ctf_type_resolve(ctfp, type), n, 196 sizeof (n)) != NULL && (strcmp(n, "long long") == 0 || 197 strcmp(n, "signed long long") == 0 || 198 strcmp(n, "unsigned long long") == 0)) 199 return (1); 200 201 /* 202 * If the type used for %llx or %llX is not an [unsigned] long long, we 203 * also permit it to be a [u]int64_t or any typedef thereof. We know 204 * that these typedefs are guaranteed to work with %ll[xX] in either 205 * compilation environment even though they alias to "long" in LP64. 206 */ 207 while (ctf_type_kind(ctfp, type) == CTF_K_TYPEDEF) { 208 if (ctf_type_name(ctfp, type, n, sizeof (n)) != NULL && 209 (strcmp(n, "int64_t") == 0 || strcmp(n, "uint64_t") == 0)) 210 return (1); 211 212 type = ctf_type_reference(ctfp, type); 213 } 214 215 return (0); 216 } 217 218 /*ARGSUSED*/ 219 static int 220 pfcheck_type(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp) 221 { 222 return (ctf_type_compat(dnp->dn_ctfp, ctf_type_resolve(dnp->dn_ctfp, 223 dnp->dn_type), pfd->pfd_conv->pfc_dctfp, pfd->pfd_conv->pfc_dtype)); 224 } 225 226 /*ARGSUSED*/ 227 static int 228 pfprint_sint(dtrace_hdl_t *dtp, FILE *fp, const char *format, 229 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t unormal) 230 { 231 int64_t normal = (int64_t)unormal; 232 int32_t n = (int32_t)normal; 233 234 switch (size) { 235 case sizeof (int8_t): 236 return (dt_printf(dtp, fp, format, 237 (int32_t)*((int8_t *)addr) / n)); 238 case sizeof (int16_t): 239 return (dt_printf(dtp, fp, format, 240 (int32_t)*((int16_t *)addr) / n)); 241 case sizeof (int32_t): 242 return (dt_printf(dtp, fp, format, 243 *((int32_t *)addr) / n)); 244 case sizeof (int64_t): 245 return (dt_printf(dtp, fp, format, 246 *((int64_t *)addr) / normal)); 247 default: 248 return (dt_set_errno(dtp, EDT_DMISMATCH)); 249 } 250 } 251 252 /*ARGSUSED*/ 253 static int 254 pfprint_uint(dtrace_hdl_t *dtp, FILE *fp, const char *format, 255 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 256 { 257 uint32_t n = (uint32_t)normal; 258 259 switch (size) { 260 case sizeof (uint8_t): 261 return (dt_printf(dtp, fp, format, 262 (uint32_t)*((uint8_t *)addr) / n)); 263 case sizeof (uint16_t): 264 return (dt_printf(dtp, fp, format, 265 (uint32_t)*((uint16_t *)addr) / n)); 266 case sizeof (uint32_t): 267 return (dt_printf(dtp, fp, format, 268 *((uint32_t *)addr) / n)); 269 case sizeof (uint64_t): 270 return (dt_printf(dtp, fp, format, 271 *((uint64_t *)addr) / normal)); 272 default: 273 return (dt_set_errno(dtp, EDT_DMISMATCH)); 274 } 275 } 276 277 static int 278 pfprint_dint(dtrace_hdl_t *dtp, FILE *fp, const char *format, 279 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 280 { 281 if (pfd->pfd_flags & DT_PFCONV_SIGNED) 282 return (pfprint_sint(dtp, fp, format, pfd, addr, size, normal)); 283 else 284 return (pfprint_uint(dtp, fp, format, pfd, addr, size, normal)); 285 } 286 287 /*ARGSUSED*/ 288 static int 289 pfprint_fp(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 double n = (double)normal; 293 long double ldn = (long double)normal; 294 295 switch (size) { 296 case sizeof (float): 297 return (dt_printf(dtp, fp, format, 298 (double)*((float *)addr) / n)); 299 case sizeof (double): 300 return (dt_printf(dtp, fp, format, 301 *((double *)addr) / n)); 302 case sizeof (long double): 303 return (dt_printf(dtp, fp, format, 304 *((long double *)addr) / ldn)); 305 default: 306 return (dt_set_errno(dtp, EDT_DMISMATCH)); 307 } 308 } 309 310 /*ARGSUSED*/ 311 static int 312 pfprint_addr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 313 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 314 { 315 char *s; 316 int n, len = 256; 317 uint64_t val; 318 319 switch (size) { 320 case sizeof (uint32_t): 321 val = *((uint32_t *)addr); 322 break; 323 case sizeof (uint64_t): 324 val = *((uint64_t *)addr); 325 break; 326 default: 327 return (dt_set_errno(dtp, EDT_DMISMATCH)); 328 } 329 330 do { 331 n = len; 332 s = alloca(n); 333 } while ((len = dtrace_addr2str(dtp, val, s, n)) >= n); 334 335 return (dt_printf(dtp, fp, format, s)); 336 } 337 338 /*ARGSUSED*/ 339 static int 340 pfprint_mod(dtrace_hdl_t *dtp, FILE *fp, const char *format, 341 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 342 { 343 return (dt_print_mod(dtp, fp, format, (caddr_t)addr)); 344 } 345 346 /*ARGSUSED*/ 347 static int 348 pfprint_umod(dtrace_hdl_t *dtp, FILE *fp, const char *format, 349 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 350 { 351 return (dt_print_umod(dtp, fp, format, (caddr_t)addr)); 352 } 353 354 /*ARGSUSED*/ 355 static int 356 pfprint_uaddr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 357 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 358 { 359 char *s; 360 int n, len = 256; 361 uint64_t val, pid = 0; 362 363 dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); 364 365 switch (size) { 366 case sizeof (uint32_t): 367 val = (u_longlong_t)*((uint32_t *)addr); 368 break; 369 case sizeof (uint64_t): 370 val = (u_longlong_t)*((uint64_t *)addr); 371 break; 372 case sizeof (uint64_t) * 2: 373 pid = ((uint64_t *)(uintptr_t)addr)[0]; 374 val = ((uint64_t *)(uintptr_t)addr)[1]; 375 break; 376 default: 377 return (dt_set_errno(dtp, EDT_DMISMATCH)); 378 } 379 380 if (pid == 0 && dtp->dt_vector == NULL && idp != NULL) 381 pid = idp->di_id; 382 383 do { 384 n = len; 385 s = alloca(n); 386 } while ((len = dtrace_uaddr2str(dtp, pid, val, s, n)) >= n); 387 388 return (dt_printf(dtp, fp, format, s)); 389 } 390 391 /*ARGSUSED*/ 392 static int 393 pfprint_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format, 394 const dt_pfargd_t *pfd, const void *vaddr, size_t size, uint64_t normal) 395 { 396 int width; 397 dtrace_optval_t saved = dtp->dt_options[DTRACEOPT_STACKINDENT]; 398 const dtrace_recdesc_t *rec = pfd->pfd_rec; 399 caddr_t addr = (caddr_t)vaddr; 400 int err = 0; 401 402 /* 403 * We have stashed the value of the STACKINDENT option, and we will 404 * now override it for the purposes of formatting the stack. If the 405 * field has been specified as left-aligned (i.e. (%-#), we set the 406 * indentation to be the width. This is a slightly odd semantic, but 407 * it's useful functionality -- and it's slightly odd to begin with to 408 * be using a single format specifier to be formatting multiple lines 409 * of text... 410 */ 411 if (pfd->pfd_dynwidth < 0) { 412 assert(pfd->pfd_flags & DT_PFCONV_DYNWIDTH); 413 width = -pfd->pfd_dynwidth; 414 } else if (pfd->pfd_flags & DT_PFCONV_LEFT) { 415 width = pfd->pfd_dynwidth ? pfd->pfd_dynwidth : pfd->pfd_width; 416 } else { 417 width = 0; 418 } 419 420 dtp->dt_options[DTRACEOPT_STACKINDENT] = width; 421 422 switch (rec->dtrd_action) { 423 case DTRACEACT_USTACK: 424 case DTRACEACT_JSTACK: 425 err = dt_print_ustack(dtp, fp, format, addr, rec->dtrd_arg); 426 break; 427 428 case DTRACEACT_STACK: 429 err = dt_print_stack(dtp, fp, format, addr, rec->dtrd_arg, 430 rec->dtrd_size / rec->dtrd_arg); 431 break; 432 433 default: 434 assert(0); 435 } 436 437 dtp->dt_options[DTRACEOPT_STACKINDENT] = saved; 438 439 return (err); 440 } 441 442 /*ARGSUSED*/ 443 static int 444 pfprint_time(dtrace_hdl_t *dtp, FILE *fp, const char *format, 445 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 446 { 447 char src[32], buf[32], *dst = buf; 448 hrtime_t time = *((uint64_t *)addr); 449 time_t sec = (time_t)(time / NANOSEC); 450 int i; 451 452 /* 453 * ctime(3C) returns a string of the form "Dec 3 17:20:00 1973\n\0". 454 * Below, we turn this into the canonical adb/mdb /[yY] format, 455 * "1973 Dec 3 17:20:00". 456 */ 457 (void) ctime_r(&sec, src, sizeof (src)); 458 459 /* 460 * Place the 4-digit year at the head of the string... 461 */ 462 for (i = 20; i < 24; i++) 463 *dst++ = src[i]; 464 465 /* 466 * ...and follow it with the remainder (month, day, hh:mm:ss). 467 */ 468 for (i = 3; i < 19; i++) 469 *dst++ = src[i]; 470 471 *dst = '\0'; 472 return (dt_printf(dtp, fp, format, buf)); 473 } 474 475 /* 476 * This prints the time in RFC 822 standard form. This is useful for emitting 477 * notions of time that are consumed by standard tools (e.g., as part of an 478 * RSS feed). 479 */ 480 /*ARGSUSED*/ 481 static int 482 pfprint_time822(dtrace_hdl_t *dtp, FILE *fp, const char *format, 483 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 484 { 485 hrtime_t time = *((uint64_t *)addr); 486 time_t sec = (time_t)(time / NANOSEC); 487 struct tm tm; 488 char buf[64]; 489 490 (void) localtime_r(&sec, &tm); 491 (void) strftime(buf, sizeof (buf), "%a, %d %b %G %T %Z", &tm); 492 return (dt_printf(dtp, fp, format, buf)); 493 } 494 495 /*ARGSUSED*/ 496 static int 497 pfprint_cstr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 498 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 499 { 500 char *s = alloca(size + 1); 501 502 bcopy(addr, s, size); 503 s[size] = '\0'; 504 return (dt_printf(dtp, fp, format, s)); 505 } 506 507 /*ARGSUSED*/ 508 static int 509 pfprint_wstr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 510 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 511 { 512 wchar_t *ws = alloca(size + sizeof (wchar_t)); 513 514 bcopy(addr, ws, size); 515 ws[size / sizeof (wchar_t)] = L'\0'; 516 return (dt_printf(dtp, fp, format, ws)); 517 } 518 519 /*ARGSUSED*/ 520 static int 521 pfprint_estr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 522 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 523 { 524 char *s; 525 int n; 526 527 if ((s = strchr2esc(addr, size)) == NULL) 528 return (dt_set_errno(dtp, EDT_NOMEM)); 529 530 n = dt_printf(dtp, fp, format, s); 531 free(s); 532 return (n); 533 } 534 535 static int 536 pfprint_echr(dtrace_hdl_t *dtp, FILE *fp, const char *format, 537 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 538 { 539 char c; 540 541 switch (size) { 542 case sizeof (int8_t): 543 c = *(int8_t *)addr; 544 break; 545 case sizeof (int16_t): 546 c = *(int16_t *)addr; 547 break; 548 case sizeof (int32_t): 549 c = *(int32_t *)addr; 550 break; 551 default: 552 return (dt_set_errno(dtp, EDT_DMISMATCH)); 553 } 554 555 return (pfprint_estr(dtp, fp, format, pfd, &c, 1, normal)); 556 } 557 558 /*ARGSUSED*/ 559 static int 560 pfprint_pct(dtrace_hdl_t *dtp, FILE *fp, const char *format, 561 const dt_pfargd_t *pfd, const void *addr, size_t size, uint64_t normal) 562 { 563 return (dt_printf(dtp, fp, "%%")); 564 } 565 566 static const char pfproto_xint[] = "char, short, int, long, or long long"; 567 static const char pfproto_csi[] = "char, short, or int"; 568 static const char pfproto_fp[] = "float, double, or long double"; 569 static const char pfproto_addr[] = "pointer or integer"; 570 static const char pfproto_uaddr[] = 571 "pointer or integer (with -p/-c) or _usymaddr (without -p/-c)"; 572 static const char pfproto_cstr[] = "char [] or string (or use stringof)"; 573 static const char pfproto_wstr[] = "wchar_t []"; 574 575 /* 576 * Printf format conversion dictionary. This table should match the set of 577 * conversions offered by printf(3C), as well as some additional extensions. 578 * The second parameter is an ASCII string which is either an actual type 579 * name we should look up (if pfcheck_type is specified), or just a descriptive 580 * string of the types expected for use in error messages. 581 */ 582 static const dt_pfconv_t _dtrace_conversions[] = { 583 { "a", "s", pfproto_addr, pfcheck_kaddr, pfprint_addr }, 584 { "A", "s", pfproto_uaddr, pfcheck_uaddr, pfprint_uaddr }, 585 { "c", "c", pfproto_csi, pfcheck_csi, pfprint_sint }, 586 { "C", "s", pfproto_csi, pfcheck_csi, pfprint_echr }, 587 { "d", "d", pfproto_xint, pfcheck_dint, pfprint_dint }, 588 { "e", "e", pfproto_fp, pfcheck_fp, pfprint_fp }, 589 { "E", "E", pfproto_fp, pfcheck_fp, pfprint_fp }, 590 { "f", "f", pfproto_fp, pfcheck_fp, pfprint_fp }, 591 { "g", "g", pfproto_fp, pfcheck_fp, pfprint_fp }, 592 { "G", "G", pfproto_fp, pfcheck_fp, pfprint_fp }, 593 { "hd", "d", "short", pfcheck_type, pfprint_sint }, 594 { "hi", "i", "short", pfcheck_type, pfprint_sint }, 595 { "ho", "o", "unsigned short", pfcheck_type, pfprint_uint }, 596 { "hu", "u", "unsigned short", pfcheck_type, pfprint_uint }, 597 { "hx", "x", "short", pfcheck_xshort, pfprint_uint }, 598 { "hX", "X", "short", pfcheck_xshort, pfprint_uint }, 599 { "i", "i", pfproto_xint, pfcheck_dint, pfprint_dint }, 600 { "k", "s", "stack", pfcheck_stack, pfprint_stack }, 601 { "lc", "lc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wint_t */ 602 { "ld", "d", "long", pfcheck_type, pfprint_sint }, 603 { "li", "i", "long", pfcheck_type, pfprint_sint }, 604 { "lo", "o", "unsigned long", pfcheck_type, pfprint_uint }, 605 { "lu", "u", "unsigned long", pfcheck_type, pfprint_uint }, 606 { "ls", "ls", pfproto_wstr, pfcheck_wstr, pfprint_wstr }, 607 { "lx", "x", "long", pfcheck_xlong, pfprint_uint }, 608 { "lX", "X", "long", pfcheck_xlong, pfprint_uint }, 609 { "lld", "d", "long long", pfcheck_type, pfprint_sint }, 610 { "lli", "i", "long long", pfcheck_type, pfprint_sint }, 611 { "llo", "o", "unsigned long long", pfcheck_type, pfprint_uint }, 612 { "llu", "u", "unsigned long long", pfcheck_type, pfprint_uint }, 613 { "llx", "x", "long long", pfcheck_xlonglong, pfprint_uint }, 614 { "llX", "X", "long long", pfcheck_xlonglong, pfprint_uint }, 615 { "Le", "e", "long double", pfcheck_type, pfprint_fp }, 616 { "LE", "E", "long double", pfcheck_type, pfprint_fp }, 617 { "Lf", "f", "long double", pfcheck_type, pfprint_fp }, 618 { "Lg", "g", "long double", pfcheck_type, pfprint_fp }, 619 { "LG", "G", "long double", pfcheck_type, pfprint_fp }, 620 { "o", "o", pfproto_xint, pfcheck_xint, pfprint_uint }, 621 { "p", "x", pfproto_addr, pfcheck_addr, pfprint_uint }, 622 { "s", "s", "char [] or string (or use stringof)", pfcheck_str, pfprint_cstr }, 623 { "S", "s", pfproto_cstr, pfcheck_str, pfprint_estr }, 624 { "T", "s", "int64_t", pfcheck_time, pfprint_time822 }, 625 { "u", "u", pfproto_xint, pfcheck_xint, pfprint_uint }, 626 { "wc", "wc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wchar_t */ 627 { "ws", "ws", pfproto_wstr, pfcheck_wstr, pfprint_wstr }, 628 { "x", "x", pfproto_xint, pfcheck_xint, pfprint_uint }, 629 { "X", "X", pfproto_xint, pfcheck_xint, pfprint_uint }, 630 { "Y", "s", "int64_t", pfcheck_time, pfprint_time }, 631 { "%", "%", "void", pfcheck_type, pfprint_pct }, 632 { NULL, NULL, NULL, NULL, NULL } 633 }; 634 635 int 636 dt_pfdict_create(dtrace_hdl_t *dtp) 637 { 638 uint_t n = _dtrace_strbuckets; 639 const dt_pfconv_t *pfd; 640 dt_pfdict_t *pdi; 641 642 if ((pdi = malloc(sizeof (dt_pfdict_t))) == NULL || 643 (pdi->pdi_buckets = malloc(sizeof (dt_pfconv_t *) * n)) == NULL) { 644 free(pdi); 645 return (dt_set_errno(dtp, EDT_NOMEM)); 646 } 647 648 dtp->dt_pfdict = pdi; 649 bzero(pdi->pdi_buckets, sizeof (dt_pfconv_t *) * n); 650 pdi->pdi_nbuckets = n; 651 652 for (pfd = _dtrace_conversions; pfd->pfc_name != NULL; pfd++) { 653 dtrace_typeinfo_t dtt; 654 dt_pfconv_t *pfc; 655 uint_t h; 656 657 if ((pfc = malloc(sizeof (dt_pfconv_t))) == NULL) { 658 dt_pfdict_destroy(dtp); 659 return (dt_set_errno(dtp, EDT_NOMEM)); 660 } 661 662 bcopy(pfd, pfc, sizeof (dt_pfconv_t)); 663 h = dt_strtab_hash(pfc->pfc_name, NULL) % n; 664 pfc->pfc_next = pdi->pdi_buckets[h]; 665 pdi->pdi_buckets[h] = pfc; 666 667 dtt.dtt_ctfp = NULL; 668 dtt.dtt_type = CTF_ERR; 669 670 /* 671 * The "D" container or its parent must contain a definition of 672 * any type referenced by a printf conversion. If none can be 673 * found, we fail to initialize the printf dictionary. 674 */ 675 if (pfc->pfc_check == &pfcheck_type && dtrace_lookup_by_type( 676 dtp, DTRACE_OBJ_DDEFS, pfc->pfc_tstr, &dtt) != 0) { 677 dt_pfdict_destroy(dtp); 678 return (dt_set_errno(dtp, EDT_NOCONV)); 679 } 680 681 pfc->pfc_dctfp = dtt.dtt_ctfp; 682 pfc->pfc_dtype = dtt.dtt_type; 683 684 /* 685 * The "C" container may contain an alternate definition of an 686 * explicit conversion type. If it does, use it; otherwise 687 * just set pfc_ctype to pfc_dtype so it is always valid. 688 */ 689 if (pfc->pfc_check == &pfcheck_type && dtrace_lookup_by_type( 690 dtp, DTRACE_OBJ_CDEFS, pfc->pfc_tstr, &dtt) == 0) { 691 pfc->pfc_cctfp = dtt.dtt_ctfp; 692 pfc->pfc_ctype = dtt.dtt_type; 693 } else { 694 pfc->pfc_cctfp = pfc->pfc_dctfp; 695 pfc->pfc_ctype = pfc->pfc_dtype; 696 } 697 698 if (pfc->pfc_check == NULL || pfc->pfc_print == NULL || 699 pfc->pfc_ofmt == NULL || pfc->pfc_tstr == NULL) { 700 dt_pfdict_destroy(dtp); 701 return (dt_set_errno(dtp, EDT_BADCONV)); 702 } 703 704 dt_dprintf("loaded printf conversion %%%s\n", pfc->pfc_name); 705 } 706 707 return (0); 708 } 709 710 void 711 dt_pfdict_destroy(dtrace_hdl_t *dtp) 712 { 713 dt_pfdict_t *pdi = dtp->dt_pfdict; 714 dt_pfconv_t *pfc, *nfc; 715 uint_t i; 716 717 if (pdi == NULL) 718 return; 719 720 for (i = 0; i < pdi->pdi_nbuckets; i++) { 721 for (pfc = pdi->pdi_buckets[i]; pfc != NULL; pfc = nfc) { 722 nfc = pfc->pfc_next; 723 free(pfc); 724 } 725 } 726 727 free(pdi->pdi_buckets); 728 free(pdi); 729 dtp->dt_pfdict = NULL; 730 } 731 732 static const dt_pfconv_t * 733 dt_pfdict_lookup(dtrace_hdl_t *dtp, const char *name) 734 { 735 dt_pfdict_t *pdi = dtp->dt_pfdict; 736 uint_t h = dt_strtab_hash(name, NULL) % pdi->pdi_nbuckets; 737 const dt_pfconv_t *pfc; 738 739 for (pfc = pdi->pdi_buckets[h]; pfc != NULL; pfc = pfc->pfc_next) { 740 if (strcmp(pfc->pfc_name, name) == 0) 741 break; 742 } 743 744 return (pfc); 745 } 746 747 static dt_pfargv_t * 748 dt_printf_error(dtrace_hdl_t *dtp, int err) 749 { 750 if (yypcb != NULL) 751 longjmp(yypcb->pcb_jmpbuf, err); 752 753 (void) dt_set_errno(dtp, err); 754 return (NULL); 755 } 756 757 dt_pfargv_t * 758 dt_printf_create(dtrace_hdl_t *dtp, const char *s) 759 { 760 dt_pfargd_t *pfd, *nfd = NULL; 761 dt_pfargv_t *pfv; 762 const char *p, *q; 763 char *format; 764 765 if ((pfv = malloc(sizeof (dt_pfargv_t))) == NULL || 766 (format = strdup(s)) == NULL) { 767 free(pfv); 768 return (dt_printf_error(dtp, EDT_NOMEM)); 769 } 770 771 pfv->pfv_format = format; 772 pfv->pfv_argv = NULL; 773 pfv->pfv_argc = 0; 774 pfv->pfv_flags = 0; 775 pfv->pfv_dtp = dtp; 776 777 for (q = format; (p = strchr(q, '%')) != NULL; q = *p ? p + 1 : p) { 778 uint_t namelen = 0; 779 int digits = 0; 780 int dot = 0; 781 782 char name[8]; 783 char c; 784 int n; 785 786 if ((pfd = malloc(sizeof (dt_pfargd_t))) == NULL) { 787 dt_printf_destroy(pfv); 788 return (dt_printf_error(dtp, EDT_NOMEM)); 789 } 790 791 if (pfv->pfv_argv != NULL) 792 nfd->pfd_next = pfd; 793 else 794 pfv->pfv_argv = pfd; 795 796 bzero(pfd, sizeof (dt_pfargd_t)); 797 pfv->pfv_argc++; 798 nfd = pfd; 799 800 if (p > q) { 801 pfd->pfd_preflen = (size_t)(p - q); 802 pfd->pfd_prefix = q; 803 } 804 805 fmt_switch: 806 switch (c = *++p) { 807 case '0': case '1': case '2': case '3': case '4': 808 case '5': case '6': case '7': case '8': case '9': 809 if (dot == 0 && digits == 0 && c == '0') { 810 pfd->pfd_flags |= DT_PFCONV_ZPAD; 811 pfd->pfd_flags &= ~DT_PFCONV_LEFT; 812 goto fmt_switch; 813 } 814 815 for (n = 0; isdigit(c); c = *++p) 816 n = n * 10 + c - '0'; 817 818 if (dot) 819 pfd->pfd_prec = n; 820 else 821 pfd->pfd_width = n; 822 823 p--; 824 digits++; 825 goto fmt_switch; 826 827 case '#': 828 pfd->pfd_flags |= DT_PFCONV_ALT; 829 goto fmt_switch; 830 831 case '*': 832 n = dot ? DT_PFCONV_DYNPREC : DT_PFCONV_DYNWIDTH; 833 834 if (pfd->pfd_flags & n) { 835 yywarn("format conversion #%u has more than " 836 "one '*' specified for the output %s\n", 837 pfv->pfv_argc, n ? "precision" : "width"); 838 839 dt_printf_destroy(pfv); 840 return (dt_printf_error(dtp, EDT_COMPILER)); 841 } 842 843 pfd->pfd_flags |= n; 844 goto fmt_switch; 845 846 case '+': 847 pfd->pfd_flags |= DT_PFCONV_SPOS; 848 goto fmt_switch; 849 850 case '-': 851 pfd->pfd_flags |= DT_PFCONV_LEFT; 852 pfd->pfd_flags &= ~DT_PFCONV_ZPAD; 853 goto fmt_switch; 854 855 case '.': 856 if (dot++ != 0) { 857 yywarn("format conversion #%u has more than " 858 "one '.' specified\n", pfv->pfv_argc); 859 860 dt_printf_destroy(pfv); 861 return (dt_printf_error(dtp, EDT_COMPILER)); 862 } 863 digits = 0; 864 goto fmt_switch; 865 866 case '?': 867 if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64) 868 pfd->pfd_width = 16; 869 else 870 pfd->pfd_width = 8; 871 goto fmt_switch; 872 873 case '@': 874 pfd->pfd_flags |= DT_PFCONV_AGG; 875 goto fmt_switch; 876 877 case '\'': 878 pfd->pfd_flags |= DT_PFCONV_GROUP; 879 goto fmt_switch; 880 881 case ' ': 882 pfd->pfd_flags |= DT_PFCONV_SPACE; 883 goto fmt_switch; 884 885 case '$': 886 yywarn("format conversion #%u uses unsupported " 887 "positional format (%%n$)\n", pfv->pfv_argc); 888 889 dt_printf_destroy(pfv); 890 return (dt_printf_error(dtp, EDT_COMPILER)); 891 892 case '%': 893 if (p[-1] == '%') 894 goto default_lbl; /* if %% then use "%" conv */ 895 896 yywarn("format conversion #%u cannot be combined " 897 "with other format flags: %%%%\n", pfv->pfv_argc); 898 899 dt_printf_destroy(pfv); 900 return (dt_printf_error(dtp, EDT_COMPILER)); 901 902 case '\0': 903 yywarn("format conversion #%u name expected before " 904 "end of format string\n", pfv->pfv_argc); 905 906 dt_printf_destroy(pfv); 907 return (dt_printf_error(dtp, EDT_COMPILER)); 908 909 case 'h': 910 case 'l': 911 case 'L': 912 case 'w': 913 if (namelen < sizeof (name) - 2) 914 name[namelen++] = c; 915 goto fmt_switch; 916 917 default_lbl: 918 default: 919 name[namelen++] = c; 920 name[namelen] = '\0'; 921 } 922 923 pfd->pfd_conv = dt_pfdict_lookup(dtp, name); 924 925 if (pfd->pfd_conv == NULL) { 926 yywarn("format conversion #%u is undefined: %%%s\n", 927 pfv->pfv_argc, name); 928 dt_printf_destroy(pfv); 929 return (dt_printf_error(dtp, EDT_COMPILER)); 930 } 931 } 932 933 if (*q != '\0' || *format == '\0') { 934 if ((pfd = malloc(sizeof (dt_pfargd_t))) == NULL) { 935 dt_printf_destroy(pfv); 936 return (dt_printf_error(dtp, EDT_NOMEM)); 937 } 938 939 if (pfv->pfv_argv != NULL) 940 nfd->pfd_next = pfd; 941 else 942 pfv->pfv_argv = pfd; 943 944 bzero(pfd, sizeof (dt_pfargd_t)); 945 pfv->pfv_argc++; 946 947 pfd->pfd_prefix = q; 948 pfd->pfd_preflen = strlen(q); 949 } 950 951 return (pfv); 952 } 953 954 void 955 dt_printf_destroy(dt_pfargv_t *pfv) 956 { 957 dt_pfargd_t *pfd, *nfd; 958 959 for (pfd = pfv->pfv_argv; pfd != NULL; pfd = nfd) { 960 nfd = pfd->pfd_next; 961 free(pfd); 962 } 963 964 free(pfv->pfv_format); 9