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