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