1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * config.c 4 * 5 * Helper functions for parsing config items. 6 * Originally copied from GIT source. 7 * 8 * Copyright (C) Linus Torvalds, 2005 9 * Copyright (C) Johannes Schindelin, 2005 10 * 11 */ 12 #include <errno.h> 13 #include <sys/param.h> 14 #include "cache.h" 15 #include "callchain.h" 16 #include <subcmd/exec-cmd.h> 17 #include "util/event.h" /* proc_map_timeout */ 18 #include "util/hist.h" /* perf_hist_config */ 19 #include "util/llvm-utils.h" /* perf_llvm_config */ 20 #include "util/stat.h" /* perf_stat__set_big_num */ 21 #include "util/evsel.h" /* evsel__hw_names, evsel__use_bpf_counters */ 22 #include "util/srcline.h" /* addr2line_timeout_ms */ 23 #include "build-id.h" 24 #include "debug.h" 25 #include "config.h" 26 #include <sys/types.h> 27 #include <sys/stat.h> 28 #include <stdlib.h> 29 #include <unistd.h> 30 #include <linux/string.h> 31 #include <linux/zalloc.h> 32 #include <linux/ctype.h> 33 34 #define MAXNAME (256) 35 36 #define DEBUG_CACHE_DIR ".debug" 37 38 39 char buildid_dir[MAXPATHLEN]; /* root dir for buildid, binary cache */ 40 41 static FILE *config_file; 42 static const char *config_file_name; 43 static int config_linenr; 44 static int config_file_eof; 45 static struct perf_config_set *config_set; 46 47 const char *config_exclusive_filename; 48 49 static int get_next_char(void) 50 { 51 int c; 52 FILE *f; 53 54 c = '\n'; 55 if ((f = config_file) != NULL) { 56 c = fgetc(f); 57 if (c == '\r') { 58 /* DOS like systems */ 59 c = fgetc(f); 60 if (c != '\n') { 61 ungetc(c, f); 62 c = '\r'; 63 } 64 } 65 if (c == '\n') 66 config_linenr++; 67 if (c == EOF) { 68 config_file_eof = 1; 69 c = '\n'; 70 } 71 } 72 return c; 73 } 74 75 static char *parse_value(void) 76 { 77 static char value[1024]; 78 int quote = 0, comment = 0, space = 0; 79 size_t len = 0; 80 81 for (;;) { 82 int c = get_next_char(); 83 84 if (len >= sizeof(value) - 1) 85 return NULL; 86 if (c == '\n') { 87 if (quote) 88 return NULL; 89 value[len] = 0; 90 return value; 91 } 92 if (comment) 93 continue; 94 if (isspace(c) && !quote) { 95 space = 1; 96 continue; 97 } 98 if (!quote) { 99 if (c == ';' || c == '#') { 100 comment = 1; 101 continue; 102 } 103 } 104 if (space) { 105 if (len) 106 value[len++] = ' '; 107 space = 0; 108 } 109 if (c == '\\') { 110 c = get_next_char(); 111 switch (c) { 112 case '\n': 113 continue; 114 case 't': 115 c = '\t'; 116 break; 117 case 'b': 118 c = '\b'; 119 break; 120 case 'n': 121 c = '\n'; 122 break; 123 /* Some characters escape as themselves */ 124 case '\\': case '"': 125 break; 126 /* Reject unknown escape sequences */ 127 default: 128 return NULL; 129 } 130 value[len++] = c; 131 continue; 132 } 133 if (c == '"') { 134 quote = 1-quote; 135 continue; 136 } 137 value[len++] = c; 138 } 139 } 140 141 static inline int iskeychar(int c) 142 { 143 return isalnum(c) || c == '-' || c == '_'; 144 } 145 146 static int get_value(config_fn_t fn, void *data, char *name, unsigned int len) 147 { 148 int c; 149 char *value; 150 151 /* Get the full name */ 152 for (;;) { 153 c = get_next_char(); 154 if (config_file_eof) 155 break; 156 if (!iskeychar(c)) 157 break; 158 name[len++] = c; 159 if (len >= MAXNAME) 160 return -1; 161 } 162 name[len] = 0; 163 while (c == ' ' || c == '\t') 164 c = get_next_char(); 165 166 value = NULL; 167 if (c != '\n') { 168 if (c != '=') 169 return -1; 170 value = parse_value(); 171 if (!value) 172 return -1; 173 } 174 return fn(name, value, data); 175 } 176 177 static int get_extended_base_var(char *name, int baselen, int c) 178 { 179 do { 180 if (c == '\n') 181 return -1; 182 c = get_next_char(); 183 } while (isspace(c)); 184 185 /* We require the format to be '[base "extension"]' */ 186 if (c != '"') 187 return -1; 188 name[baselen++] = '.'; 189 190 for (;;) { 191 int ch = get_next_char(); 192 193 if (ch == '\n') 194 return -1; 195 if (ch == '"') 196 break; 197 if (ch == '\\') { 198 ch = get_next_char(); 199 if (ch == '\n') 200 return -1; 201 } 202 name[baselen++] = ch; 203 if (baselen > MAXNAME / 2) 204 return -1; 205 } 206 207 /* Final ']' */ 208 if (get_next_char() != ']') 209 return -1; 210 return baselen; 211 } 212 213 static int get_base_var(char *name) 214 { 215 int baselen = 0; 216 217 for (;;) { 218 int c = get_next_char(); 219 if (config_file_eof) 220 return -1; 221 if (c == ']') 222 return baselen; 223 if (isspace(c)) 224 return get_extended_base_var(name, baselen, c); 225 if (!iskeychar(c) && c != '.') 226 return -1; 227 if (baselen > MAXNAME / 2) 228 return -1; 229 name[baselen++] = tolower(c); 230 } 231 } 232 233 static int perf_parse_file(config_fn_t fn, void *data) 234 { 235 int comment = 0; 236 int baselen = 0; 237 static char var[MAXNAME]; 238 239 /* U+FEFF Byte Order Mark in UTF8 */ 240 static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf"; 241 const unsigned char *bomptr = utf8_bom; 242 243 for (;;) { 244 int line, c = get_next_char(); 245 246 if (bomptr && *bomptr) { 247 /* We are at the file beginning; skip UTF8-encoded BOM 248 * if present. Sane editors won't put this in on their 249 * own, but e.g. Windows Notepad will do it happily. */ 250 if ((unsigned char) c == *bomptr) { 251 bomptr++; 252 continue; 253 } else { 254 /* Do not tolerate partial BOM. */ 255 if (bomptr != utf8_bom) 256 break; 257 /* No BOM at file beginning. Cool. */ 258 bomptr = NULL; 259 } 260 } 261 if (c == '\n') { 262 if (config_file_eof) 263 return 0; 264 comment = 0; 265 continue; 266 } 267 if (comment || isspace(c)) 268 continue; 269 if (c == '#' || c == ';') { 270 comment = 1; 271 continue; 272 } 273 if (c == '[') { 274 baselen = get_base_var(var); 275 if (baselen <= 0) 276 break; 277 var[baselen++] = '.'; 278 var[baselen] = 0; 279 continue; 280 } 281 if (!isalpha(c)) 282 break; 283 var[baselen] = tolower(c); 284 285 /* 286 * The get_value function might or might not reach the '\n', 287 * so saving the current line number for error reporting. 288 */ 289 line = config_linenr; 290 if (get_value(fn, data, var, baselen+1) < 0) { 291 config_linenr = line; 292 break; 293 } 294 } 295 pr_err("bad config file line %d in %s\n", config_linenr, config_file_name); 296 return -1; 297 } 298 299 static int parse_unit_factor(const char *end, unsigned long *val) 300 { 301 if (!*end) 302 return 1; 303 else if (!strcasecmp(end, "k")) { 304 *val *= 1024; 305 return 1; 306 } 307 else if (!strcasecmp(end, "m")) { 308 *val *= 1024 * 1024; 309 return 1; 310 } 311 else if (!strcasecmp(end, "g")) { 312 *val *= 1024 * 1024 * 1024; 313 return 1; 314 } 315 return 0; 316 } 317 318 static int perf_parse_llong(const char *value, long long *ret) 319 { 320 if (value && *value) { 321 char *end; 322 long long val = strtoll(value, &end, 0); 323 unsigned long factor = 1; 324 325 if (!parse_unit_factor(end, &factor)) 326 return 0; 327 *ret = val * factor; 328 return 1; 329 } 330 return 0; 331 } 332 333 static int perf_parse_long(const char *value, long *ret) 334 { 335 if (value && *value) { 336 char *end; 337 long val = strtol(value, &end, 0); 338 unsigned long factor = 1; 339 if (!parse_unit_factor(end, &factor)) 340 return 0; 341 *ret = val * factor; 342 return 1; 343 } 344 return 0; 345 } 346 347 static void bad_config(const char *name) 348 { 349 if (config_file_name) 350 pr_warning("bad config value for '%s' in %s, ignoring...\n", name, config_file_name); 351 else 352 pr_warning("bad config value for '%s', ignoring...\n", name); 353 } 354 355 int perf_config_u64(u64 *dest, const char *name, const char *value) 356 { 357 long long ret = 0; 358 359 if (!perf_parse_llong(value, &ret)) { 360 bad_config(name); 361 return -1; 362 } 363 364 *dest = ret; 365 return 0; 366 } 367 368 int perf_config_int(int *dest, const char *name, const char *value) 369 { 370 long ret = 0; 371 if (!perf_parse_long(value, &ret)) { 372 bad_config(name); 373 return -1; 374 } 375 *dest = ret; 376 return 0; 377 } 378 379 int perf_config_u8(u8 *dest, const char *name, const char *value) 380 { 381 long ret = 0; 382 383 if (!perf_parse_long(value, &ret)) { 384 bad_config(name); 385 return -1; 386 } 387 *dest = ret; 388 return 0; 389 } 390 391 static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) 392 { 393 int ret; 394 395 *is_bool = 1; 396 if (!value) 397 return 1; 398 if (!*value) 399 return 0; 400 if (!strcasecmp(value, "true") || !strcasecmp(value, "yes") || !strcasecmp(value, "on")) 401 return 1; 402 if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off")) 403 return 0; 404 *is_bool = 0; 405 return perf_config_int(&ret, name, value) < 0 ? -1 : ret; 406 } 407 408 int perf_config_bool(const char *name, const char *value) 409 { 410 int discard; 411 return !!perf_config_bool_or_int(name, value, &discard); 412 } 413 414 static const char *perf_config_dirname(const char *name, const char *value) 415 { 416 if (!name) 417 return NULL; 418 return value; 419 } 420 421 static int perf_buildid_config(const char *var, const char *value) 422 { 423 /* same dir for all commands */ 424 if (!strcmp(var, "buildid.dir")) { 425 const char *dir = perf_config_dirname(var, value); 426 427 if (!dir) { 428 pr_err("Invalid buildid directory!\n"); 429 return -1; 430 } 431 strncpy(buildid_dir, dir, MAXPATHLEN-1); 432 buildid_dir[MAXPATHLEN-1] = '\0'; 433 } 434 435 return 0; 436 } 437 438 static int perf_default_core_config(const char *var, const char *value) 439 { 440 if (!strcmp(var, "core.proc-map-timeout")) 441 proc_map_timeout = strtoul(value, NULL, 10); 442 443 if (!strcmp(var, "core.addr2line-timeout")) 444 addr2line_timeout_ms = strtoul(value, NULL, 10); 445 446 /* Add other config variables here. */ 447 return 0; 448 } 449 450 static int perf_ui_config(const char *var, const char *value) 451 { 452 /* Add other config variables here. */ 453 if (!strcmp(var, "ui.show-headers")) 454 symbol_conf.show_hist_headers = perf_config_bool(var, value); 455 456 return 0; 457 } 458 459 static int perf_stat_config(const char *var, const char *value) 460 { 461 if (!strcmp(var, "stat.big-num")) 462 perf_stat__set_big_num(perf_config_bool(var, value)); 463 464 if (!strcmp(var, "stat.no-csv-summary")) 465 perf_stat__set_no_csv_summary(perf_config_bool(var, value)); 466 467 if (!strcmp(var, "stat.bpf-counter-events")) 468 evsel__bpf_counter_events = strdup(value); 469 470 /* Add other config variables here. */ 471 return 0; 472 } 473 474 int perf_default_config(const char *var, const char *value, 475 void *dummy __maybe_unused) 476 { 477 if (strstarts(var, "core.")) 478 return perf_default_core_config(var, value); 479 480 if (strstarts(var, "hist.")) 481 return perf_hist_config(var, value); 482 483 if (strstarts(var, "ui.")) 484 return perf_ui_config(var, value); 485 486 if (strstarts(var, "call-graph.")) 487 return perf_callchain_config(var, value); 488 489 if (strstarts(var, "llvm.")) 490 return perf_llvm_config(var, value); 491 492 if (strstarts(var, "buildid.")) 493 return perf_buildid_config(var, value); 494 495 if (strstarts(var, "stat.")) 496 return perf_stat_config(var, value); 497 498 /* Add other config variables here. */ 499 return 0; 500 } 501 502 static int perf_config_from_file(config_fn_t fn, const char *filename, void *data) 503 { 504 int ret; 505 FILE *f = fopen(filename, "r"); 506 507 ret = -1; 508 if (f) { 509 config_file = f; 510 config_file_name = filename; 511 config_linenr = 1; 512 config_file_eof = 0; 513 ret = perf_parse_file(fn, data); 514 fclose(f); 515 config_file_name = NULL; 516 } 517 return ret; 518 } 519 520 const char *perf_etc_perfconfig(void) 521 { 522 static const char *system_wide; 523 if (!system_wide) 524 system_wide = system_path(ETC_PERFCONFIG); 525 return system_wide; 526 } 527 528 static int perf_env_bool(const char *k, int def) 529 { 530 const char *v = getenv(k); 531 return v ? perf_config_bool(k, v) : def; 532 } 533 534 int perf_config_system(void) 535 { 536 return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0); 537 } 538 539 int perf_config_global(void) 540 { 541 return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); 542 } 543 544 static char *home_perfconfig(void) 545 { 546 const char *home = NULL; 547 char *config; 548 struct stat st; 549 char path[PATH_MAX]; 550 551 home = getenv("HOME"); 552 553 /* 554 * Skip reading user config if: 555 * - there is no place to read it from (HOME) 556 * - we are asked not to (PERF_CONFIG_NOGLOBAL=1) 557 */ 558 if (!home || !*home || !perf_config_global()) 559 return NULL; 560 561 config = strdup(mkpath(path, sizeof(path), "%s/.perfconfig", home)); 562 if (config == NULL) { 563 pr_warning("Not enough memory to process %s/.perfconfig, ignoring it.\n", home); 564 return NULL; 565 } 566 567 if (stat(config, &st) < 0) 568 goto out_free; 569 570 if (st.st_uid && (st.st_uid != geteuid())) { 571 pr_warning("File %s not owned by current user or root, ignoring it.\n", config); 572 goto out_free; 573 } 574 575 if (st.st_size) 576 return config; 577 578 out_free: 579 free(config); 580 return NULL; 581 } 582 583 const char *perf_home_perfconfig(void) 584 { 585 static const char *config; 586 static bool failed; 587 588 if (failed || config) 589 return config; 590 591 config = home_perfconfig(); 592 if (!config) 593 failed = true; 594 595 return config; 596 } 597 598 static struct perf_config_section *find_section(struct list_head *sections, 599 const char *section_name) 600 { 601 struct perf_config_section *section; 602 603 list_for_each_entry(section, sections, node) 604 if (!strcmp(section->name, section_name)) 605 return section; 606 607 return NULL; 608 } 609 610 static struct perf_config_item *find_config_item(const char *name, 611 struct perf_config_section *section) 612 { 613 struct perf_config_item *item; 614 615 list_for_each_entry(item, §ion->items, node) 616 if (!strcmp(item->name, name)) 617 return item; 618 619 return NULL; 620 } 621 622 static struct perf_config_section *add_section(struct list_head *sections, 623 const char *section_name) 624 { 625 struct perf_config_section *section = zalloc(sizeof(*section)); 626 627 if (!section) 628 return NULL; 629 630 INIT_LIST_HEAD(§ion->items); 631 section->name = strdup(section_name); 632 if (!section->name) { 633 pr_debug("%s: strdup failed\n", __func__); 634 free(section); 635 return NULL; 636 } 637 638 list_add_tail(§ion->node, sections); 639 return section; 640 } 641 642 static struct perf_config_item *add_config_item(struct perf_config_section *section, 643 const char *name) 644 { 645 struct perf_config_item *item = zalloc(sizeof(*item)); 646 647 if (!item) 648 return NULL; 649 650 item->name = strdup(name); 651 if (!item->name) { 652 pr_debug("%s: strdup failed\n", __func__); 653 free(item); 654 return NULL; 655 } 656 657 list_add_tail(&item->node, §ion->items); 658 return item; 659 } 660 661 static int set_value(struct perf_config_item *item, const char *value) 662 { 663 char *val = strdup(value); 664 665 if (!val) 666 return -1; 667 668 zfree(&item->value); 669 item->value = val; 670 return 0; 671 } 672 673 static int collect_config(const char *var, const char *value, 674 void *perf_config_set) 675 { 676 int ret = -1; 677 char *ptr, *key; 678 char *section_name, *name; 679 struct perf_config_section *section = NULL; 680 struct perf_config_item *item = NULL; 681 struct perf_config_set *set = perf_config_set; 682 struct list_head *sections; 683 684 if (set == NULL) 685 return -1; 686 687 sections = &set->sections; 688 key = ptr = strdup(var); 689 if (!key) { 690 pr_debug("%s: strdup failed\n", __func__); 691 return -1; 692 } 693 694 section_name = strsep(&ptr, "."); 695 name = ptr; 696 if (name == NULL || value == NULL) 697 goto out_free; 698 699 section = find_section(sections, section_name); 700 if (!section) { 701 section = add_section(sections, section_name); 702 if (!section) 703 goto out_free; 704 } 705 706 item = find_config_item(name, section); 707 if (!item) { 708 item = add_config_item(section, name); 709 if (!item) 710 goto out_free; 711 } 712 713 /* perf_config_set can contain both user and system config items. 714 * So we should know where each value is from. 715 * The classification would be needed when a particular config file 716 * is overwritten by setting feature i.e. set_config(). 717 */ 718 if (strcmp(config_file_name, perf_etc_perfconfig()) == 0) { 719 section->from_system_config = true; 720 item->from_system_config = true; 721 } else { 722 section->from_system_config = false; 723 item->from_system_config = false; 724 } 725 726 ret = set_value(item, value); 727 728 out_free: 729 free(key); 730 return ret; 731 } 732 733 int perf_config_set__collect(struct perf_config_set *set, const char *file_name, 734 const char *var, const char *value) 735 { 736 config_file_name = file_name; 737 return collect_config(var, value, set); 738 } 739 740 static int perf_config_set__init(struct perf_config_set *set) 741 { 742 int ret = -1; 743 744 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ 745 if (config_exclusive_filename) 746 return perf_config_from_file(collect_config, config_exclusive_filename, set); 747 if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) { 748 if (perf_config_from_file(collect_config, perf_etc_perfconfig(), set) < 0) 749 goto out; 750 } 751 if (perf_config_global() && perf_home_perfconfig()) { 752 if (perf_config_from_file(collect_config, perf_home_perfconfig(), set) < 0) 753 goto out; 754 } 755 756 out: 757 return ret; 758 } 759 760 struct perf_config_set *perf_config_set__new(void) 761 { 762 struct perf_config_set *set = zalloc(sizeof(*set)); 763 764 if (set) { 765 INIT_LIST_HEAD(&set->sections); 766 perf_config_set__init(set); 767 } 768 769 return set; 770 } 771 772 struct perf_config_set *perf_config_set__load_file(const char *file) 773 { 774 struct perf_config_set *set = zalloc(sizeof(*set)); 775 776 if (set) { 777 INIT_LIST_HEAD(&set->sections); 778 perf_config_from_file(collect_config, file, set); 779 } 780 781 return set; 782 } 783 784 static int perf_config__init(void) 785 { 786 if (config_set == NULL) 787 config_set = perf_config_set__new(); 788 789 return config_set == NULL; 790 } 791 792 int perf_config_set(struct perf_config_set *set, 793 config_fn_t fn, void *data) 794 { 795 int ret = 0; 796 char key[BUFSIZ]; 797 struct perf_config_section *section; 798 struct perf_config_item *item; 799 800 perf_config_set__for_each_entry(set, section, item) { 801 char *value = item->value; 802 803 if (value) { 804 scnprintf(key, sizeof(key), "%s.%s", 805 section->name, item->name); 806 ret = fn(key, value, data); 807 if (ret < 0) { 808 pr_err("Error in the given config file: wrong config key-value pair %s=%s\n", 809 key, value); 810 /* 811 * Can't be just a 'break', as perf_config_set__for_each_entry() 812 * expands to two nested for() loops. 813 */ 814 goto out; 815 } 816 } 817 } 818 out: 819 return ret; 820 } 821 822 int perf_config(config_fn_t fn, void *data) 823 { 824 if (config_set == NULL && perf_config__init()) 825 return -1; 826 827 return perf_config_set(config_set, fn, data); 828 } 829 830 void perf_config__exit(void) 831 { 832 perf_config_set__delete(config_set); 833 config_set = NULL; 834 } 835 836 void perf_config__refresh(void) 837 { 838 perf_config__exit(); 839 perf_config__init(); 840 } 841 842 static void perf_config_item__delete(struct perf_config_item *item) 843 { 844 zfree(&item->name); 845 zfree(&item->value); 846 free(item); 847 } 848 849 static void perf_config_section__purge(struct perf_config_section *section) 850 { 851 struct perf_config_item *item, *tmp; 852 853 list_for_each_entry_safe(item, tmp, §ion->items, node) { 854 list_del_init(&item->node); 855 perf_config_item__delete(item); 856 } 857 } 858 859 static void perf_config_section__delete(struct perf_config_section *section) 860 { 861 perf_config_section__purge(section); 862 zfree(§ion->name); 863 free(section); 864 } 865 866 static void perf_config_set__purge(struct perf_config_set *set) 867 { 868 struct perf_config_section *section, *tmp; 869 870 list_for_each_entry_safe(section, tmp, &set->sections, node) { 871 list_del_init(§ion->node); 872 perf_config_section__delete(section); 873 } 874 } 875 876 void perf_config_set__delete(struct perf_config_set *set) 877 { 878 if (set == NULL) 879 return; 880 881 perf_config_set__purge(set); 882 free(set); 883 } 884 885 /* 886 * Call this to report error for your variable that should not 887 * get a boolean value (i.e. "[my] var" means "true"). 888 */ 889 int config_error_nonbool(const char *var) 890 { 891 pr_err("Missing value for '%s'", var); 892 return -1; 893 } 894 895 void set_buildid_dir(const char *dir) 896 { 897 if (dir) 898 scnprintf(buildid_dir, MAXPATHLEN, "%s", dir); 899 900 /* default to $HOME/.debug */ 901 if (buildid_dir[0] == '\0') { 902 char *home = getenv("HOME"); 903 904 if (home) { 905 snprintf(buildid_dir, MAXPATHLEN, "%s/%s", 906 home, DEBUG_CACHE_DIR); 907 } else { 908 strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1); 909 } 910 buildid_dir[MAXPATHLEN-1] = '\0'; 911 } 912 /* for communicating with external commands */ 913 setenv("PERF_BUILDID_DIR", buildid_dir, 1); 914 } 915 916 struct perf_config_scan_data { 917 const char *name; 918 const char *fmt; 919 va_list args; 920 int ret; 921 }; 922 923 static int perf_config_scan_cb(const char *var, const char *value, void *data) 924 { 925 struct perf_config_scan_data *d = data; 926 927 if (!strcmp(var, d->name)) 928 d->ret = vsscanf(value, d->fmt, d->args); 929 930 return 0; 931 } 932 933 int perf_config_scan(const char *name, const char *fmt, ...) 934 { 935 struct perf_config_scan_data d = { 936 .name = name, 937 .fmt = fmt, 938 }; 939 940 va_start(d.args, fmt); 941 perf_config(perf_config_scan_cb, &d); 942 va_end(d.args); 943 944 return d.ret; 945 } 946