aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-11-28 04:49:10 -0500
committerIngo Molnar <mingo@kernel.org>2015-11-28 04:49:10 -0500
commitac675d0d586a2d96df58228c495b4005bc7bca7b (patch)
tree557cc686d470ac513c647cafd07ae61bf9793e0c
parent3f3b1a46bfdbce97dd3f9594d8a95db82baa554b (diff)
parent0bb93490170477224f8bd4cc9ce8920517461643 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: - Fix 'perf list' segfault due to lack of support for PERF_CONF_SW_BPF_OUTPUT in an array used just for printing available events, robustify the code involved (Arnaldo Carvalho de Melo) - 'perf test unwind' should create kernel maps, now that entry works and the test passes (Jiri Olsa) - Fix showing the running kernel build id in 'perf buildid-list' (Michael Petlan) - Fix command line symbol filtering in 'perf report' (Namhyung Kim) Infrastructure changes: - Extract and collect map info from BPF object files in libbpf (Wang Nan) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/lib/bpf/libbpf.c252
-rw-r--r--tools/lib/bpf/libbpf.h24
-rw-r--r--tools/perf/builtin-report.c12
-rw-r--r--tools/perf/tests/dwarf-unwind.c5
-rw-r--r--tools/perf/ui/browsers/hists.c5
-rw-r--r--tools/perf/util/bpf-loader.c65
-rw-r--r--tools/perf/util/bpf-loader.h2
-rw-r--r--tools/perf/util/build-id.c2
-rw-r--r--tools/perf/util/hist.c6
-rw-r--r--tools/perf/util/parse-events.c6
10 files changed, 268 insertions, 111 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e3f4c3379f14..a298614ad091 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -163,22 +163,25 @@ struct bpf_program {
163 bpf_program_clear_priv_t clear_priv; 163 bpf_program_clear_priv_t clear_priv;
164}; 164};
165 165
166struct bpf_map {
167 int fd;
168 char *name;
169 struct bpf_map_def def;
170 void *priv;
171 bpf_map_clear_priv_t clear_priv;
172};
173
166static LIST_HEAD(bpf_objects_list); 174static LIST_HEAD(bpf_objects_list);
167 175
168struct bpf_object { 176struct bpf_object {
169 char license[64]; 177 char license[64];
170 u32 kern_version; 178 u32 kern_version;
171 void *maps_buf;
172 size_t maps_buf_sz;
173 179
174 struct bpf_program *programs; 180 struct bpf_program *programs;
175 size_t nr_programs; 181 size_t nr_programs;
176 int *map_fds; 182 struct bpf_map *maps;
177 /* 183 size_t nr_maps;
178 * This field is required because maps_buf will be freed and 184
179 * maps_buf_sz will be set to 0 after loaded.
180 */
181 size_t nr_map_fds;
182 bool loaded; 185 bool loaded;
183 186
184 /* 187 /*
@@ -489,30 +492,81 @@ static int
489bpf_object__init_maps(struct bpf_object *obj, void *data, 492bpf_object__init_maps(struct bpf_object *obj, void *data,
490 size_t size) 493 size_t size)
491{ 494{
492 if (size == 0) { 495 size_t nr_maps;
496 int i;
497
498 nr_maps = size / sizeof(struct bpf_map_def);
499 if (!data || !nr_maps) {
493 pr_debug("%s doesn't need map definition\n", 500 pr_debug("%s doesn't need map definition\n",
494 obj->path); 501 obj->path);
495 return 0; 502 return 0;
496 } 503 }
497 504
498 obj->maps_buf = malloc(size); 505 pr_debug("maps in %s: %zd bytes\n", obj->path, size);
499 if (!obj->maps_buf) { 506
500 pr_warning("malloc maps failed: %s\n", obj->path); 507 obj->maps = calloc(nr_maps, sizeof(obj->maps[0]));
508 if (!obj->maps) {
509 pr_warning("alloc maps for object failed\n");
501 return -ENOMEM; 510 return -ENOMEM;
502 } 511 }
512 obj->nr_maps = nr_maps;
503 513
504 obj->maps_buf_sz = size; 514 for (i = 0; i < nr_maps; i++) {
505 memcpy(obj->maps_buf, data, size); 515 struct bpf_map_def *def = &obj->maps[i].def;
506 pr_debug("maps in %s: %ld bytes\n", obj->path, (long)size); 516
517 /*
518 * fill all fd with -1 so won't close incorrect
519 * fd (fd=0 is stdin) when failure (zclose won't close
520 * negative fd)).
521 */
522 obj->maps[i].fd = -1;
523
524 /* Save map definition into obj->maps */
525 *def = ((struct bpf_map_def *)data)[i];
526 }
507 return 0; 527 return 0;
508} 528}
509 529
530static void
531bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
532{
533 int i;
534 Elf_Data *symbols = obj->efile.symbols;
535
536 if (!symbols || maps_shndx < 0)
537 return;
538
539 for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
540 GElf_Sym sym;
541 size_t map_idx;
542 const char *map_name;
543
544 if (!gelf_getsym(symbols, i, &sym))
545 continue;
546 if (sym.st_shndx != maps_shndx)
547 continue;
548
549 map_name = elf_strptr(obj->efile.elf,
550 obj->efile.ehdr.e_shstrndx,
551 sym.st_name);
552 map_idx = sym.st_value / sizeof(struct bpf_map_def);
553 if (map_idx >= obj->nr_maps) {
554 pr_warning("index of map \"%s\" is buggy: %zu > %zu\n",
555 map_name, map_idx, obj->nr_maps);
556 continue;
557 }
558 obj->maps[map_idx].name = strdup(map_name);
559 pr_debug("map %zu is \"%s\"\n", map_idx,
560 obj->maps[map_idx].name);
561 }
562}
563
510static int bpf_object__elf_collect(struct bpf_object *obj) 564static int bpf_object__elf_collect(struct bpf_object *obj)
511{ 565{
512 Elf *elf = obj->efile.elf; 566 Elf *elf = obj->efile.elf;
513 GElf_Ehdr *ep = &obj->efile.ehdr; 567 GElf_Ehdr *ep = &obj->efile.ehdr;
514 Elf_Scn *scn = NULL; 568 Elf_Scn *scn = NULL;
515 int idx = 0, err = 0; 569 int idx = 0, err = 0, maps_shndx = -1;
516 570
517 /* Elf is corrupted/truncated, avoid calling elf_strptr. */ 571 /* Elf is corrupted/truncated, avoid calling elf_strptr. */
518 if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) { 572 if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
@@ -562,10 +616,11 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
562 err = bpf_object__init_kversion(obj, 616 err = bpf_object__init_kversion(obj,
563 data->d_buf, 617 data->d_buf,
564 data->d_size); 618 data->d_size);
565 else if (strcmp(name, "maps") == 0) 619 else if (strcmp(name, "maps") == 0) {
566 err = bpf_object__init_maps(obj, data->d_buf, 620 err = bpf_object__init_maps(obj, data->d_buf,
567 data->d_size); 621 data->d_size);
568 else if (sh.sh_type == SHT_SYMTAB) { 622 maps_shndx = idx;
623 } else if (sh.sh_type == SHT_SYMTAB) {
569 if (obj->efile.symbols) { 624 if (obj->efile.symbols) {
570 pr_warning("bpf: multiple SYMTAB in %s\n", 625 pr_warning("bpf: multiple SYMTAB in %s\n",
571 obj->path); 626 obj->path);
@@ -606,6 +661,9 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
606 if (err) 661 if (err)
607 goto out; 662 goto out;
608 } 663 }
664
665 if (maps_shndx >= 0)
666 bpf_object__init_maps_name(obj, maps_shndx);
609out: 667out:
610 return err; 668 return err;
611} 669}
@@ -688,37 +746,15 @@ static int
688bpf_object__create_maps(struct bpf_object *obj) 746bpf_object__create_maps(struct bpf_object *obj)
689{ 747{
690 unsigned int i; 748 unsigned int i;
691 size_t nr_maps;
692 int *pfd;
693 749
694 nr_maps = obj->maps_buf_sz / sizeof(struct bpf_map_def); 750 for (i = 0; i < obj->nr_maps; i++) {
695 if (!obj->maps_buf || !nr_maps) { 751 struct bpf_map_def *def = &obj->maps[i].def;
696 pr_debug("don't need create maps for %s\n", 752 int *pfd = &obj->maps[i].fd;
697 obj->path);
698 return 0;
699 }
700
701 obj->map_fds = malloc(sizeof(int) * nr_maps);
702 if (!obj->map_fds) {
703 pr_warning("realloc perf_bpf_map_fds failed\n");
704 return -ENOMEM;
705 }
706 obj->nr_map_fds = nr_maps;
707 753
708 /* fill all fd with -1 */ 754 *pfd = bpf_create_map(def->type,
709 memset(obj->map_fds, -1, sizeof(int) * nr_maps); 755 def->key_size,
710 756 def->value_size,
711 pfd = obj->map_fds; 757 def->max_entries);
712 for (i = 0; i < nr_maps; i++) {
713 struct bpf_map_def def;
714
715 def = *(struct bpf_map_def *)(obj->maps_buf +
716 i * sizeof(struct bpf_map_def));
717
718 *pfd = bpf_create_map(def.type,
719 def.key_size,
720 def.value_size,
721 def.max_entries);
722 if (*pfd < 0) { 758 if (*pfd < 0) {
723 size_t j; 759 size_t j;
724 int err = *pfd; 760 int err = *pfd;
@@ -726,22 +762,17 @@ bpf_object__create_maps(struct bpf_object *obj)
726 pr_warning("failed to create map: %s\n", 762 pr_warning("failed to create map: %s\n",
727 strerror(errno)); 763 strerror(errno));
728 for (j = 0; j < i; j++) 764 for (j = 0; j < i; j++)
729 zclose(obj->map_fds[j]); 765 zclose(obj->maps[j].fd);
730 obj->nr_map_fds = 0;
731 zfree(&obj->map_fds);
732 return err; 766 return err;
733 } 767 }
734 pr_debug("create map: fd=%d\n", *pfd); 768 pr_debug("create map: fd=%d\n", *pfd);
735 pfd++;
736 } 769 }
737 770
738 zfree(&obj->maps_buf);
739 obj->maps_buf_sz = 0;
740 return 0; 771 return 0;
741} 772}
742 773
743static int 774static int
744bpf_program__relocate(struct bpf_program *prog, int *map_fds) 775bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj)
745{ 776{
746 int i; 777 int i;
747 778
@@ -761,7 +792,7 @@ bpf_program__relocate(struct bpf_program *prog, int *map_fds)
761 return -LIBBPF_ERRNO__RELOC; 792 return -LIBBPF_ERRNO__RELOC;
762 } 793 }
763 insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD; 794 insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
764 insns[insn_idx].imm = map_fds[map_idx]; 795 insns[insn_idx].imm = obj->maps[map_idx].fd;
765 } 796 }
766 797
767 zfree(&prog->reloc_desc); 798 zfree(&prog->reloc_desc);
@@ -780,7 +811,7 @@ bpf_object__relocate(struct bpf_object *obj)
780 for (i = 0; i < obj->nr_programs; i++) { 811 for (i = 0; i < obj->nr_programs; i++) {
781 prog = &obj->programs[i]; 812 prog = &obj->programs[i];
782 813
783 err = bpf_program__relocate(prog, obj->map_fds); 814 err = bpf_program__relocate(prog, obj);
784 if (err) { 815 if (err) {
785 pr_warning("failed to relocate '%s'\n", 816 pr_warning("failed to relocate '%s'\n",
786 prog->section_name); 817 prog->section_name);
@@ -804,8 +835,7 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
804 Elf_Data *data = obj->efile.reloc[i].data; 835 Elf_Data *data = obj->efile.reloc[i].data;
805 int idx = shdr->sh_info; 836 int idx = shdr->sh_info;
806 struct bpf_program *prog; 837 struct bpf_program *prog;
807 size_t nr_maps = obj->maps_buf_sz / 838 size_t nr_maps = obj->nr_maps;
808 sizeof(struct bpf_map_def);
809 839
810 if (shdr->sh_type != SHT_REL) { 840 if (shdr->sh_type != SHT_REL) {
811 pr_warning("internal error at %d\n", __LINE__); 841 pr_warning("internal error at %d\n", __LINE__);
@@ -1050,10 +1080,8 @@ int bpf_object__unload(struct bpf_object *obj)
1050 if (!obj) 1080 if (!obj)
1051 return -EINVAL; 1081 return -EINVAL;
1052 1082
1053 for (i = 0; i < obj->nr_map_fds; i++) 1083 for (i = 0; i < obj->nr_maps; i++)
1054 zclose(obj->map_fds[i]); 1084 zclose(obj->maps[i].fd);
1055 zfree(&obj->map_fds);
1056 obj->nr_map_fds = 0;
1057 1085
1058 for (i = 0; i < obj->nr_programs; i++) 1086 for (i = 0; i < obj->nr_programs; i++)
1059 bpf_program__unload(&obj->programs[i]); 1087 bpf_program__unload(&obj->programs[i]);
@@ -1096,7 +1124,16 @@ void bpf_object__close(struct bpf_object *obj)
1096 bpf_object__elf_finish(obj); 1124 bpf_object__elf_finish(obj);
1097 bpf_object__unload(obj); 1125 bpf_object__unload(obj);
1098 1126
1099 zfree(&obj->maps_buf); 1127 for (i = 0; i < obj->nr_maps; i++) {
1128 zfree(&obj->maps[i].name);
1129 if (obj->maps[i].clear_priv)
1130 obj->maps[i].clear_priv(&obj->maps[i],
1131 obj->maps[i].priv);
1132 obj->maps[i].priv = NULL;
1133 obj->maps[i].clear_priv = NULL;
1134 }
1135 zfree(&obj->maps);
1136 obj->nr_maps = 0;
1100 1137
1101 if (obj->programs && obj->nr_programs) { 1138 if (obj->programs && obj->nr_programs) {
1102 for (i = 0; i < obj->nr_programs; i++) 1139 for (i = 0; i < obj->nr_programs; i++)
@@ -1251,3 +1288,92 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n)
1251 1288
1252 return fd; 1289 return fd;
1253} 1290}
1291
1292int bpf_map__get_fd(struct bpf_map *map)
1293{
1294 if (!map)
1295 return -EINVAL;
1296
1297 return map->fd;
1298}
1299
1300int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef)
1301{
1302 if (!map || !pdef)
1303 return -EINVAL;
1304
1305 *pdef = map->def;
1306 return 0;
1307}
1308
1309const char *bpf_map__get_name(struct bpf_map *map)
1310{
1311 if (!map)
1312 return NULL;
1313 return map->name;
1314}
1315
1316int bpf_map__set_private(struct bpf_map *map, void *priv,
1317 bpf_map_clear_priv_t clear_priv)
1318{
1319 if (!map)
1320 return -EINVAL;
1321
1322 if (map->priv) {
1323 if (map->clear_priv)
1324 map->clear_priv(map, map->priv);
1325 }
1326
1327 map->priv = priv;
1328 map->clear_priv = clear_priv;
1329 return 0;
1330}
1331
1332int bpf_map__get_private(struct bpf_map *map, void **ppriv)
1333{
1334 if (!map)
1335 return -EINVAL;
1336
1337 if (ppriv)
1338 *ppriv = map->priv;
1339 return 0;
1340}
1341
1342struct bpf_map *
1343bpf_map__next(struct bpf_map *prev, struct bpf_object *obj)
1344{
1345 size_t idx;
1346 struct bpf_map *s, *e;
1347
1348 if (!obj || !obj->maps)
1349 return NULL;
1350
1351 s = obj->maps;
1352 e = obj->maps + obj->nr_maps;
1353
1354 if (prev == NULL)
1355 return s;
1356
1357 if ((prev < s) || (prev >= e)) {
1358 pr_warning("error in %s: map handler doesn't belong to object\n",
1359 __func__);
1360 return NULL;
1361 }
1362
1363 idx = (prev - obj->maps) + 1;
1364 if (idx >= obj->nr_maps)
1365 return NULL;
1366 return &obj->maps[idx];
1367}
1368
1369struct bpf_map *
1370bpf_object__get_map_by_name(struct bpf_object *obj, const char *name)
1371{
1372 struct bpf_map *pos;
1373
1374 bpf_map__for_each(pos, obj) {
1375 if (strcmp(pos->name, name) == 0)
1376 return pos;
1377 }
1378 return NULL;
1379}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 949df4b346cf..a51594c7b518 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -165,4 +165,28 @@ struct bpf_map_def {
165 unsigned int max_entries; 165 unsigned int max_entries;
166}; 166};
167 167
168/*
169 * There is another 'struct bpf_map' in include/linux/map.h. However,
170 * it is not a uapi header so no need to consider name clash.
171 */
172struct bpf_map;
173struct bpf_map *
174bpf_object__get_map_by_name(struct bpf_object *obj, const char *name);
175
176struct bpf_map *
177bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
178#define bpf_map__for_each(pos, obj) \
179 for ((pos) = bpf_map__next(NULL, (obj)); \
180 (pos) != NULL; \
181 (pos) = bpf_map__next((pos), (obj)))
182
183int bpf_map__get_fd(struct bpf_map *map);
184int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef);
185const char *bpf_map__get_name(struct bpf_map *map);
186
187typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
188int bpf_map__set_private(struct bpf_map *map, void *priv,
189 bpf_map_clear_priv_t clear_priv);
190int bpf_map__get_private(struct bpf_map *map, void **ppriv);
191
168#endif 192#endif
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 8a9c6908f54e..af5db885ea9c 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -513,20 +513,26 @@ static int __cmd_report(struct report *rep)
513 if (rep->cpu_list) { 513 if (rep->cpu_list) {
514 ret = perf_session__cpu_bitmap(session, rep->cpu_list, 514 ret = perf_session__cpu_bitmap(session, rep->cpu_list,
515 rep->cpu_bitmap); 515 rep->cpu_bitmap);
516 if (ret) 516 if (ret) {
517 ui__error("failed to set cpu bitmap\n");
517 return ret; 518 return ret;
519 }
518 } 520 }
519 521
520 if (rep->show_threads) 522 if (rep->show_threads)
521 perf_read_values_init(&rep->show_threads_values); 523 perf_read_values_init(&rep->show_threads_values);
522 524
523 ret = report__setup_sample_type(rep); 525 ret = report__setup_sample_type(rep);
524 if (ret) 526 if (ret) {
527 /* report__setup_sample_type() already showed error message */
525 return ret; 528 return ret;
529 }
526 530
527 ret = perf_session__process_events(session); 531 ret = perf_session__process_events(session);
528 if (ret) 532 if (ret) {
533 ui__error("failed to process sample\n");
529 return ret; 534 return ret;
535 }
530 536
531 report__warn_kptr_restrict(rep); 537 report__warn_kptr_restrict(rep);
532 538
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index b2357e8115a2..3cce13b19cbb 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -173,6 +173,11 @@ int test__dwarf_unwind(int subtest __maybe_unused)
173 return -1; 173 return -1;
174 } 174 }
175 175
176 if (machine__create_kernel_maps(machine)) {
177 pr_err("Failed to create kernel maps\n");
178 return -1;
179 }
180
176 callchain_param.record_mode = CALLCHAIN_DWARF; 181 callchain_param.record_mode = CALLCHAIN_DWARF;
177 182
178 if (init_live_machine(machine)) { 183 if (init_live_machine(machine)) {
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a211b7b6a81e..dcdcbafb078b 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -2055,10 +2055,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2055 SLang_reset_tty(); 2055 SLang_reset_tty();
2056 SLang_init_tty(0, 0, 0); 2056 SLang_init_tty(0, 0, 0);
2057 2057
2058 if (min_pcnt) { 2058 if (min_pcnt)
2059 browser->min_pcnt = min_pcnt; 2059 browser->min_pcnt = min_pcnt;
2060 hist_browser__update_nr_entries(browser); 2060 hist_browser__update_nr_entries(browser);
2061 }
2062 2061
2063 browser->pstack = pstack__new(3); 2062 browser->pstack = pstack__new(3);
2064 if (browser->pstack == NULL) 2063 if (browser->pstack == NULL)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 36544e5ece43..540a7efa657e 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -120,7 +120,7 @@ bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused,
120} 120}
121 121
122static int 122static int
123config__exec(const char *value, struct perf_probe_event *pev) 123prog_config__exec(const char *value, struct perf_probe_event *pev)
124{ 124{
125 pev->uprobes = true; 125 pev->uprobes = true;
126 pev->target = strdup(value); 126 pev->target = strdup(value);
@@ -130,7 +130,7 @@ config__exec(const char *value, struct perf_probe_event *pev)
130} 130}
131 131
132static int 132static int
133config__module(const char *value, struct perf_probe_event *pev) 133prog_config__module(const char *value, struct perf_probe_event *pev)
134{ 134{
135 pev->uprobes = false; 135 pev->uprobes = false;
136 pev->target = strdup(value); 136 pev->target = strdup(value);
@@ -140,8 +140,7 @@ config__module(const char *value, struct perf_probe_event *pev)
140} 140}
141 141
142static int 142static int
143config__bool(const char *value, 143prog_config__bool(const char *value, bool *pbool, bool invert)
144 bool *pbool, bool invert)
145{ 144{
146 int err; 145 int err;
147 bool bool_value; 146 bool bool_value;
@@ -158,17 +157,17 @@ config__bool(const char *value,
158} 157}
159 158
160static int 159static int
161config__inlines(const char *value, 160prog_config__inlines(const char *value,
162 struct perf_probe_event *pev __maybe_unused) 161 struct perf_probe_event *pev __maybe_unused)
163{ 162{
164 return config__bool(value, &probe_conf.no_inlines, true); 163 return prog_config__bool(value, &probe_conf.no_inlines, true);
165} 164}
166 165
167static int 166static int
168config__force(const char *value, 167prog_config__force(const char *value,
169 struct perf_probe_event *pev __maybe_unused) 168 struct perf_probe_event *pev __maybe_unused)
170{ 169{
171 return config__bool(value, &probe_conf.force_add, false); 170 return prog_config__bool(value, &probe_conf.force_add, false);
172} 171}
173 172
174static struct { 173static struct {
@@ -176,58 +175,58 @@ static struct {
176 const char *usage; 175 const char *usage;
177 const char *desc; 176 const char *desc;
178 int (*func)(const char *, struct perf_probe_event *); 177 int (*func)(const char *, struct perf_probe_event *);
179} bpf_config_terms[] = { 178} bpf_prog_config_terms[] = {
180 { 179 {
181 .key = "exec", 180 .key = "exec",
182 .usage = "exec=<full path of file>", 181 .usage = "exec=<full path of file>",
183 .desc = "Set uprobe target", 182 .desc = "Set uprobe target",
184 .func = config__exec, 183 .func = prog_config__exec,
185 }, 184 },
186 { 185 {
187 .key = "module", 186 .key = "module",
188 .usage = "module=<module name> ", 187 .usage = "module=<module name> ",
189 .desc = "Set kprobe module", 188 .desc = "Set kprobe module",
190 .func = config__module, 189 .func = prog_config__module,
191 }, 190 },
192 { 191 {
193 .key = "inlines", 192 .key = "inlines",
194 .usage = "inlines=[yes|no] ", 193 .usage = "inlines=[yes|no] ",
195 .desc = "Probe at inline symbol", 194 .desc = "Probe at inline symbol",
196 .func = config__inlines, 195 .func = prog_config__inlines,
197 }, 196 },
198 { 197 {
199 .key = "force", 198 .key = "force",
200 .usage = "force=[yes|no] ", 199 .usage = "force=[yes|no] ",
201 .desc = "Forcibly add events with existing name", 200 .desc = "Forcibly add events with existing name",
202 .func = config__force, 201 .func = prog_config__force,
203 }, 202 },
204}; 203};
205 204
206static int 205static int
207do_config(const char *key, const char *value, 206do_prog_config(const char *key, const char *value,
208 struct perf_probe_event *pev) 207 struct perf_probe_event *pev)
209{ 208{
210 unsigned int i; 209 unsigned int i;
211 210
212 pr_debug("config bpf program: %s=%s\n", key, value); 211 pr_debug("config bpf program: %s=%s\n", key, value);
213 for (i = 0; i < ARRAY_SIZE(bpf_config_terms); i++) 212 for (i = 0; i < ARRAY_SIZE(bpf_prog_config_terms); i++)
214 if (strcmp(key, bpf_config_terms[i].key) == 0) 213 if (strcmp(key, bpf_prog_config_terms[i].key) == 0)
215 return bpf_config_terms[i].func(value, pev); 214 return bpf_prog_config_terms[i].func(value, pev);
216 215
217 pr_debug("BPF: ERROR: invalid config option in object: %s=%s\n", 216 pr_debug("BPF: ERROR: invalid program config option: %s=%s\n",
218 key, value); 217 key, value);
219 218
220 pr_debug("\nHint: Currently valid options are:\n"); 219 pr_debug("\nHint: Valid options are:\n");
221 for (i = 0; i < ARRAY_SIZE(bpf_config_terms); i++) 220 for (i = 0; i < ARRAY_SIZE(bpf_prog_config_terms); i++)
222 pr_debug("\t%s:\t%s\n", bpf_config_terms[i].usage, 221 pr_debug("\t%s:\t%s\n", bpf_prog_config_terms[i].usage,
223 bpf_config_terms[i].desc); 222 bpf_prog_config_terms[i].desc);
224 pr_debug("\n"); 223 pr_debug("\n");
225 224
226 return -BPF_LOADER_ERRNO__CONFIG_TERM; 225 return -BPF_LOADER_ERRNO__PROGCONF_TERM;
227} 226}
228 227
229static const char * 228static const char *
230parse_config_kvpair(const char *config_str, struct perf_probe_event *pev) 229parse_prog_config_kvpair(const char *config_str, struct perf_probe_event *pev)
231{ 230{
232 char *text = strdup(config_str); 231 char *text = strdup(config_str);
233 char *sep, *line; 232 char *sep, *line;
@@ -253,7 +252,7 @@ parse_config_kvpair(const char *config_str, struct perf_probe_event *pev)
253 } 252 }
254 *equ = '\0'; 253 *equ = '\0';
255 254
256 err = do_config(line, equ + 1, pev); 255 err = do_prog_config(line, equ + 1, pev);
257 if (err) 256 if (err)
258 break; 257 break;
259nextline: 258nextline:
@@ -268,10 +267,10 @@ nextline:
268} 267}
269 268
270static int 269static int
271parse_config(const char *config_str, struct perf_probe_event *pev) 270parse_prog_config(const char *config_str, struct perf_probe_event *pev)
272{ 271{
273 int err; 272 int err;
274 const char *main_str = parse_config_kvpair(config_str, pev); 273 const char *main_str = parse_prog_config_kvpair(config_str, pev);
275 274
276 if (IS_ERR(main_str)) 275 if (IS_ERR(main_str))
277 return PTR_ERR(main_str); 276 return PTR_ERR(main_str);
@@ -312,7 +311,7 @@ config_bpf_program(struct bpf_program *prog)
312 pev = &priv->pev; 311 pev = &priv->pev;
313 312
314 pr_debug("bpf: config program '%s'\n", config_str); 313 pr_debug("bpf: config program '%s'\n", config_str);
315 err = parse_config(config_str, pev); 314 err = parse_prog_config(config_str, pev);
316 if (err) 315 if (err)
317 goto errout; 316 goto errout;
318 317
@@ -750,7 +749,7 @@ static const char *bpf_loader_strerror_table[NR_ERRNO] = {
750 [ERRCODE_OFFSET(EVENTNAME)] = "No event name found in config string", 749 [ERRCODE_OFFSET(EVENTNAME)] = "No event name found in config string",
751 [ERRCODE_OFFSET(INTERNAL)] = "BPF loader internal error", 750 [ERRCODE_OFFSET(INTERNAL)] = "BPF loader internal error",
752 [ERRCODE_OFFSET(COMPILE)] = "Error when compiling BPF scriptlet", 751 [ERRCODE_OFFSET(COMPILE)] = "Error when compiling BPF scriptlet",
753 [ERRCODE_OFFSET(CONFIG_TERM)] = "Invalid config term in config string", 752 [ERRCODE_OFFSET(PROGCONF_TERM)] = "Invalid program config term in config string",
754 [ERRCODE_OFFSET(PROLOGUE)] = "Failed to generate prologue", 753 [ERRCODE_OFFSET(PROLOGUE)] = "Failed to generate prologue",
755 [ERRCODE_OFFSET(PROLOGUE2BIG)] = "Prologue too big for program", 754 [ERRCODE_OFFSET(PROLOGUE2BIG)] = "Prologue too big for program",
756 [ERRCODE_OFFSET(PROLOGUEOOB)] = "Offset out of bound for prologue", 755 [ERRCODE_OFFSET(PROLOGUEOOB)] = "Offset out of bound for prologue",
@@ -834,7 +833,7 @@ int bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
834 int err, char *buf, size_t size) 833 int err, char *buf, size_t size)
835{ 834{
836 bpf__strerror_head(err, buf, size); 835 bpf__strerror_head(err, buf, size);
837 case BPF_LOADER_ERRNO__CONFIG_TERM: { 836 case BPF_LOADER_ERRNO__PROGCONF_TERM: {
838 scnprintf(buf, size, "%s (add -v to see detail)", emsg); 837 scnprintf(buf, size, "%s (add -v to see detail)", emsg);
839 break; 838 break;
840 } 839 }
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index a58740b0f31e..6fdc0457e2b6 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -20,7 +20,7 @@ enum bpf_loader_errno {
20 BPF_LOADER_ERRNO__EVENTNAME, /* Event name is missing */ 20 BPF_LOADER_ERRNO__EVENTNAME, /* Event name is missing */
21 BPF_LOADER_ERRNO__INTERNAL, /* BPF loader internal error */ 21 BPF_LOADER_ERRNO__INTERNAL, /* BPF loader internal error */
22 BPF_LOADER_ERRNO__COMPILE, /* Error when compiling BPF scriptlet */ 22 BPF_LOADER_ERRNO__COMPILE, /* Error when compiling BPF scriptlet */
23 BPF_LOADER_ERRNO__CONFIG_TERM, /* Invalid config term in config term */ 23 BPF_LOADER_ERRNO__PROGCONF_TERM,/* Invalid program config term in config string */
24 BPF_LOADER_ERRNO__PROLOGUE, /* Failed to generate prologue */ 24 BPF_LOADER_ERRNO__PROLOGUE, /* Failed to generate prologue */
25 BPF_LOADER_ERRNO__PROLOGUE2BIG, /* Prologue too big for program */ 25 BPF_LOADER_ERRNO__PROLOGUE2BIG, /* Prologue too big for program */
26 BPF_LOADER_ERRNO__PROLOGUEOOB, /* Offset out of bound for prologue */ 26 BPF_LOADER_ERRNO__PROLOGUEOOB, /* Offset out of bound for prologue */
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 217b5a60e2ab..6a7e273a514a 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -91,7 +91,7 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
91 bid += 2; 91 bid += 2;
92 } 92 }
93 93
94 return raw - build_id; 94 return (bid - bf) + 1;
95} 95}
96 96
97int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id) 97int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 4fd37d6708cb..6e8e0ee9ec37 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -924,9 +924,6 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
924 int64_t cmp = 0; 924 int64_t cmp = 0;
925 925
926 perf_hpp__for_each_sort_list(fmt) { 926 perf_hpp__for_each_sort_list(fmt) {
927 if (perf_hpp__should_skip(fmt))
928 continue;
929
930 cmp = fmt->cmp(fmt, left, right); 927 cmp = fmt->cmp(fmt, left, right);
931 if (cmp) 928 if (cmp)
932 break; 929 break;
@@ -942,9 +939,6 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
942 int64_t cmp = 0; 939 int64_t cmp = 0;
943 940
944 perf_hpp__for_each_sort_list(fmt) { 941 perf_hpp__for_each_sort_list(fmt) {
945 if (perf_hpp__should_skip(fmt))
946 continue;
947
948 cmp = fmt->collapse(fmt, left, right); 942 cmp = fmt->collapse(fmt, left, right);
949 if (cmp) 943 if (cmp)
950 break; 944 break;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index e48d9da75707..6fc8cd753e1a 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -124,6 +124,10 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
124 .symbol = "dummy", 124 .symbol = "dummy",
125 .alias = "", 125 .alias = "",
126 }, 126 },
127 [PERF_COUNT_SW_BPF_OUTPUT] = {
128 .symbol = "bpf-output",
129 .alias = "",
130 },
127}; 131};
128 132
129#define __PERF_EVENT_FIELD(config, name) \ 133#define __PERF_EVENT_FIELD(config, name) \
@@ -1879,7 +1883,7 @@ restart:
1879 1883
1880 for (i = 0; i < max; i++, syms++) { 1884 for (i = 0; i < max; i++, syms++) {
1881 1885
1882 if (event_glob != NULL && 1886 if (event_glob != NULL && syms->symbol != NULL &&
1883 !(strglobmatch(syms->symbol, event_glob) || 1887 !(strglobmatch(syms->symbol, event_glob) ||
1884 (syms->alias && strglobmatch(syms->alias, event_glob)))) 1888 (syms->alias && strglobmatch(syms->alias, event_glob))))
1885 continue; 1889 continue;