Print this page
16446 dtrace consumers should not be isaexec'd
Change-Id: Ibf80c7283c421cba98e80dce272c6dd51d24bb87
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/latencytop/common/table.c
+++ new/usr/src/cmd/latencytop/table.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2008-2009, Intel Corporation.
23 23 * All Rights Reserved.
24 24 */
25 25
26 26 #include <stdlib.h>
27 27 #include <string.h>
28 28 #include <memory.h>
29 29 #include <stdio.h>
30 30 #include <ctype.h>
31 31
32 32 #include "latencytop.h"
33 33
34 34 /*
35 35 * Structure that holds detail of a cause.
36 36 */
37 37 typedef struct {
38 38 int lt_c_cause_id;
39 39 int lt_c_flags;
40 40 char *lt_c_name;
41 41 } lt_cause_t;
42 42
43 43 /*
44 44 * Structure that represents a matched cause.
45 45 */
46 46 typedef struct {
47 47 int lt_mt_priority;
48 48 int lt_mt_cause_id;
49 49 } lt_match_t;
50 50
51 51 /* All lt_cause_t that are created. */
52 52 static GHashTable *cause_lookup = NULL;
53 53 static GPtrArray *causes_array = NULL;
54 54 static int causes_array_len = 0;
55 55
56 56 /*
57 57 * This hash table maps a symbol to a cause.
58 58 * key is of type "char *" and value is of type "lt_match_t *".
59 59 */
60 60 static GHashTable *symbol_lookup_table = NULL;
61 61
62 62 /*
63 63 * The dtrace translation rules we get from the script
64 64 */
65 65 char *dtrans = NULL;
66 66
67 67 /*
68 68 * These structures are only used inside .trans parser.
69 69 */
70 70 typedef struct {
71 71 int lt_dm_priority;
72 72 char *lt_dm_macro;
73 73 } lt_dmacro_t;
74 74
75 75 typedef struct {
76 76 GSequence *lt_pr_cmd_disable;
77 77 GHashTable *lt_pr_dmacro;
78 78 } lt_parser_t;
79 79
80 80 /* ARGSUSED */
81 81 static void
82 82 free_cause(lt_cause_t *cause, void *user)
83 83 {
84 84 g_assert(cause != NULL && cause->lt_c_name != NULL);
85 85
86 86 free(cause->lt_c_name);
87 87 free(cause);
88 88 }
89 89
90 90 static void
91 91 free_dmacro(lt_dmacro_t *d)
92 92 {
93 93 g_assert(d->lt_dm_macro != NULL);
94 94 free(d->lt_dm_macro);
95 95 free(d);
96 96 }
97 97
98 98 /*
99 99 * Add a cause.
100 100 */
101 101 static lt_cause_t *
102 102 new_cause(char *name, int flags)
103 103 {
104 104 lt_cause_t *entry;
105 105
106 106 g_assert(name != NULL);
107 107
108 108 entry = (lt_cause_t *)lt_malloc(sizeof (lt_cause_t));
109 109 entry->lt_c_flags = flags;
110 110 entry->lt_c_name = name;
111 111 entry->lt_c_cause_id = causes_array_len;
112 112
113 113 g_ptr_array_add(causes_array, entry);
114 114 ++causes_array_len;
115 115
116 116 return (entry);
117 117 }
118 118
119 119 /*
120 120 * Set a cause to "disabled" state.
121 121 */
122 122 static void
123 123 disable_cause(char *cause_str, GHashTable *cause_table)
124 124 {
125 125 lt_cause_t *cause;
126 126
127 127 cause = (lt_cause_t *)g_hash_table_lookup(cause_table, cause_str);
128 128
129 129 if (cause != NULL) {
130 130 cause->lt_c_flags |= CAUSE_FLAG_DISABLED;
131 131 }
132 132 }
133 133
134 134 /*
135 135 * Helper functions that reads a line from a character array.
136 136 */
137 137 static int
138 138 read_line_from_mem(const char *mem, int mem_len, char *line, int line_len,
139 139 int *index)
140 140 {
141 141 g_assert(mem != NULL && line != NULL && index != NULL);
142 142
143 143 if (line_len <= 0 || mem_len <= 0) {
144 144 return (0);
145 145 }
146 146
147 147 if (*index >= mem_len) {
148 148 return (0);
149 149 }
150 150
151 151 while (line_len > 1 && *index < mem_len) {
152 152 *line = mem[(*index)++];
153 153 --line_len;
154 154 ++line;
155 155
156 156 if (*(line-1) == '\r' || *(line-1) == '\n') {
157 157 break;
|
↓ open down ↓ |
157 lines elided |
↑ open up ↑ |
158 158 }
159 159 }
160 160 *line = '\0';
161 161
162 162 return (1);
163 163 }
164 164
165 165 /*
166 166 * Parse special command from configuration file. Special command
167 167 * has the following format :
168 -
168 + *
169 169 * disable_cause <cause name>
170 170 */
171 171 static int
172 172 parse_config_cmd(char *begin, lt_parser_t *parser)
173 173 {
174 174 char *tmp;
175 175 char old_chr = 0;
176 176
177 177 /*
178 178 * disable_cause FSFlush Daemon
179 179 * ^
180 180 */
181 181 if (*begin == '\0') {
182 182 return (0);
183 183 }
184 184
185 185 for (tmp = begin;
186 186 *tmp != '\0' && !isspace(*tmp);
187 187 ++tmp) {
188 188 }
189 189 old_chr = *tmp;
190 190 *tmp = '\0';
191 191
192 192 if (strcmp("disable_cause", begin) == 0) {
193 193 if (old_chr == '\0') {
194 194 /* Must have an argument */
195 195 lt_display_error(
196 196 "Invalid command format: %s\n",
197 197 begin);
198 198 return (-1);
199 199 }
200 200
201 201 begin = tmp+1;
202 202 while (isspace(*begin)) {
203 203 ++begin;
204 204 }
205 205
206 206 g_sequence_append(parser->lt_pr_cmd_disable,
207 207 lt_strdup(begin));
208 208 } else {
209 209 *tmp = old_chr;
210 210 lt_display_error(
211 211 "Unknown command: %s\n", begin);
212 212 return (-1);
213 213 }
214 214
215 215 return (0);
216 216 }
217 217
218 218 /*
219 219 * Parse symbol translation from configuration file. Symbol translation
220 220 * has the following format :
221 221 *
222 222 * <priority> <symbol name> <cause>
223 223 *
224 224 * Finally check if that cause has already been mapped.
225 225 */
226 226 static int
227 227 parse_sym_trans(char *begin)
228 228 {
229 229 int priority = 0;
230 230 char *match;
231 231 char *match_dup;
232 232 char *cause_str;
233 233 lt_cause_t *cause;
234 234 lt_match_t *match_entry;
235 235 char *tmp;
236 236
237 237 /*
238 238 * 10 genunix`pread Syscall pread
239 239 * ^
240 240 */
241 241 priority = strtol(begin, &tmp, 10);
242 242
243 243 if (tmp == begin || priority == 0) {
244 244 return (-1);
245 245 }
246 246
247 247 begin = tmp;
248 248
249 249 /*
250 250 * 10 genunix`pread Syscall pread
251 251 * --^
252 252 */
253 253
254 254 if (!isspace(*begin)) {
255 255 /* At least one space char after <priority> */
256 256 return (-1);
257 257 }
258 258
259 259 while (isspace(*begin)) {
260 260 ++begin;
261 261 }
262 262
263 263 if (*begin == 0) {
264 264 return (-1);
265 265 }
266 266
267 267 /*
268 268 * 10 genunix`pread Syscall pread
269 269 * -----^
270 270 */
271 271 for (tmp = begin;
272 272 *tmp != '\0' && !isspace(*tmp);
273 273 ++tmp) {
274 274 }
275 275
276 276 if (*tmp == '\0') {
277 277 return (-1);
278 278 }
279 279
280 280 *tmp = '\0';
281 281 match = begin;
282 282
283 283 /* Check if we have mapped this function before. */
284 284 match_entry = (lt_match_t *)
285 285 g_hash_table_lookup(symbol_lookup_table, match);
286 286
287 287 if (match_entry != NULL &&
288 288 HIGHER_PRIORITY(match_entry->lt_mt_priority, priority)) {
289 289 /* We already have a higher entry. Ignore this. */
290 290 return (0);
291 291 }
292 292
293 293 begin = tmp + 1;
294 294
295 295 /*
296 296 * 10 genunix`pread Syscall pread
297 297 * -------------------------------------^
298 298 */
299 299 while (isspace(*begin)) {
300 300 ++begin;
301 301 }
302 302
303 303 if (*begin == 0) {
304 304 return (-1);
305 305 }
306 306
307 307 cause_str = begin;
308 308
309 309 /* Check if we have mapped this cause before. */
310 310 cause = (lt_cause_t *)
311 311 g_hash_table_lookup(cause_lookup, cause_str);
312 312
313 313 if (cause == NULL) {
314 314 char *cause_dup = lt_strdup(cause_str);
315 315 cause = new_cause(cause_dup, 0);
316 316 g_hash_table_insert(cause_lookup, cause_dup, cause);
317 317 }
318 318
319 319 match_entry = (lt_match_t *)lt_malloc(sizeof (lt_match_t));
320 320 match_entry->lt_mt_priority = priority;
321 321 match_entry->lt_mt_cause_id = cause->lt_c_cause_id;
322 322 match_dup = lt_strdup(match);
323 323
324 324 g_hash_table_insert(symbol_lookup_table, match_dup,
325 325 match_entry);
326 326
327 327 return (0);
328 328 }
329 329
330 330 /*
331 331 * Parse D macro. D macros have the following format :
332 332 *
333 333 * <priority> <entry probe> <return probe> <cause>
334 334 *
335 335 * Finally check if that cause has already been mapped.
336 336 */
337 337 static int
338 338 parse_dmacro(char *begin, lt_parser_t *parser)
339 339 {
340 340 int priority = 0;
341 341 char *entryprobe;
342 342 char *returnprobe;
343 343 char *cause_str;
344 344 char buf[512];
345 345 char probepair[512];
346 346 char *tmp = NULL;
347 347 lt_cause_t *cause;
348 348 lt_dmacro_t *dmacro;
349 349
350 350 /*
351 351 * 10 syscall::pread:entry syscall::pread:return Syscall pread
352 352 * ^
353 353 */
354 354 priority = strtol(begin, &tmp, 10);
355 355
356 356 if (tmp == begin || priority == 0) {
357 357 return (-1);
358 358 }
359 359
360 360 begin = tmp;
361 361
362 362 /*
363 363 * 10 syscall::pread:entry syscall::pread:return Syscall pread
364 364 * --^
365 365 */
366 366 while (isspace(*begin)) {
367 367 ++begin;
368 368 }
369 369
370 370 if (*begin == 0) {
371 371 return (-1);
372 372 }
373 373
374 374 /*
375 375 * 10 syscall::pread:entry syscall::pread:return Syscall pread
376 376 * -----^
377 377 */
378 378 for (tmp = begin;
379 379 *tmp != '\0' && !isspace(*tmp);
380 380 ++tmp) {
381 381 }
382 382
383 383 if (*tmp == '\0') {
384 384 return (-1);
385 385 }
386 386
387 387 *tmp = '\0';
388 388 entryprobe = begin;
389 389 begin = tmp + 1;
390 390
391 391 while (isspace(*begin)) {
392 392 ++begin;
393 393 }
394 394
395 395 /*
396 396 * 10 syscall::pread:entry syscall::pread:return Syscall pread
397 397 * -----------------------------^
398 398 */
399 399 for (tmp = begin;
400 400 *tmp != '\0' && !isspace(*tmp);
401 401 ++tmp) {
402 402 }
403 403
404 404 if (*tmp == '\0') {
405 405 return (-1);
406 406 }
407 407
408 408 *tmp = '\0';
409 409 returnprobe = begin;
410 410 begin = tmp + 1;
411 411
412 412 while (isspace(*begin)) {
413 413 ++begin;
414 414 }
415 415
416 416 /*
417 417 * 10 syscall::pread:entry syscall::pread:return Syscall pread
418 418 * -----------------------------------------------------^
419 419 */
420 420 if (*begin == 0) {
421 421 return (-1);
422 422 }
423 423
424 424 cause_str = begin;
425 425
426 426 dmacro = NULL;
427 427
428 428 /* Check if we have mapped this cause before. */
429 429 cause = (lt_cause_t *)
430 430 g_hash_table_lookup(cause_lookup, cause_str);
431 431
432 432 if (cause == NULL) {
433 433 char *cause_dup = lt_strdup(cause_str);
434 434 cause = new_cause(cause_dup, 0);
435 435 g_hash_table_insert(cause_lookup, cause_dup, cause);
436 436 }
437 437
438 438 (void) snprintf(buf, sizeof (buf), "\nTRANSLATE(%s, %s, \"%s\", %d)\n",
439 439 entryprobe, returnprobe, cause_str, priority);
440 440
441 441 (void) snprintf(probepair, sizeof (probepair), "%s %s", entryprobe,
442 442 returnprobe);
443 443
444 444 g_assert(cause != NULL);
445 445 g_assert(parser->lt_pr_dmacro != NULL);
446 446
447 447 dmacro = g_hash_table_lookup(parser->lt_pr_dmacro, probepair);
448 448
449 449 if (dmacro == NULL) {
450 450 dmacro = (lt_dmacro_t *)lt_malloc(sizeof (lt_dmacro_t));
451 451 dmacro->lt_dm_priority = priority;
452 452 dmacro->lt_dm_macro = lt_strdup(buf);
453 453 g_hash_table_insert(parser->lt_pr_dmacro, lt_strdup(probepair),
454 454 dmacro);
455 455 } else if (dmacro->lt_dm_priority < priority) {
456 456 free(dmacro->lt_dm_macro);
457 457 dmacro->lt_dm_priority = priority;
458 458 dmacro->lt_dm_macro = lt_strdup(buf);
459 459 }
460 460
461 461 return (0);
462 462 }
463 463
464 464 /*
465 465 * Helper function to collect TRANSLATE() macros.
466 466 */
467 467 /* ARGSUSED */
468 468 static void
469 469 genscript(void *key, lt_dmacro_t *dmacro, GString *str)
470 470 {
471 471 g_string_append(str, dmacro->lt_dm_macro);
472 472 }
473 473
474 474 /*
475 475 * Main logic that parses translation rules one line at a time,
476 476 * and creates a lookup table from it. The syntax for the translation
477 477 * is as follows :
478 478 *
479 479 * # <--- comment
480 480 * D <D macro rule> <--- D macro
481 481 * S <Symbol translation> <--- Symbols
482 482 * disable_cause <cause> <--- special command
483 483 */
484 484 static int
485 485 parse_config(const char *work, int work_len)
486 486 {
487 487 char line[256];
488 488 int len;
489 489 char *begin, *end;
490 490 int current = 0;
491 491 lt_parser_t parser;
492 492 int ret = 0;
493 493 char flag;
494 494 GString *script;
495 495
496 496 cause_lookup = g_hash_table_new(g_str_hash, g_str_equal);
497 497 lt_check_null(cause_lookup);
498 498
499 499 parser.lt_pr_cmd_disable = g_sequence_new((GDestroyNotify)free);
500 500 lt_check_null(parser.lt_pr_cmd_disable);
501 501
502 502 parser.lt_pr_dmacro = g_hash_table_new_full(g_str_hash,
503 503 g_str_equal, (GDestroyNotify)free, (GDestroyNotify)free_dmacro);
504 504 lt_check_null(parser.lt_pr_dmacro);
505 505
506 506 while (read_line_from_mem(work, work_len, line, sizeof (line),
507 507 ¤t)) {
508 508 len = strlen(line);
509 509
510 510 if (line[len-1] != '\n' && line[len-1] != '\r' &&
511 511 current < work_len) {
512 512 lt_display_error("Configuration line too long.\n");
513 513 goto err;
514 514 }
515 515
516 516 begin = line;
517 517
518 518 while (isspace(*begin)) {
519 519 ++begin;
520 520 }
521 521
522 522 if (*begin == '\0') {
523 523 /* Ignore empty line */
524 524 continue;
525 525 }
526 526
527 527 /* Delete trailing spaces. */
528 528 end = begin + strlen(begin) - 1;
529 529
530 530 while (isspace(*end)) {
531 531 --end;
532 532 }
533 533
534 534 end[1] = '\0';
535 535
536 536 flag = *begin;
537 537 ++begin;
538 538
539 539 switch (flag) {
540 540 case '#':
541 541 ret = 0;
542 542 break;
543 543 case ';':
544 544 ret = parse_config_cmd(begin, &parser);
545 545 break;
546 546 case 'D':
547 547 case 'd':
548 548 if (!isspace(*begin)) {
549 549 lt_display_error(
550 550 "No space after flag char: %s\n", line);
551 551 }
552 552 while (isspace(*begin)) {
553 553 ++begin;
554 554 }
555 555 ret = parse_dmacro(begin, &parser);
556 556 break;
557 557 case 'S':
558 558 case 's':
559 559 if (!isspace(*begin)) {
560 560 lt_display_error(
561 561 "No space after flag char: %s\n", line);
562 562 }
563 563 while (isspace(*begin)) {
564 564 ++begin;
565 565 }
566 566 ret = parse_sym_trans(begin);
567 567 break;
568 568 default:
569 569 ret = -1;
570 570 break;
571 571 }
572 572
573 573 if (ret != 0) {
574 574 lt_display_error(
575 575 "Invalid configuration line: %s\n", line);
576 576 goto err;
577 577 }
578 578 }
579 579
580 580 script = g_string_new(NULL);
581 581 g_hash_table_foreach(parser.lt_pr_dmacro, (GHFunc)genscript, script);
582 582 dtrans = g_string_free(script, FALSE);
583 583
584 584 if (dtrans != NULL && strlen(dtrans) == 0) {
585 585 free(dtrans);
586 586 dtrans = NULL;
587 587 }
588 588
589 589 g_sequence_foreach(parser.lt_pr_cmd_disable, (GFunc)disable_cause,
590 590 cause_lookup);
591 591 g_sequence_free(parser.lt_pr_cmd_disable);
592 592
593 593 return (0);
594 594
595 595 err:
596 596 g_sequence_free(parser.lt_pr_cmd_disable);
597 597 g_hash_table_destroy(parser.lt_pr_dmacro);
598 598 return (-1);
599 599
600 600 }
601 601
602 602 /*
603 603 * Init function, called when latencytop starts.
604 604 * It loads translation rules from the configuration file. The configuration
605 605 * file defines some causes and symbols that match those causes.
606 606 */
607 607 int
608 608 lt_table_init(void)
609 609 {
610 610 char *config_loaded = NULL;
611 611 int config_loaded_len = 0;
612 612 const char *work = NULL;
613 613 int work_len = 0;
614 614 lt_cause_t *cause;
615 615
616 616 #ifdef EMBED_CONFIGS
617 617 work = &latencytop_trans_start;
618 618 work_len = (int)(&latencytop_trans_end - &latencytop_trans_start);
619 619 #endif
620 620
621 621 if (g_config.lt_cfg_config_name != NULL) {
622 622 FILE *fp;
623 623 fp = fopen(g_config.lt_cfg_config_name, "r");
624 624
625 625 if (NULL == fp) {
626 626 lt_display_error(
627 627 "Unable to open configuration file.\n");
628 628 return (-1);
629 629 }
630 630
631 631 (void) fseek(fp, 0, SEEK_END);
632 632 config_loaded_len = (int)ftell(fp);
633 633 config_loaded = (char *)lt_malloc(config_loaded_len);
634 634 (void) fseek(fp, 0, SEEK_SET);
635 635
636 636 /* A zero-byte translation is valid */
637 637 if (config_loaded_len != 0 &&
638 638 fread(config_loaded, config_loaded_len, 1, fp) == 0) {
639 639 lt_display_error(
640 640 "Unable to read configuration file.\n");
641 641 (void) fclose(fp);
642 642 free(config_loaded);
643 643 return (-1);
644 644 }
645 645
646 646 (void) fclose(fp);
647 647 (void) printf("Loaded configuration from %s\n",
648 648 g_config.lt_cfg_config_name);
649 649
650 650 work = config_loaded;
651 651 work_len = config_loaded_len;
652 652 }
653 653
654 654 lt_table_deinit();
655 655 causes_array = g_ptr_array_new();
656 656 lt_check_null(causes_array);
657 657
658 658 /* 0 is not used, but it is kept as a place for bugs etc. */
659 659 cause = new_cause(lt_strdup("Nothing"), CAUSE_FLAG_DISABLED);
660 660 g_assert(cause->lt_c_cause_id == INVALID_CAUSE);
661 661
662 662 symbol_lookup_table = g_hash_table_new_full(
663 663 g_str_hash, g_str_equal,
664 664 (GDestroyNotify)free, (GDestroyNotify)free);
665 665 lt_check_null(symbol_lookup_table);
666 666
667 667 if (work_len != 0 && parse_config(work, work_len) != 0) {
668 668 return (-1);
669 669 }
670 670
671 671 if (config_loaded != NULL) {
672 672 free(config_loaded);
673 673 }
674 674
675 675 return (0);
676 676 }
677 677
678 678 /*
679 679 * Some causes, such as "lock spinning", do not have stack trace. Names
680 680 * of such causes are explicitly specified in the D script.
681 681 * This function resolves such causes and dynamically adds them
682 682 * to the global tables when they are found first. If auto_create is set
683 683 * to TRUE, the entry will be created if it is not found.
684 684 * Return cause_id of the cause.
685 685 */
686 686 int
687 687 lt_table_cause_from_name(char *name, int auto_create, int flags)
688 688 {
689 689 lt_cause_t *cause = NULL;
690 690
691 691 if (cause_lookup == NULL) {
692 692 cause_lookup = g_hash_table_new(g_str_hash, g_str_equal);
693 693 lt_check_null(cause_lookup);
694 694 } else {
695 695 cause = (lt_cause_t *)
696 696 g_hash_table_lookup(cause_lookup, name);
697 697 }
698 698
699 699 if (cause == NULL && auto_create) {
700 700 char *cause_dup;
701 701
702 702 if (name[0] == '#') {
703 703 flags |= CAUSE_FLAG_HIDE_IN_SUMMARY;
704 704 }
705 705
706 706 cause_dup = lt_strdup(name);
707 707 cause = new_cause(cause_dup, flags);
708 708 g_hash_table_insert(cause_lookup, cause_dup, cause);
709 709 }
710 710
711 711 return (cause == NULL ? INVALID_CAUSE : cause->lt_c_cause_id);
712 712 }
713 713
714 714 /*
715 715 * Try to map a symbol on stack to a known cause.
716 716 * module_func has the format "module_name`function_name".
717 717 * cause_id and priority will be set if a cause is found.
718 718 * If cause is found return 1, otherwise return 0.
719 719 */
720 720 int
721 721 lt_table_cause_from_stack(const char *module_func, int *cause_id, int *priority)
722 722 {
723 723 lt_match_t *match;
724 724
725 725 g_assert(module_func != NULL && cause_id != NULL && priority != NULL);
726 726
727 727 if (symbol_lookup_table == NULL) {
728 728 return (0);
729 729 }
730 730
731 731 match = (lt_match_t *)
732 732 g_hash_table_lookup(symbol_lookup_table, module_func);
733 733
734 734 if (match == NULL) {
735 735 char *func = strchr(module_func, '`');
736 736
737 737 if (func != NULL) {
738 738 match = (lt_match_t *)
739 739 g_hash_table_lookup(symbol_lookup_table, func);
740 740 }
741 741 }
742 742
743 743 if (match == NULL) {
744 744 return (0);
745 745 } else {
746 746 *cause_id = match->lt_mt_cause_id;
747 747 *priority = match->lt_mt_priority;
748 748 return (1);
749 749 }
750 750 }
751 751
752 752 /*
753 753 * Get the display name of a cause. cause_id must be valid,
754 754 * it is usually returned from lt_table_cause_from_stack() or
755 755 * lt_table_cause_from_name().
756 756 */
757 757 const char *
758 758 lt_table_get_cause_name(int cause_id)
759 759 {
760 760 lt_cause_t *cause;
761 761
762 762 if (cause_id < 0 || cause_id >= causes_array_len) {
763 763 return (NULL);
764 764 }
765 765
766 766 cause = (lt_cause_t *)g_ptr_array_index(causes_array, cause_id);
767 767
768 768 if (cause == NULL) {
769 769 return (NULL);
770 770 } else {
771 771 return (cause->lt_c_name);
772 772 }
773 773 }
774 774
775 775 /*
776 776 * Check cause flag.
777 777 * If CAUSE_ALL_FLAGS is passed in, all flags are returned.
778 778 */
779 779 int
780 780 lt_table_get_cause_flag(int cause_id, int flag)
781 781 {
782 782 lt_cause_t *cause;
783 783
784 784 if (cause_id < 0 || cause_id >= causes_array_len) {
785 785 return (0);
786 786 }
787 787
788 788 cause = (lt_cause_t *)g_ptr_array_index(causes_array, cause_id);
789 789
790 790 if (cause == NULL) {
791 791 return (0);
792 792 } else {
793 793 return (cause->lt_c_flags & flag);
794 794 }
795 795 }
796 796
797 797 /*
798 798 * Append macros to D script, if any.
799 799 */
800 800 int
801 801 lt_table_append_trans(FILE *fp)
802 802 {
803 803 if (dtrans != NULL) {
804 804 if (fwrite(dtrans, strlen(dtrans), 1, fp) != 1) {
805 805 return (-1);
806 806 }
807 807 }
808 808
809 809 return (0);
810 810 }
811 811
812 812 /*
813 813 * Clean up function.
814 814 * Free the resources used for symbol table (symbols, causes etc.).
815 815 */
816 816 void
817 817 lt_table_deinit(void)
818 818 {
819 819 if (symbol_lookup_table != NULL) {
820 820 g_hash_table_destroy(symbol_lookup_table);
821 821 symbol_lookup_table = NULL;
822 822 }
823 823
824 824 if (cause_lookup != NULL) {
825 825 g_hash_table_destroy(cause_lookup);
826 826 cause_lookup = NULL;
827 827 }
828 828
829 829 if (causes_array != NULL) {
830 830 g_ptr_array_foreach(causes_array, (GFunc)free_cause, NULL);
831 831 g_ptr_array_free(causes_array, TRUE);
832 832 causes_array = NULL;
833 833 causes_array_len = 0;
834 834 }
835 835
836 836 if (dtrans != NULL) {
837 837 g_free(dtrans);
838 838 dtrans = NULL;
839 839 }
840 840 }
|
↓ open down ↓ |
662 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX