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 by Delphix. All rights reserved. 25 * Copyright (c) 2013 Joyent, Inc. All rights reserved. 26 */ 27 28 #include <sys/sysmacros.h> 29 #include <strings.h> 30 #include <stdlib.h> 31 #include <alloca.h> 32 #include <assert.h> 33 #include <errno.h> 34 #include <ctype.h> 35 #include <sys/procfs_isa.h> 36 #include <limits.h> 37 38 #include <dt_ident.h> 39 #include <dt_parser.h> 40 #include <dt_provider.h> 41 #include <dt_strtab.h> 42 #include <dt_impl.h> 43 44 /* 45 * Common code for cooking an identifier that uses a typed signature list (we 46 * use this for associative arrays and functions). If the argument list is 47 * of the same length and types, then return the return type. Otherwise 48 * print an appropriate compiler error message and abort the compile. 49 */ 50 static void 51 dt_idcook_sign(dt_node_t *dnp, dt_ident_t *idp, 52 int argc, dt_node_t *args, const char *prefix, const char *suffix) 53 { 54 dt_idsig_t *isp = idp->di_data; 55 int i, compat, mismatch, arglimit, iskey; 56 57 char n1[DT_TYPE_NAMELEN]; 58 char n2[DT_TYPE_NAMELEN]; 59 60 iskey = idp->di_kind == DT_IDENT_ARRAY || idp->di_kind == DT_IDENT_AGG; 61 62 if (isp->dis_varargs >= 0) { 63 mismatch = argc < isp->dis_varargs; 64 arglimit = isp->dis_varargs; 65 } else if (isp->dis_optargs >= 0) { 66 mismatch = (argc < isp->dis_optargs || argc > isp->dis_argc); 67 arglimit = argc; 68 } else { 69 mismatch = argc != isp->dis_argc; 70 arglimit = isp->dis_argc; 71 } 72 73 if (mismatch) { 74 xyerror(D_PROTO_LEN, "%s%s%s prototype mismatch: %d %s%s" 75 "passed, %s%d expected\n", prefix, idp->di_name, suffix, 76 argc, iskey ? "key" : "arg", argc == 1 ? " " : "s ", 77 isp->dis_optargs >= 0 ? "at least " : "", 78 isp->dis_optargs >= 0 ? isp->dis_optargs : arglimit); 79 } 80 81 for (i = 0; i < arglimit; i++, args = args->dn_list) { 82 if (isp->dis_args[i].dn_ctfp != NULL) 83 compat = dt_node_is_argcompat(&isp->dis_args[i], args); 84 else 85 compat = 1; /* "@" matches any type */ 86 87 if (!compat) { 88 xyerror(D_PROTO_ARG, 89 "%s%s%s %s #%d is incompatible with " 90 "prototype:\n\tprototype: %s\n\t%9s: %s\n", 91 prefix, idp->di_name, suffix, 92 iskey ? "key" : "argument", i + 1, 93 dt_node_type_name(&isp->dis_args[i], n1, 94 sizeof (n1)), 95 iskey ? "key" : "argument", 96 dt_node_type_name(args, n2, sizeof (n2))); 97 } 98 } 99 100 dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE); 101 } 102 103 /* 104 * Cook an associative array identifier. If this is the first time we are 105 * cooking this array, create its signature based on the argument list. 106 * Otherwise validate the argument list against the existing signature. 107 */ 108 static void 109 dt_idcook_assc(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args) 110 { 111 if (idp->di_data == NULL) { 112 dt_idsig_t *isp = idp->di_data = malloc(sizeof (dt_idsig_t)); 113 char n[DT_TYPE_NAMELEN]; 114 int i; 115 116 if (isp == NULL) 117 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 118 119 isp->dis_varargs = -1; 120 isp->dis_optargs = -1; 121 isp->dis_argc = argc; 122 isp->dis_args = NULL; 123 isp->dis_auxinfo = 0; 124 125 if (argc != 0 && (isp->dis_args = calloc(argc, 126 sizeof (dt_node_t))) == NULL) { 127 idp->di_data = NULL; 128 free(isp); 129 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 130 } 131 132 /* 133 * If this identifier has not been explicitly declared earlier, 134 * set the identifier's base type to be our special type <DYN>. 135 * If this ident is an aggregation, it will remain as is. If 136 * this ident is an associative array, it will be reassigned 137 * based on the result type of the first assignment statement. 138 */ 139 if (!(idp->di_flags & DT_IDFLG_DECL)) { 140 idp->di_ctfp = DT_DYN_CTFP(yypcb->pcb_hdl); 141 idp->di_type = DT_DYN_TYPE(yypcb->pcb_hdl); 142 } 143 144 for (i = 0; i < argc; i++, args = args->dn_list) { 145 if (dt_node_is_dynamic(args) || dt_node_is_void(args)) { 146 xyerror(D_KEY_TYPE, "%s expression may not be " 147 "used as %s index: key #%d\n", 148 dt_node_type_name(args, n, sizeof (n)), 149 dt_idkind_name(idp->di_kind), i + 1); 150 } 151 152 dt_node_type_propagate(args, &isp->dis_args[i]); 153 isp->dis_args[i].dn_list = &isp->dis_args[i + 1]; 154 } 155 156 if (argc != 0) 157 isp->dis_args[argc - 1].dn_list = NULL; 158 159 dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE); 160 161 } else { 162 dt_idcook_sign(dnp, idp, argc, args, 163 idp->di_kind == DT_IDENT_AGG ? "@" : "", "[ ]"); 164 } 165 } 166 167 /* 168 * Cook a function call. If this is the first time we are cooking this 169 * identifier, create its type signature based on predefined prototype stored 170 * in di_iarg. We then validate the argument list against this signature. 171 */ 172 static void 173 dt_idcook_func(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args) 174 { 175 if (idp->di_data == NULL) { 176 dtrace_hdl_t *dtp = yypcb->pcb_hdl; 177 dtrace_typeinfo_t dtt; 178 dt_idsig_t *isp; 179 char *s, *p1, *p2; 180 int i = 0; 181 182 assert(idp->di_iarg != NULL); 183 s = strdupa(idp->di_iarg); 184 185 if ((p2 = strrchr(s, ')')) != NULL) 186 *p2 = '\0'; /* mark end of parameter list string */ 187 188 if ((p1 = strchr(s, '(')) != NULL) 189 *p1++ = '\0'; /* mark end of return type string */ 190 191 if (p1 == NULL || p2 == NULL) { 192 xyerror(D_UNKNOWN, "internal error: malformed entry " 193 "for built-in function %s\n", idp->di_name); 194 } 195 196 for (p2 = p1; *p2 != '\0'; p2++) { 197 if (!isspace(*p2)) { 198 i++; 199 break; 200 } 201 } 202 203 for (p2 = strchr(p2, ','); p2++ != NULL; i++) 204 p2 = strchr(p2, ','); 205 206 /* 207 * We first allocate a new ident signature structure with the 208 * appropriate number of argument entries, and then look up 209 * the return type and store its CTF data in di_ctfp/type. 210 */ 211 if ((isp = idp->di_data = malloc(sizeof (dt_idsig_t))) == NULL) 212 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 213 214 isp->dis_varargs = -1; 215 isp->dis_optargs = -1; 216 isp->dis_argc = i; 217 isp->dis_args = NULL; 218 isp->dis_auxinfo = 0; 219 220 if (i != 0 && (isp->dis_args = calloc(i, 221 sizeof (dt_node_t))) == NULL) { 222 idp->di_data = NULL; 223 free(isp); 224 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 225 } 226 227 if (dt_type_lookup(s, &dtt) == -1) { 228 xyerror(D_UNKNOWN, "failed to resolve type of %s (%s):" 229 " %s\n", idp->di_name, s, 230 dtrace_errmsg(dtp, dtrace_errno(dtp))); 231 } 232 233 if (idp->di_kind == DT_IDENT_AGGFUNC) { 234 idp->di_ctfp = DT_DYN_CTFP(dtp); 235 idp->di_type = DT_DYN_TYPE(dtp); 236 } else { 237 idp->di_ctfp = dtt.dtt_ctfp; 238 idp->di_type = dtt.dtt_type; 239 } 240 241 /* 242 * For each comma-delimited parameter in the prototype string, 243 * we look up the corresponding type and store its CTF data in 244 * the corresponding location in dis_args[]. We also recognize 245 * the special type string "@" to indicate that the specified 246 * parameter may be a D expression of *any* type (represented 247 * as a dis_args[] element with ctfp = NULL, type == CTF_ERR). 248 * If a varargs "..." is present, we record the argument index 249 * in dis_varargs for the benefit of dt_idcook_sign(), above. 250 * If the type of an argument is enclosed in square brackets 251 * (e.g. "[int]"), the argument is considered optional: the 252 * argument may be absent, but if it is present, it must be of 253 * the specified type. Note that varargs may not optional, 254 * optional arguments may not follow varargs, and non-optional 255 * arguments may not follow optional arguments. 256 */ 257 for (i = 0; i < isp->dis_argc; i++, p1 = p2) { 258 while (isspace(*p1)) 259 p1++; /* skip leading whitespace */ 260 261 if ((p2 = strchr(p1, ',')) == NULL) 262 p2 = p1 + strlen(p1); 263 else 264 *p2++ = '\0'; 265 266 if (strcmp(p1, "@") == 0 || strcmp(p1, "...") == 0) { 267 isp->dis_args[i].dn_ctfp = NULL; 268 isp->dis_args[i].dn_type = CTF_ERR; 269 if (*p1 == '.') 270 isp->dis_varargs = i; 271 continue; 272 } 273 274 if (*p1 == '[' && p1[strlen(p1) - 1] == ']') { 275 if (isp->dis_varargs != -1) { 276 xyerror(D_UNKNOWN, "optional arg#%d " 277 "may not follow variable arg#%d\n", 278 i + 1, isp->dis_varargs + 1); 279 } 280 281 if (isp->dis_optargs == -1) 282 isp->dis_optargs = i; 283 284 p1[strlen(p1) - 1] = '\0'; 285 p1++; 286 } else if (isp->dis_optargs != -1) { 287 xyerror(D_UNKNOWN, "required arg#%d may not " 288 "follow optional arg#%d\n", i + 1, 289 isp->dis_optargs + 1); 290 } 291 292 if (dt_type_lookup(p1, &dtt) == -1) { 293 xyerror(D_UNKNOWN, "failed to resolve type of " 294 "%s arg#%d (%s): %s\n", idp->di_name, i + 1, 295 p1, dtrace_errmsg(dtp, dtrace_errno(dtp))); 296 } 297 298 dt_node_type_assign(&isp->dis_args[i], 299 dtt.dtt_ctfp, dtt.dtt_type, B_FALSE); 300 } 301 } 302 303 dt_idcook_sign(dnp, idp, argc, args, "", "( )"); 304 } 305 306 /* 307 * Cook a reference to the dynamically typed args[] array. We verify that the 308 * reference is using a single integer constant, and then construct a new ident 309 * representing the appropriate type or translation specifically for this node. 310 */ 311 static void 312 dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap) 313 { 314 dtrace_hdl_t *dtp = yypcb->pcb_hdl; 315 dt_probe_t *prp = yypcb->pcb_probe; 316 317 dt_node_t tag, *nnp, *xnp; 318 dt_xlator_t *dxp; 319 dt_ident_t *xidp; 320 321 char n1[DT_TYPE_NAMELEN]; 322 char n2[DT_TYPE_NAMELEN]; 323 324 if (argc != 1) { 325 xyerror(D_PROTO_LEN, "%s[ ] prototype mismatch: %d arg%s" 326 "passed, 1 expected\n", idp->di_name, argc, 327 argc == 1 ? " " : "s "); 328 } 329 330 if (ap->dn_kind != DT_NODE_INT) { 331 xyerror(D_PROTO_ARG, "%s[ ] argument #1 is incompatible with " 332 "prototype:\n\tprototype: %s\n\t argument: %s\n", 333 idp->di_name, "integer constant", 334 dt_type_name(ap->dn_ctfp, ap->dn_type, n1, sizeof (n1))); 335 } 336 337 if (yypcb->pcb_pdesc == NULL) { 338 xyerror(D_ARGS_NONE, "%s[ ] may not be referenced outside " 339 "of a probe clause\n", idp->di_name); 340 } 341 342 if (prp == NULL) { 343 xyerror(D_ARGS_MULTI, 344 "%s[ ] may not be referenced because probe description %s " 345 "matches an unstable set of probes\n", idp->di_name, 346 dtrace_desc2str(yypcb->pcb_pdesc, n1, sizeof (n1))); 347 } 348 349 if (ap->dn_value >= prp->pr_argc) { 350 xyerror(D_ARGS_IDX, "index %lld is out of range for %s %s[ ]\n", 351 (longlong_t)ap->dn_value, dtrace_desc2str(yypcb->pcb_pdesc, 352 n1, sizeof (n1)), idp->di_name); 353 } 354 355 /* 356 * Look up the native and translated argument types for the probe. 357 * If no translation is needed, these will be the same underlying node. 358 * If translation is needed, look up the appropriate translator. Once 359 * we have the appropriate node, create a new dt_ident_t for this node, 360 * assign it the appropriate attributes, and set the type of 'dnp'. 361 */ 362 xnp = prp->pr_xargv[ap->dn_value]; 363 nnp = prp->pr_nargv[prp->pr_mapping[ap->dn_value]]; 364 365 if (xnp->dn_type == CTF_ERR) { 366 xyerror(D_ARGS_TYPE, "failed to resolve translated type for " 367 "%s[%lld]\n", idp->di_name, (longlong_t)ap->dn_value); 368 } 369 370 if (nnp->dn_type == CTF_ERR) { 371 xyerror(D_ARGS_TYPE, "failed to resolve native type for " 372 "%s[%lld]\n", idp->di_name, (longlong_t)ap->dn_value); 373 } 374 375 if (dtp->dt_xlatemode == DT_XL_STATIC && ( 376 nnp == xnp || dt_node_is_argcompat(nnp, xnp))) { 377 dnp->dn_ident = dt_ident_create(idp->di_name, idp->di_kind, 378 idp->di_flags | DT_IDFLG_ORPHAN, idp->di_id, idp->di_attr, 379 idp->di_vers, idp->di_ops, idp->di_iarg, idp->di_gen); 380 381 if (dnp->dn_ident == NULL) 382 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 383 384 dt_node_type_assign(dnp, 385 prp->pr_argv[ap->dn_value].dtt_ctfp, 386 prp->pr_argv[ap->dn_value].dtt_type, 387 prp->pr_argv[ap->dn_value].dtt_flags & DTT_FL_USER ? 388 B_TRUE : B_FALSE); 389 390 } else if ((dxp = dt_xlator_lookup(dtp, 391 nnp, xnp, DT_XLATE_FUZZY)) != NULL || ( 392 dxp = dt_xlator_lookup(dtp, dt_probe_tag(prp, ap->dn_value, &tag), 393 xnp, DT_XLATE_EXACT | DT_XLATE_EXTERN)) != NULL) { 394 395 xidp = dt_xlator_ident(dxp, xnp->dn_ctfp, xnp->dn_type); 396 397 dnp->dn_ident = dt_ident_create(idp->di_name, xidp->di_kind, 398 xidp->di_flags | DT_IDFLG_ORPHAN, idp->di_id, idp->di_attr, 399 idp->di_vers, idp->di_ops, idp->di_iarg, idp->di_gen); 400 401 if (dnp->dn_ident == NULL) 402 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 403 404 if (dt_xlator_dynamic(dxp)) 405 dxp->dx_arg = (int)ap->dn_value; 406 407 /* 408 * Propagate relevant members from the translator's internal 409 * dt_ident_t. This code must be kept in sync with the state 410 * that is initialized for idents in dt_xlator_create(). 411 */ 412 dnp->dn_ident->di_data = xidp->di_data; 413 dnp->dn_ident->di_ctfp = xidp->di_ctfp; 414 dnp->dn_ident->di_type = xidp->di_type; 415 416 dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), 417 B_FALSE); 418 419 } else { 420 xyerror(D_ARGS_XLATOR, "translator for %s[%lld] from %s to %s " 421 "is not defined\n", idp->di_name, (longlong_t)ap->dn_value, 422 dt_node_type_name(nnp, n1, sizeof (n1)), 423 dt_node_type_name(xnp, n2, sizeof (n2))); 424 } 425 426 assert(dnp->dn_ident->di_flags & DT_IDFLG_ORPHAN); 427 assert(dnp->dn_ident->di_id == idp->di_id); 428 } 429 430 static void 431 dt_idcook_regs(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap) 432 { 433 dtrace_typeinfo_t dtt; 434 dtrace_hdl_t *dtp = yypcb->pcb_hdl; 435 char n[DT_TYPE_NAMELEN]; 436 437 if (argc != 1) { 438 xyerror(D_PROTO_LEN, "%s[ ] prototype mismatch: %d arg%s" 439 "passed, 1 expected\n", idp->di_name, 440 argc, argc == 1 ? " " : "s "); 441 } 442 443 if (ap->dn_kind != DT_NODE_INT) { 444 xyerror(D_PROTO_ARG, "%s[ ] argument #1 is incompatible with " 445 "prototype:\n\tprototype: %s\n\t argument: %s\n", 446 idp->di_name, "integer constant", 447 dt_type_name(ap->dn_ctfp, ap->dn_type, n, sizeof (n))); 448 } 449 450 if ((ap->dn_flags & DT_NF_SIGNED) && (int64_t)ap->dn_value < 0) { 451 xyerror(D_REGS_IDX, "index %lld is out of range for array %s\n", 452 (longlong_t)ap->dn_value, idp->di_name); 453 } 454 455 if (dt_type_lookup("uint64_t", &dtt) == -1) { 456 xyerror(D_UNKNOWN, "failed to resolve type of %s: %s\n", 457 idp->di_name, dtrace_errmsg(dtp, dtrace_errno(dtp))); 458 } 459 460 idp->di_ctfp = dtt.dtt_ctfp; 461 idp->di_type = dtt.dtt_type; 462 463 dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE); 464 } 465 466 /*ARGSUSED*/ 467 static void 468 dt_idcook_type(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args) 469 { 470 if (idp->di_type == CTF_ERR) { 471 dtrace_hdl_t *dtp = yypcb->pcb_hdl; 472 dtrace_typeinfo_t dtt; 473 474 if (dt_type_lookup(idp->di_iarg, &dtt) == -1) { 475 xyerror(D_UNKNOWN, 476 "failed to resolve type %s for identifier %s: %s\n", 477 (const char *)idp->di_iarg, idp->di_name, 478 dtrace_errmsg(dtp, dtrace_errno(dtp))); 479 } 480 481 idp->di_ctfp = dtt.dtt_ctfp; 482 idp->di_type = dtt.dtt_type; 483 } 484 485 dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE); 486 } 487 488 /*ARGSUSED*/ 489 static void 490 dt_idcook_thaw(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args) 491 { 492 if (idp->di_ctfp != NULL && idp->di_type != CTF_ERR) 493 dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE); 494 } 495 496 static void 497 dt_idcook_inline(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args) 498 { 499 if (idp->di_kind == DT_IDENT_ARRAY) 500 dt_idcook_assc(dnp, idp, argc, args); 501 else 502 dt_idcook_thaw(dnp, idp, argc, args); 503 } 504 505 static void 506 dt_iddtor_sign(dt_ident_t *idp) 507 { 508 if (idp->di_data != NULL) 509 free(((dt_idsig_t *)idp->di_data)->dis_args); 510 free(idp->di_data); 511 } 512 513 static void 514 dt_iddtor_free(dt_ident_t *idp) 515 { 516 free(idp->di_data); 517 } 518 519 static void 520 dt_iddtor_inline(dt_ident_t *idp) 521 { 522 dt_idnode_t *inp = idp->di_iarg; 523 524 if (inp != NULL) { 525 dt_node_link_free(&inp->din_list); 526 527 if (inp->din_hash != NULL) 528 dt_idhash_destroy(inp->din_hash); 529 530 free(inp->din_argv); 531 free(inp); 532 } 533 534 if (idp->di_kind == DT_IDENT_ARRAY) 535 dt_iddtor_sign(idp); 536 else 537 dt_iddtor_free(idp); 538 } 539 540 /*ARGSUSED*/ 541 static void 542 dt_iddtor_none(dt_ident_t *idp) 543 { 544 /* do nothing */ 545 } 546 547 static void 548 dt_iddtor_probe(dt_ident_t *idp) 549 { 550 if (idp->di_data != NULL) 551 dt_probe_destroy(idp->di_data); 552 } 553 554 static size_t 555 dt_idsize_type(dt_ident_t *idp) 556 { 557 return (ctf_type_size(idp->di_ctfp, idp->di_type)); 558 } 559 560 /*ARGSUSED*/ 561 static size_t 562 dt_idsize_none(dt_ident_t *idp) 563 { 564 return (0); 565 } 566 567 const dt_idops_t dt_idops_assc = { 568 dt_idcook_assc, 569 dt_iddtor_sign, 570 dt_idsize_none, 571 }; 572 573 const dt_idops_t dt_idops_func = { 574 dt_idcook_func, 575 dt_iddtor_sign, 576 dt_idsize_none, 577 }; 578 579 const dt_idops_t dt_idops_args = { 580 dt_idcook_args, 581 dt_iddtor_none, 582 dt_idsize_none, 583 }; 584 585 const dt_idops_t dt_idops_regs = { 586 dt_idcook_regs, 587 dt_iddtor_free, 588 dt_idsize_none, 589 }; 590 591 const dt_idops_t dt_idops_type = { 592 dt_idcook_type, 593 dt_iddtor_free, 594 dt_idsize_type, 595 }; 596 597 const dt_idops_t dt_idops_thaw = { 598 dt_idcook_thaw, 599 dt_iddtor_free, 600 dt_idsize_type, 601 }; 602 603 const dt_idops_t dt_idops_inline = { 604 dt_idcook_inline, 605 dt_iddtor_inline, 606 dt_idsize_type, 607 }; 608 609 const dt_idops_t dt_idops_probe = { 610 dt_idcook_thaw, 611 dt_iddtor_probe, 612 dt_idsize_none, 613 }; 614 615 static void 616 dt_idhash_populate(dt_idhash_t *dhp) 617 { 618 const dt_ident_t *idp = dhp->dh_tmpl; 619 620 dhp->dh_tmpl = NULL; /* clear dh_tmpl first to avoid recursion */ 621 dt_dprintf("populating %s idhash from %p\n", dhp->dh_name, (void *)idp); 622 623 for (; idp->di_name != NULL; idp++) { 624 if (dt_idhash_insert(dhp, idp->di_name, 625 idp->di_kind, idp->di_flags, idp->di_id, idp->di_attr, 626 idp->di_vers, idp->di_ops ? idp->di_ops : &dt_idops_thaw, 627 idp->di_iarg, 0) == NULL) 628 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 629 } 630 } 631 632 dt_idhash_t * 633 dt_idhash_create(const char *name, const dt_ident_t *tmpl, 634 uint_t min, uint_t max) 635 { 636 dt_idhash_t *dhp; 637 size_t size; 638 639 assert(min <= max); 640 641 size = sizeof (dt_idhash_t) + 642 sizeof (dt_ident_t *) * (_dtrace_strbuckets - 1); 643 644 if ((dhp = malloc(size)) == NULL) 645 return (NULL); 646 647 bzero(dhp, size); 648 dhp->dh_name = name; 649 dhp->dh_tmpl = tmpl; 650 dhp->dh_nextid = min; 651 dhp->dh_minid = min; 652 dhp->dh_maxid = max; 653 dhp->dh_hashsz = _dtrace_strbuckets; 654 655 return (dhp); 656 } 657 658 /* 659 * Destroy an entire identifier hash. This must be done using two passes with 660 * an inlined version of dt_ident_destroy() to avoid referencing freed memory. 661 * In the first pass di_dtor() is called for all identifiers; then the second 662 * pass frees the actual dt_ident_t's. These must be done separately because 663 * a di_dtor() may operate on data structures which contain references to other 664 * identifiers inside of this hash itself (e.g. a global inline definition 665 * which contains a parse tree that refers to another global variable). 666 */ 667 void 668 dt_idhash_destroy(dt_idhash_t *dhp) 669 { 670 dt_ident_t *idp, *next; 671 ulong_t i; 672 673 for (i = 0; i < dhp->dh_hashsz; i++) { 674 for (idp = dhp->dh_hash[i]; idp != NULL; idp = next) { 675 next = idp->di_next; 676 idp->di_ops->di_dtor(idp); 677 } 678 } 679 680 for (i = 0; i < dhp->dh_hashsz; i++) { 681 for (idp = dhp->dh_hash[i]; idp != NULL; idp = next) { 682 next = idp->di_next; 683 free(idp->di_name); 684 free(idp); 685 } 686 } 687 688 free(dhp); 689 } 690 691 void 692 dt_idhash_update(dt_idhash_t *dhp) 693 { 694 uint_t nextid = dhp->dh_minid; 695 dt_ident_t *idp; 696 ulong_t i; 697 698 for (i = 0; i < dhp->dh_hashsz; i++) { 699 for (idp = dhp->dh_hash[i]; idp != NULL; idp = idp->di_next) { 700 /* 701 * Right now we're hard coding which types need to be 702 * reset, but ideally this would be done dynamically. 703 */ 704 if (idp->di_kind == DT_IDENT_ARRAY || 705 idp->di_kind == DT_IDENT_SCALAR || 706 idp->di_kind == DT_IDENT_AGG) 707 nextid = MAX(nextid, idp->di_id + 1); 708 } 709 } 710 711 dhp->dh_nextid = nextid; 712 } 713 714 dt_ident_t * 715 dt_idhash_lookup(dt_idhash_t *dhp, const char *name) 716 { 717 size_t len; 718 ulong_t h = dt_strtab_hash(name, &len) % dhp->dh_hashsz; 719 dt_ident_t *idp; 720 721 if (dhp->dh_tmpl != NULL) 722 dt_idhash_populate(dhp); /* fill hash w/ initial population */ 723 724 for (idp = dhp->dh_hash[h]; idp != NULL; idp = idp->di_next) { 725 if (strcmp(idp->di_name, name) == 0) 726 return (idp); 727 } 728 729 return (NULL); 730 } 731 732 int 733 dt_idhash_nextid(dt_idhash_t *dhp, uint_t *p) 734 { 735 if (dhp->dh_nextid >= dhp->dh_maxid) 736 return (-1); /* no more id's are free to allocate */ 737 738 *p = dhp->dh_nextid++; 739 return (0); 740 } 741 742 ulong_t 743 dt_idhash_size(const dt_idhash_t *dhp) 744 { 745 return (dhp->dh_nelems); 746 } 747 748 const char * 749 dt_idhash_name(const dt_idhash_t *dhp) 750 { 751 return (dhp->dh_name); 752 } 753 754 dt_ident_t * 755 dt_idhash_insert(dt_idhash_t *dhp, const char *name, ushort_t kind, 756 ushort_t flags, uint_t id, dtrace_attribute_t attr, uint_t vers, 757 const dt_idops_t *ops, void *iarg, ulong_t gen) 758 { 759 dt_ident_t *idp; 760 ulong_t h; 761 762 if (dhp->dh_tmpl != NULL) 763 dt_idhash_populate(dhp); /* fill hash w/ initial population */ 764 765 idp = dt_ident_create(name, kind, flags, id, 766 attr, vers, ops, iarg, gen); 767 768 if (idp == NULL) 769 return (NULL); 770 771 h = dt_strtab_hash(name, NULL) % dhp->dh_hashsz; 772 idp->di_next = dhp->dh_hash[h]; 773 774 dhp->dh_hash[h] = idp; 775 dhp->dh_nelems++; 776 777 if (dhp->dh_defer != NULL) 778 dhp->dh_defer(dhp, idp); 779 780 return (idp); 781 } 782 783 void 784 dt_idhash_xinsert(dt_idhash_t *dhp, dt_ident_t *idp) 785 { 786 ulong_t h; 787 788 if (dhp->dh_tmpl != NULL) 789 dt_idhash_populate(dhp); /* fill hash w/ initial population */ 790 791 h = dt_strtab_hash(idp->di_name, NULL) % dhp->dh_hashsz; 792 idp->di_next = dhp->dh_hash[h]; 793 idp->di_flags &= ~DT_IDFLG_ORPHAN; 794 795 dhp->dh_hash[h] = idp; 796 dhp->dh_nelems++; 797 798 if (dhp->dh_defer != NULL) 799 dhp->dh_defer(dhp, idp); 800 } 801 802 void 803 dt_idhash_delete(dt_idhash_t *dhp, dt_ident_t *key) 804 { 805 size_t len; 806 ulong_t h = dt_strtab_hash(key->di_name, &len) % dhp->dh_hashsz; 807 dt_ident_t **pp = &dhp->dh_hash[h]; 808 dt_ident_t *idp; 809 810 for (idp = dhp->dh_hash[h]; idp != NULL; idp = idp->di_next) { 811 if (idp == key) 812 break; 813 else 814 pp = &idp->di_next; 815 } 816 817 assert(idp == key); 818 *pp = idp->di_next; 819 820 assert(dhp->dh_nelems != 0); 821 dhp->dh_nelems--; 822 823 if (!(idp->di_flags & DT_IDFLG_ORPHAN)) 824 dt_ident_destroy(idp); 825 } 826 827 static int 828 dt_idhash_comp(const void *lp, const void *rp) 829 { 830 const dt_ident_t *lhs = *((const dt_ident_t **)lp); 831 const dt_ident_t *rhs = *((const dt_ident_t **)rp); 832 833 if (lhs->di_id != rhs->di_id) 834 return ((int)(lhs->di_id - rhs->di_id)); 835 else 836 return (strcmp(lhs->di_name, rhs->di_name)); 837 } 838 839 int 840 dt_idhash_iter(dt_idhash_t *dhp, dt_idhash_f *func, void *data) 841 { 842 dt_ident_t **ids; 843 dt_ident_t *idp; 844 ulong_t i, j, n; 845 int rv; 846 847 if (dhp->dh_tmpl != NULL) 848 dt_idhash_populate(dhp); /* fill hash w/ initial population */ 849 850 n = dhp->dh_nelems; 851 ids = alloca(sizeof (dt_ident_t *) * n); 852 853 for (i = 0, j = 0; i < dhp->dh_hashsz; i++) { 854 for (idp = dhp->dh_hash[i]; idp != NULL; idp = idp->di_next) 855 ids[j++] = idp; 856 } 857 858 qsort(ids, dhp->dh_nelems, sizeof (dt_ident_t *), dt_idhash_comp); 859 860 for (i = 0; i < n; i++) { 861 if ((rv = func(dhp, ids[i], data)) != 0) 862 return (rv); 863 } 864 865 return (0); 866 } 867 868 dt_ident_t * 869 dt_idstack_lookup(dt_idstack_t *sp, const char *name) 870 { 871 dt_idhash_t *dhp; 872 dt_ident_t *idp; 873 874 for (dhp = dt_list_prev(&sp->dids_list); 875 dhp != NULL; dhp = dt_list_prev(dhp)) { 876 if ((idp = dt_idhash_lookup(dhp, name)) != NULL) 877 return (idp); 878 } 879 880 return (NULL); 881 } 882 883 void 884 dt_idstack_push(dt_idstack_t *sp, dt_idhash_t *dhp) 885 { 886 dt_list_append(&sp->dids_list, dhp); 887 } 888 889 void 890 dt_idstack_pop(dt_idstack_t *sp, dt_idhash_t *dhp) 891 { 892 assert(dt_list_prev(&sp->dids_list) == dhp); 893 dt_list_delete(&sp->dids_list, dhp); 894 } 895 896 dt_ident_t * 897 dt_ident_create(const char *name, ushort_t kind, ushort_t flags, uint_t id, 898 dtrace_attribute_t attr, uint_t vers, 899 const dt_idops_t *ops, void *iarg, ulong_t gen) 900 { 901 dt_ident_t *idp; 902 char *s = NULL; 903 904 if ((name != NULL && (s = strdup(name)) == NULL) || 905 (idp = malloc(sizeof (dt_ident_t))) == NULL) { 906 free(s); 907 return (NULL); 908 } 909 910 idp->di_name = s; 911 idp->di_kind = kind; 912 idp->di_flags = flags; 913 idp->di_id = id; 914 idp->di_attr = attr; 915 idp->di_vers = vers; 916 idp->di_ops = ops; 917 idp->di_iarg = iarg; 918 idp->di_data = NULL; 919 idp->di_ctfp = NULL; 920 idp->di_type = CTF_ERR; 921 idp->di_next = NULL; 922 idp->di_gen = gen; 923 idp->di_lineno = yylineno; 924 925 return (idp); 926 } 927 928 /* 929 * Destroy an individual identifier. This code must be kept in sync with the 930 * dt_idhash_destroy() function below, which separates out the call to di_dtor. 931 */ 932 void 933 dt_ident_destroy(dt_ident_t *idp) 934 { 935 idp->di_ops->di_dtor(idp); 936 free(idp->di_name); 937 free(idp); 938 } 939 940 void 941 dt_ident_morph(dt_ident_t *idp, ushort_t kind, 942 const dt_idops_t *ops, void *iarg) 943 { 944 idp->di_ops->di_dtor(idp); 945 idp->di_kind = kind; 946 idp->di_ops = ops; 947 idp->di_iarg = iarg; 948 idp->di_data = NULL; 949 } 950 951 dtrace_attribute_t 952 dt_ident_cook(dt_node_t *dnp, dt_ident_t *idp, dt_node_t **pargp) 953 { 954 dtrace_attribute_t attr; 955 dt_node_t *args, *argp; 956 int argc = 0; 957 958 attr = dt_node_list_cook(pargp, DT_IDFLG_REF); 959 args = pargp ? *pargp : NULL; 960 961 for (argp = args; argp != NULL; argp = argp->dn_list) 962 argc++; 963 964 idp->di_ops->di_cook(dnp, idp, argc, args); 965 966 if (idp->di_flags & DT_IDFLG_USER) 967 dnp->dn_flags |= DT_NF_USERLAND; 968 969 return (dt_attr_min(attr, idp->di_attr)); 970 } 971 972 void 973 dt_ident_type_assign(dt_ident_t *idp, ctf_file_t *fp, ctf_id_t type) 974 { 975 idp->di_ctfp = fp; 976 idp->di_type = type; 977 } 978 979 dt_ident_t * 980 dt_ident_resolve(dt_ident_t *idp) 981 { 982 while (idp->di_flags & DT_IDFLG_INLINE) { 983 const dt_node_t *dnp = ((dt_idnode_t *)idp->di_iarg)->din_root; 984 985 if (dnp == NULL) 986 break; /* can't resolve any further yet */ 987 988 switch (dnp->dn_kind) { 989 case DT_NODE_VAR: 990 case DT_NODE_SYM: 991 case DT_NODE_FUNC: 992 case DT_NODE_AGG: 993 case DT_NODE_INLINE: 994 case DT_NODE_PROBE: 995 idp = dnp->dn_ident; 996 continue; 997 } 998 999 if (dt_node_is_dynamic(dnp)) 1000 idp = dnp->dn_ident; 1001 else 1002 break; 1003 } 1004 1005 return (idp); 1006 } 1007 1008 size_t 1009 dt_ident_size(dt_ident_t *idp) 1010 { 1011 idp = dt_ident_resolve(idp); 1012 return (idp->di_ops->di_size(idp)); 1013 } 1014 1015 int 1016 dt_ident_unref(const dt_ident_t *idp) 1017 { 1018 return (idp->di_gen == yypcb->pcb_hdl->dt_gen && 1019 (idp->di_flags & (DT_IDFLG_REF|DT_IDFLG_MOD|DT_IDFLG_DECL)) == 0); 1020 } 1021 1022 const char * 1023 dt_idkind_name(uint_t kind) 1024 { 1025 switch (kind) { 1026 case DT_IDENT_ARRAY: return ("associative array"); 1027 case DT_IDENT_SCALAR: return ("scalar"); 1028 case DT_IDENT_PTR: return ("pointer"); 1029 case DT_IDENT_FUNC: return ("function"); 1030 case DT_IDENT_AGG: return ("aggregation"); 1031 case DT_IDENT_AGGFUNC: return ("aggregating function"); 1032 case DT_IDENT_ACTFUNC: return ("tracing function"); 1033 case DT_IDENT_XLSOU: return ("translated data"); 1034 case DT_IDENT_XLPTR: return ("pointer to translated data"); 1035 case DT_IDENT_SYMBOL: return ("external symbol reference"); 1036 case DT_IDENT_ENUM: return ("enumerator"); 1037 case DT_IDENT_PRAGAT: return ("#pragma attributes"); 1038 case DT_IDENT_PRAGBN: return ("#pragma binding"); 1039 case DT_IDENT_PROBE: return ("probe definition"); 1040 default: return ("<?>"); 1041 } 1042 }