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