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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1994, by Sun Microsytems, Inc. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Includes 30 */ 31 32 #ifndef DEBUG 33 #define NDEBUG 1 34 #endif 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <assert.h> 40 #include <libintl.h> 41 #include <search.h> 42 43 #include "source.h" 44 #include "queue.h" 45 #include "list.h" 46 #include "spec.h" 47 #include "new.h" 48 #include "fcn.h" 49 50 extern caddr_t g_commitfunc; 51 52 53 /* 54 * Typedefs 55 */ 56 57 typedef struct list_probe_args { 58 spec_t *speclist_p; 59 expr_t *exprlist_p; 60 } list_probe_args_t; 61 62 typedef struct list_attrs_args { 63 spec_t *speclist_p; 64 void *attrroot_p; 65 } list_attrs_args_t; 66 67 typedef struct attr_node { 68 char *name; 69 void *valsroot_p; 70 } attr_node_t; 71 72 typedef struct vals_node { 73 char *name; 74 } vals_node_t; 75 76 77 /* 78 * Globals 79 */ 80 81 82 /* 83 * Declarations 84 */ 85 86 static tnfctl_errcode_t listprobe(tnfctl_handle_t *hndl, 87 tnfctl_probe_t *ref_p, void *calldata_p); 88 static tnfctl_errcode_t probescan(tnfctl_handle_t *hndl, 89 tnfctl_probe_t *ref_p, void *calldata_p); 90 static void printattrval(spec_t * spec_p, char *attr, char *value, 91 void *pdata); 92 static void attrscan(spec_t * spec_p, char *attr, char *values, void *pdata); 93 static int attrcompare(const void *node1, const void *node2); 94 static int valscompare(const void *node1, const void *node2); 95 static void printattrs(const void *node, VISIT order, int level); 96 static void printvals(const void *node, VISIT order, int level); 97 98 #if 0 99 static void attrnodedel(attr_node_t * an_p); 100 #endif 101 102 static void valadd(spec_t * spec_p, char *val, void *calldata_p); 103 104 105 /* ---------------------------------------------------------------- */ 106 /* ----------------------- Public Functions ----------------------- */ 107 /* ---------------------------------------------------------------- */ 108 109 extern tnfctl_handle_t *g_hndl; 110 111 /* 112 * list_set() - lists all of the current probes in a target process 113 */ 114 115 void 116 list_set(spec_t * speclist_p, char *setname_p) 117 { 118 set_t *set_p; 119 list_probe_args_t args; 120 tnfctl_errcode_t err; 121 122 set_p = set_find(setname_p); 123 if (!set_p) { 124 semantic_err(gettext("missing or invalid set")); 125 return; 126 } 127 args.speclist_p = speclist_p; 128 args.exprlist_p = set_p->exprlist_p; 129 err = tnfctl_probe_apply(g_hndl, listprobe, &args); 130 if (err) { 131 semantic_err(gettext("listing error : %s"), 132 tnfctl_strerror(err)); 133 } 134 } 135 136 137 /* 138 * list_expr() - lists all of the current probes in an expression list 139 */ 140 141 void 142 list_expr(spec_t * speclist_p, expr_t * expr_p) 143 { 144 list_probe_args_t args; 145 tnfctl_errcode_t err; 146 147 args.speclist_p = speclist_p; 148 args.exprlist_p = expr_p; 149 err = tnfctl_probe_apply(g_hndl, listprobe, &args); 150 if (err) { 151 semantic_err(gettext("listing error : %s"), 152 tnfctl_strerror(err)); 153 } 154 } 155 156 157 /* 158 * list_values() - list all the values for a supplied spec 159 */ 160 161 void 162 list_values(spec_t * speclist_p) 163 { 164 list_attrs_args_t args; 165 tnfctl_errcode_t err; 166 167 /* setup argument block */ 168 args.speclist_p = speclist_p; 169 args.attrroot_p = NULL; 170 171 /* traverse the probes, recording attributes that match */ 172 err = tnfctl_probe_apply(g_hndl, probescan, &args); 173 if (err) { 174 semantic_err(gettext("probe traversal error : %s"), 175 tnfctl_strerror(err)); 176 } 177 178 /* pretty print the results */ 179 twalk(args.attrroot_p, printattrs); 180 181 /* destroy the attribute tree */ 182 while (args.attrroot_p) { 183 attr_node_t **aptr; 184 char *anameptr; 185 186 aptr = (attr_node_t **) args.attrroot_p; 187 188 /* destroy the value tree */ 189 while ((*aptr)->valsroot_p) { 190 vals_node_t **vptr; 191 char *vnameptr; 192 193 vptr = (vals_node_t **) (*aptr)->valsroot_p; 194 vnameptr = (*vptr)->name; 195 #ifdef LEAKCHK 196 (void) fprintf(stderr, "freeing value \"%s\"\n", 197 vnameptr); 198 #endif 199 (void) tdelete((void *) *vptr, &(*aptr)->valsroot_p, 200 valscompare); 201 if (vnameptr) free(vnameptr); 202 } 203 204 anameptr = (*aptr)->name; 205 #ifdef LEAKCHK 206 (void) fprintf(stderr, "freeing attr \"%s\"\n", anameptr); 207 #endif 208 (void) tdelete((void *) *aptr, &args.attrroot_p, attrcompare); 209 if (anameptr) free(anameptr); 210 } 211 212 } /* end list_values */ 213 214 215 /* 216 * list_getattrs() - build an attribute string for this probe. 217 */ 218 219 220 #define BUF_LIMIT 2048 221 222 char * 223 list_getattrs(tnfctl_probe_t *probe_p) 224 { 225 tnfctl_errcode_t err; 226 tnfctl_probe_state_t p_state; 227 char *attrs; 228 char buffer[BUF_LIMIT]; 229 char *buf_p; 230 char *buf_end; 231 int str_len; 232 size_t len; 233 234 err = tnfctl_probe_state_get(g_hndl, probe_p, &p_state); 235 if (err) { 236 attrs = malloc(2); 237 if (attrs) 238 attrs[0] = '\0'; 239 return (attrs); 240 } 241 242 buf_p = buffer; 243 buf_end = buf_p + BUF_LIMIT; 244 str_len = sprintf(buf_p, "enable %s; trace %s; ", 245 (p_state.enabled) ? "on" : "off", 246 (p_state.traced) ? "on" : "off"); 247 buf_p += str_len; 248 if (p_state.obj_name) { 249 str_len = strlen(p_state.obj_name); 250 if (buf_p + str_len < buf_end) { 251 str_len = sprintf(buf_p, "object %s; ", 252 p_state.obj_name); 253 buf_p += str_len; 254 } 255 } 256 str_len = sprintf(buf_p, "funcs"); 257 buf_p += str_len; 258 259 /* REMIND: add limit for string size */ 260 if (p_state.func_names) { 261 int i = 0; 262 char *fcnname; 263 264 while (p_state.func_names[i]) { 265 (void) strcat(buffer, " "); 266 267 fcnname = fcn_findname(p_state.func_names[i]); 268 if (fcnname) { 269 (void) strcat(buffer, "&"); 270 (void) strcat(buffer, fcnname); 271 } else 272 (void) strcat(buffer, p_state.func_names[i]); 273 i++; 274 } 275 } 276 277 (void) strcat(buffer, ";"); 278 279 len = strlen(buffer) + strlen(p_state.attr_string) + 1; 280 attrs = (char *) malloc(len); 281 282 if (attrs) { 283 (void) strcpy(attrs, buffer); 284 (void) strcat(attrs, p_state.attr_string); 285 } 286 287 return (attrs); 288 } 289 290 291 /* ---------------------------------------------------------------- */ 292 /* ----------------------- Private Functions ---------------------- */ 293 /* ---------------------------------------------------------------- */ 294 295 /* 296 * probescan() - function used as a callback, gathers probe attributes and 297 * values 298 */ 299 /*ARGSUSED*/ 300 static tnfctl_errcode_t 301 probescan(tnfctl_handle_t *hndl, tnfctl_probe_t *ref_p, void *calldata_p) 302 { 303 list_attrs_args_t *args_p = (list_attrs_args_t *) calldata_p; 304 spec_t *speclist_p; 305 spec_t *spec_p; 306 char *attrs; 307 308 speclist_p = args_p->speclist_p; 309 spec_p = NULL; 310 311 attrs = list_getattrs(ref_p); 312 313 while (spec_p = (spec_t *) queue_next(&speclist_p->qn, &spec_p->qn)) { 314 spec_attrtrav(spec_p, attrs, attrscan, calldata_p); 315 } 316 317 if (attrs) 318 free(attrs); 319 320 return (TNFCTL_ERR_NONE); 321 } 322 323 324 /* 325 * attrscan() - called on each matching attr/values component 326 */ 327 328 /*ARGSUSED*/ 329 static void 330 attrscan(spec_t * spec_p, 331 char *attr, 332 char *values, 333 void *pdata) 334 { 335 list_attrs_args_t *args_p = (list_attrs_args_t *) pdata; 336 attr_node_t *an_p; 337 attr_node_t **ret_pp; 338 static spec_t *allspec = NULL; 339 340 if (!allspec) 341 allspec = spec(".*", SPEC_REGEXP); 342 343 an_p = new(attr_node_t); 344 345 #ifdef LEAKCHK 346 (void) fprintf(stderr, "creating attr \"%s\"\n", attr); 347 #endif 348 an_p->name = strdup(attr); 349 an_p->valsroot_p = NULL; 350 351 ret_pp = tfind((void *) an_p, &args_p->attrroot_p, attrcompare); 352 353 if (ret_pp) { 354 /* 355 * we already had a node for this attribute; delete ours * 356 * and point at the original instead. 357 */ 358 #ifdef LEAKCHK 359 (void) fprintf(stderr, "attr already there \"%s\"\n", attr); 360 #endif 361 if (an_p->name) 362 free(an_p->name); 363 free(an_p); 364 365 an_p = *ret_pp; 366 } else { 367 (void) tsearch((void *) an_p, &args_p->attrroot_p, attrcompare); 368 } 369 370 spec_valtrav(allspec, values, valadd, (void *) an_p); 371 372 } /* end attrscan */ 373 374 375 /* 376 * valadd() - add vals to an attributes tree 377 */ 378 379 /*ARGSUSED*/ 380 static void 381 valadd(spec_t * spec_p, 382 char *val, 383 void *calldata_p) 384 { 385 attr_node_t *an_p = (attr_node_t *) calldata_p; 386 387 vals_node_t *vn_p; 388 vals_node_t **ret_pp; 389 390 vn_p = new(vals_node_t); 391 #ifdef LEAKCHK 392 (void) fprintf(stderr, "creating value \"%s\"\n", val); 393 #endif 394 vn_p->name = strdup(val); 395 396 ret_pp = tfind((void *) vn_p, &an_p->valsroot_p, valscompare); 397 398 if (ret_pp) { 399 /* we already had a node for this value */ 400 #ifdef LEAKCHK 401 (void) fprintf(stderr, "value already there \"%s\"\n", val); 402 #endif 403 if (vn_p->name) 404 free(vn_p->name); 405 free(vn_p); 406 } else { 407 (void) tsearch((void *) vn_p, &an_p->valsroot_p, valscompare); 408 } 409 410 411 } /* end valadd */ 412 413 414 /* 415 * attrcompare() - compares attribute nodes, alphabetically 416 */ 417 418 static int 419 attrcompare(const void *node1, 420 const void *node2) 421 { 422 return strcmp(((attr_node_t *) node1)->name, 423 ((attr_node_t *) node2)->name); 424 425 } /* end attrcompare */ 426 427 428 /* 429 * valscompare() - compares attribute nodes, alphabetically 430 */ 431 432 static int 433 valscompare(const void *node1, 434 const void *node2) 435 { 436 return strcmp(((vals_node_t *) node1)->name, 437 ((vals_node_t *) node2)->name); 438 439 } /* end valscompare */ 440 441 442 /* 443 * printattrs() - prints attributes from the attr tree 444 */ 445 446 /*ARGSUSED*/ 447 static void 448 printattrs(const void *node, 449 VISIT order, 450 int level) 451 { 452 attr_node_t *an_p = (*(attr_node_t **) node); 453 454 if (order == postorder || order == leaf) { 455 (void) printf("%s =\n", an_p->name); 456 twalk(an_p->valsroot_p, printvals); 457 } 458 } /* end printattrs */ 459 460 461 /* 462 * printvals() - prints values from a value tree 463 */ 464 465 /*ARGSUSED*/ 466 static void 467 printvals(const void *node, 468 VISIT order, 469 int level) 470 { 471 vals_node_t *vn_p = (*(vals_node_t **) node); 472 473 if (order == postorder || order == leaf) 474 (void) printf(" %s\n", vn_p->name); 475 476 } /* end printvals */ 477 478 479 #if 0 480 /* 481 * attrnodedel() - deletes an attr_node_t after the action 482 */ 483 484 static void 485 attrnodedel(attr_node_t * an_p) 486 { 487 if (an_p->name) 488 free(an_p->name); 489 490 /* destroy the value tree */ 491 while (an_p->valsroot_p) { 492 vals_node_t **ptr; 493 494 ptr = (vals_node_t **) an_p->valsroot_p; 495 (void) tdelete((void *) *ptr, &an_p->valsroot_p, valscompare); 496 } 497 498 /* We don't need to free this object, since tdelete() appears to */ 499 /* free(an_p); */ 500 501 } /* end attrnodedel */ 502 #endif 503 504 505 /* 506 * listprobe() - function used as a callback, pretty prints a probe 507 */ 508 /*ARGSUSED*/ 509 static tnfctl_errcode_t 510 listprobe(tnfctl_handle_t *hndl, tnfctl_probe_t *ref_p, void *calldata_p) 511 { 512 static spec_t *default_speclist = NULL; 513 list_probe_args_t *args_p = (list_probe_args_t *) calldata_p; 514 spec_t *speclist_p; 515 spec_t *spec_p; 516 boolean_t sawattr; 517 char *attrs; 518 519 /* build a default speclist if there is not one built already */ 520 if (!default_speclist) { 521 default_speclist = spec_list( 522 spec_list( 523 spec_list( 524 spec_list( 525 spec_list( 526 spec("name", 527 SPEC_EXACT), 528 spec("enable", 529 SPEC_EXACT)), 530 spec("trace", SPEC_EXACT)), 531 spec("file", SPEC_EXACT)), 532 spec("line", SPEC_EXACT)), 533 spec("funcs", SPEC_EXACT)); 534 } 535 attrs = list_getattrs(ref_p); 536 537 if (expr_match(args_p->exprlist_p, attrs)) { 538 speclist_p = args_p->speclist_p; 539 speclist_p = (speclist_p) ? speclist_p : default_speclist; 540 541 spec_p = NULL; 542 while (spec_p = (spec_t *) 543 queue_next(&speclist_p->qn, &spec_p->qn)) { 544 sawattr = B_FALSE; 545 spec_attrtrav(spec_p, attrs, printattrval, &sawattr); 546 if (!sawattr) 547 (void) printf("<no attr> "); 548 } 549 (void) printf("\n"); 550 } 551 if (attrs) 552 free(attrs); 553 554 return (TNFCTL_ERR_NONE); 555 } 556 557 558 /*ARGSUSED*/ 559 static void 560 printattrval(spec_t * spec_p, 561 char *attr, 562 char *value, 563 void *pdata) 564 { 565 boolean_t *bptr = (boolean_t *) pdata; 566 567 *bptr = B_TRUE; 568 569 (void) printf("%s=%s ", attr, (value && *value) ? value : "<no value>"); 570 571 } /* end printattrval */ 572