Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1286157 > unrolled thread
| Started by | Wang Nan <wangnan0@huawei.com> |
|---|---|
| First post | 2015-12-08 03:30 +0100 |
| Last post | 2015-12-08 03:40 +0100 |
| Articles | 20 on this page of 28 — 6 participants |
Back to article view | Back to linux.kernel
[PATCH v4 00/16] perf tools: BPF related update and other improvements Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
[PATCH v4 01/16] tools lib bpf: Check return value of strdup when reading map names Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
[tip:perf/core] tools lib bpf: Check return value of strdup when reading map names tip-bot for Wang Nan <tipbot@zytor.com> - 2015-12-14 09:40 +0100
[PATCH v4 07/16] perf tools: Enable passing event to BPF object Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
[PATCH v4 12/16] perf data: Support converting data from bpf_perf_event_output() Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
[PATCH v4 14/16] perf record: Support custom vmlinux path Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
[PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-12-11 13:20 +0100
Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-12-11 13:20 +0100
Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-12-11 13:50 +0100
Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps pi3orama <pi3orama@163.com> - 2015-12-11 14:00 +0100
Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps pi3orama <pi3orama@163.com> - 2015-12-11 13:50 +0100
Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps Alexei Starovoitov <alexei.starovoitov@gmail.com> - 2015-12-11 19:30 +0100
Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps "Wangnan (F)" <wangnan0@huawei.com> - 2015-12-14 04:30 +0100
Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps Alexei Starovoitov <alexei.starovoitov@gmail.com> - 2015-12-14 05:30 +0100
Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps "Wangnan (F)" <wangnan0@huawei.com> - 2015-12-14 05:50 +0100
Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps Alexei Starovoitov <alexei.starovoitov@gmail.com> - 2015-12-14 07:00 +0100
[PATCH v4 13/16] perf tools: Always give options even it not compiled Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:30 +0100
Re: [PATCH v4 13/16] perf tools: Always give options even it not compiled Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-12-11 13:50 +0100
[PATCH v4 15/16] perf script: Add support for PERF_TYPE_BREAKPOINT Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:40 +0100
[tip:perf/core] perf script: Add support for PERF_TYPE_BREAKPOINT tip-bot for Wang Nan <tipbot@zytor.com> - 2015-12-14 09:40 +0100
[PATCH v4 06/16] perf tools: Support perf event alias name Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:40 +0100
Re: [PATCH v4 06/16] perf tools: Support perf event alias name Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-12-11 13:10 +0100
Re: [PATCH v4 06/16] perf tools: Support perf event alias name pi3orama <pi3orama@163.com> - 2015-12-11 13:20 +0100
[PATCH v4 02/16] tools lib bpf: Fetch map names from correct strtab Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:40 +0100
[tip:perf/core] tools lib bpf: Fetch map names from correct strtab tip-bot for Wang Nan <tipbot@zytor.com> - 2015-12-14 09:40 +0100
[PATCH v4 05/16] perf record: Apply config to BPF objects before recording Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:40 +0100
[PATCH v4 04/16] perf tools: Enable BPF object configure syntax Wang Nan <wangnan0@huawei.com> - 2015-12-08 03:40 +0100
Page 1 of 2 [1] 2 Next page →
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-12-08 03:30 +0100 |
| Subject | [PATCH v4 00/16] perf tools: BPF related update and other improvements |
| Message-ID | <qDgcp-4Bz-3@gated-at.bofh.it> |
Hi Arnaldo, Glad to see you start processing patches again. This patch set contains all BPF related patches and two other patches in my local tree. I have rebased them onto your newest perf/core. Please review them when you have time. This patch set is based on perf/core. Compare with v3: - Rebase on newest perf/core - Small commit message improvements - Fetch map names from correct strtab (2/16) - Patch 15-16 are not related to BPF. Send them together because they stay in my local tree for sereval days. He Kuang (2): perf tools: Support perf event alias name perf record: Support custom vmlinux path Wang Nan (14): tools lib bpf: Check return value of strdup when reading map names tools lib bpf: Fetch map names from correct strtab perf tools: Add API to config maps in bpf object perf tools: Enable BPF object configure syntax perf record: Apply config to BPF objects before recording perf tools: Enable passing event to BPF object perf tools: Support setting different slots in a BPF map separately perf tools: Enable indices setting syntax for BPF maps perf tools: Introduce bpf-output event perf data: Add u32_hex data type perf data: Support converting data from bpf_perf_event_output() perf tools: Always give options even it not compiled perf script: Add support for PERF_TYPE_BREAKPOINT perf tools: Clear struct machine during machine__init() tools/lib/bpf/libbpf.c | 24 +- tools/perf/Documentation/perf-record.txt | 10 +- tools/perf/builtin-probe.c | 15 +- tools/perf/builtin-record.c | 36 +- tools/perf/builtin-script.c | 14 + tools/perf/util/bpf-loader.c | 700 +++++++++++++++++++++++++++++++ tools/perf/util/bpf-loader.h | 59 +++ tools/perf/util/data-convert-bt.c | 117 +++++- tools/perf/util/evlist.c | 16 + tools/perf/util/evlist.h | 4 + tools/perf/util/evsel.c | 7 + tools/perf/util/evsel.h | 1 + tools/perf/util/machine.c | 1 + tools/perf/util/parse-events.c | 125 +++++- tools/perf/util/parse-events.h | 20 +- tools/perf/util/parse-events.l | 16 +- tools/perf/util/parse-events.y | 123 +++++- tools/perf/util/parse-options.c | 113 ++++- tools/perf/util/parse-options.h | 5 + 19 files changed, 1369 insertions(+), 37 deletions(-) -- 1.8.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-12-08 03:30 +0100 |
| Subject | [PATCH v4 01/16] tools lib bpf: Check return value of strdup when reading map names |
| Message-ID | <qDgcq-4Bz-19@gated-at.bofh.it> |
| In reply to | #1286157 |
Commit 561bbccac72d08babafaa33fd7fa9100ec4c9fb6 ("tools lib bpf:
Extract and collect map names from BPF object file") forgets checking
return value of strdup(). This patch fixes it. It also checks names
pointer before strcmp() for safty.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/lib/bpf/libbpf.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index a298614..16485ab 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -527,14 +527,14 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
return 0;
}
-static void
+static int
bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
{
int i;
Elf_Data *symbols = obj->efile.symbols;
if (!symbols || maps_shndx < 0)
- return;
+ return -EINVAL;
for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
GElf_Sym sym;
@@ -556,9 +556,14 @@ bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
continue;
}
obj->maps[map_idx].name = strdup(map_name);
+ if (!obj->maps[map_idx].name) {
+ pr_warning("failed to alloc map name\n");
+ return -ENOMEM;
+ }
pr_debug("map %zu is \"%s\"\n", map_idx,
obj->maps[map_idx].name);
}
+ return 0;
}
static int bpf_object__elf_collect(struct bpf_object *obj)
@@ -663,7 +668,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
}
if (maps_shndx >= 0)
- bpf_object__init_maps_name(obj, maps_shndx);
+ err = bpf_object__init_maps_name(obj, maps_shndx);
out:
return err;
}
@@ -1372,7 +1377,7 @@ bpf_object__get_map_by_name(struct bpf_object *obj, const char *name)
struct bpf_map *pos;
bpf_map__for_each(pos, obj) {
- if (strcmp(pos->name, name) == 0)
+ if (pos->name && !strcmp(pos->name, name))
return pos;
}
return NULL;
--
1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Wang Nan <tipbot@zytor.com> |
|---|---|
| Date | 2015-12-14 09:40 +0100 |
| Subject | [tip:perf/core] tools lib bpf: Check return value of strdup when reading map names |
| Message-ID | <qFwPM-3DO-11@gated-at.bofh.it> |
| In reply to | #1286158 |
Commit-ID: 973170e66726672518eb935eb0dc0e63876d133d
Gitweb: http://git.kernel.org/tip/973170e66726672518eb935eb0dc0e63876d133d
Author: Wang Nan <wangnan0@huawei.com>
AuthorDate: Tue, 8 Dec 2015 02:25:29 +0000
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 11 Dec 2015 08:51:09 -0300
tools lib bpf: Check return value of strdup when reading map names
Commit 561bbccac72d08babafaa33fd7fa9100ec4c9fb6 ("tools lib bpf:
Extract and collect map names from BPF object file") forgets checking
return value of strdup(). This patch fixes it. It also checks names
pointer before strcmp() for safety.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Fixes: 561bbccac72d ("tools lib bpf: Extract and collect map names from BPF object file")
Link: http://lkml.kernel.org/r/1449541544-67621-2-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/lib/bpf/libbpf.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index a298614..16485ab 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -527,14 +527,14 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
return 0;
}
-static void
+static int
bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
{
int i;
Elf_Data *symbols = obj->efile.symbols;
if (!symbols || maps_shndx < 0)
- return;
+ return -EINVAL;
for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
GElf_Sym sym;
@@ -556,9 +556,14 @@ bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
continue;
}
obj->maps[map_idx].name = strdup(map_name);
+ if (!obj->maps[map_idx].name) {
+ pr_warning("failed to alloc map name\n");
+ return -ENOMEM;
+ }
pr_debug("map %zu is \"%s\"\n", map_idx,
obj->maps[map_idx].name);
}
+ return 0;
}
static int bpf_object__elf_collect(struct bpf_object *obj)
@@ -663,7 +668,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
}
if (maps_shndx >= 0)
- bpf_object__init_maps_name(obj, maps_shndx);
+ err = bpf_object__init_maps_name(obj, maps_shndx);
out:
return err;
}
@@ -1372,7 +1377,7 @@ bpf_object__get_map_by_name(struct bpf_object *obj, const char *name)
struct bpf_map *pos;
bpf_map__for_each(pos, obj) {
- if (strcmp(pos->name, name) == 0)
+ if (pos->name && !strcmp(pos->name, name))
return pos;
}
return NULL;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-12-08 03:30 +0100 |
| Subject | [PATCH v4 07/16] perf tools: Enable passing event to BPF object |
| Message-ID | <qDgcq-4Bz-23@gated-at.bofh.it> |
| In reply to | #1286157 |
A new syntax is appended into parser so user can pass predefined perf
events into BPF objects.
After this patch, BPF programs for perf are finally able to utilize
bpf_perf_event_read() introduced in commit 35578d7984003097af2b1e3
(bpf: Implement function bpf_perf_event_read() that get the selected
hardware PMU conuter).
Test result:
# cat ./test_bpf_map_2.c
/************************ BEGIN **************************/
#define SEC(NAME) __attribute__((section(NAME), used))
enum bpf_map_type {
BPF_MAP_TYPE_PERF_EVENT_ARRAY = 4,
};
struct bpf_map_def {
unsigned int type;
unsigned int key_size;
unsigned int value_size;
unsigned int max_entries;
};
static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
(void *)1;
static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
(void *)6;
static int (*bpf_get_smp_processor_id)(void) =
(void *)8;
static int (*bpf_perf_event_read)(struct bpf_map_def *, int) =
(void *)22;
struct bpf_map_def SEC("maps") pmu_map = {
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(int),
.max_entries = __NR_CPUS__,
};
SEC("func_write=sys_write")
int func_write(void *ctx)
{
unsigned long long val;
char fmt[] = "sys_write: pmu=%llu\n";
val = bpf_perf_event_read(&pmu_map, bpf_get_smp_processor_id());
bpf_trace_printk(fmt, sizeof(fmt), val);
return 0;
}
SEC("func_write_return=sys_write%return")
int func_write_return(void *ctx)
{
unsigned long long val = 0;
char fmt[] = "sys_write_return: pmu=%llu\n";
val = bpf_perf_event_read(&pmu_map, bpf_get_smp_processor_id());
bpf_trace_printk(fmt, sizeof(fmt), val);
return 0;
}
char _license[] SEC("license") = "GPL";
int _version SEC("version") = LINUX_VERSION_CODE;
/************************* END ***************************/
Normal case 1:
# echo "" > /sys/kernel/debug/tracing/trace
# ./perf record -e evt=cycles/no-inherit/ -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' ls /
[SNIP]
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.013 MB perf.data (7 samples) ]
# cat /sys/kernel/debug/tracing/trace | grep ls
ls-13865 [006] d... 2722740.933204: : sys_write: pmu=1121685
ls-13865 [006] dN.. 2722740.933242: : sys_write_return: pmu=1178149
ls-13865 [006] d... 2722740.933248: : sys_write: pmu=1194986
ls-13865 [006] dN.. 2722740.933270: : sys_write_return: pmu=1220862
Normal case 2:
# echo "" > /sys/kernel/debug/tracing/trace
# ./perf record -e evt=cycles/period=0x7fffffffffffffff,no-inherit/ \
-e './test_bpf_map_2.c/maps:pmu_map.event=evt/' ls /
[SNIP]
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.013 MB perf.data ]
# ./perf report --stdio
Error:
The perf.data file has no samples!
(This is expected because we set period of cycles to a very large
value to period of cycles event because we want to use this event
as a counter only, don't need sampling)
# cat /sys/kernel/debug/tracing/trace | grep ls
ls-14446 [006] d... 2722976.486458: : sys_write: pmu=1116233
ls-14446 [006] dN.. 2722976.486486: : sys_write_return: pmu=1162108
ls-14446 [006] d... 2722976.486491: : sys_write: pmu=1177122
ls-14446 [006] dN.. 2722976.486511: : sys_write_return: pmu=1202417
Normal case 3:
# echo "" > /sys/kernel/debug/tracing/trace
# ./perf record -i -e cycles -e './test_bpf_map_2.c/maps:pmu_map.event=cycles/' ls /
(When doesn't explicitly set alias, event name can be used to search events)
[SNIP]
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.013 MB perf.data (7 samples) ]
# cat /sys/kernel/debug/tracing/trace | grep ls
ls-16480 [005] d... 2724143.955040: : sys_write: pmu=1150794
ls-16480 [005] dN.. 2724143.955077: : sys_write_return: pmu=1207161
ls-16480 [005] d... 2724143.955083: : sys_write: pmu=1219145
ls-16480 [005] dN.. 2724143.955104: : sys_write_return: pmu=1245433
Normal case 4 (one thread case):
# ls /proc/11808/task/
11808
# echo "" > /sys/kernel/debug/tracing/trace
# ./perf record -e evt=cycles/no-inherit/ -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' -p 11808
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.019 MB perf.data (2 samples) ]
# cat /sys/kernel/debug/tracing/trace | grep 11808
sshd-11808 [000] d... 2740454.781150: : sys_write: pmu=18446744073709551594
sshd-11808 [000] d... 2740454.781168: : sys_write_return: pmu=18446744073709551594
sshd-11808 [003] d... 2740467.411799: : sys_write: pmu=131031
sshd-11808 [003] dN.. 2740467.411806: : sys_write_return: pmu=161549
sshd-11808 [003] d... 2740467.411834: : sys_write: pmu=210269
Normal case 5 (system wide):
# echo "" > /sys/kernel/debug/tracing/trace
# ./perf record -e evt=cycles/no-inherit/ -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' -a
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.811 MB perf.data (120 samples) ]
# cat /sys/kernel/debug/tracing/trace | grep -v '18446744073709551594' | grep -v perf | head -n 20
[SNIP]
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
gmain-30828 [002] d... 2740551.068992: : sys_write: pmu=84373
gmain-30828 [002] d... 2740551.068992: : sys_write_return: pmu=87696
gmain-30828 [002] d... 2740551.068996: : sys_write: pmu=100658
gmain-30828 [002] d... 2740551.068997: : sys_write_return: pmu=102572
Error case 1:
# ./perf record -e './test_bpf_map_2.c' ls /
[SNIP]
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.014 MB perf.data ]
# cat /sys/kernel/debug/tracing/trace | grep ls
ls-17115 [007] d... 2724279.665625: : sys_write: pmu=18446744073709551614
ls-17115 [007] dN.. 2724279.665651: : sys_write_return: pmu=18446744073709551614
ls-17115 [007] d... 2724279.665658: : sys_write: pmu=18446744073709551614
ls-17115 [007] dN.. 2724279.665677: : sys_write_return: pmu=18446744073709551614
(18446744073709551614 is 0xfffffffffffffffe (-2))
Error case 2:
# ./perf record -e cycles -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' -a
event syntax error: '..ps:pmu_map.event=evt/'
\___ Event not found for map setting
Hint: Valid config terms:
maps:[<arraymap>].value=[value]
maps:[<eventmap>].event=[event]
[SNIP]
Error case 3:
# ls /proc/2342/task/
2342 2373 2374 2375 2376
# ./perf record -e evt=cycles/no-inherit/ -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' -p 2342
ERROR: Apply config to BPF failed: Cannot set event to BPF maps in multi-thread tracing
Error case 4:
# ./perf record -e cycles -e './test_bpf_map_2.c/maps:pmu_map.event=cycles/' ls /
ERROR: Apply config to BPF failed: Doesn't support inherit event (Hint: use /no-inherit/ config term or use -i)
Error case 5:
# ./perf record -e evt=raw_syscalls:sys_enter/no-inherit/ -e './test_bpf_map_2.c/maps:pmu_map.event=evt/' ls
ERROR: Apply config to BPF failed: Can only put raw, hardware and BPF output event into a BPF map
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
tools/perf/util/bpf-loader.c | 138 ++++++++++++++++++++++++++++++++++++++++-
tools/perf/util/bpf-loader.h | 5 ++
tools/perf/util/parse-events.c | 4 +-
3 files changed, 145 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 96fd18b..97f5efc 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -742,6 +742,7 @@ int bpf__foreach_tev(struct bpf_object *obj,
enum bpf_map_op_type {
BPF_MAP_OP_SET_VALUE,
+ BPF_MAP_OP_SET_EVSEL,
};
enum bpf_map_key_type {
@@ -754,6 +755,7 @@ struct bpf_map_op {
enum bpf_map_key_type key_type;
union {
u64 value;
+ struct perf_evsel *evsel;
} v;
};
@@ -891,10 +893,73 @@ bpf__obj_config_map_value(struct bpf_map *map,
if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
return bpf__obj_config_map_array_value(map, term);
- pr_debug("ERROR: wrong value type\n");
+ pr_debug("ERROR: wrong value type for 'value'\n");
return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE;
}
+static int
+bpf__obj_config_map_array_event(struct bpf_map *map,
+ struct parse_events_term *term,
+ struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel;
+ struct bpf_map_def def;
+ struct bpf_map_op *op;
+ const char *map_name;
+ int err;
+
+ map_name = bpf_map__get_name(map);
+ evsel = perf_evlist__find_evsel_by_alias(evlist, term->val.str);
+ if (!evsel) {
+ pr_debug("Event (for '%s') '%s' doesn't exist\n",
+ map_name, term->val.str);
+ return -BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT;
+ }
+
+ err = bpf_map__get_def(map, &def);
+ if (err) {
+ pr_debug("Unable to get map definition from '%s'\n",
+ map_name);
+ return err;
+ }
+
+ /*
+ * No need to check key_size and value_size:
+ * kernel has already checked them.
+ */
+ if (def.type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) {
+ pr_debug("Map %s type is not BPF_MAP_TYPE_PERF_EVENT_ARRAY\n",
+ map_name);
+ return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
+ }
+
+ op = bpf_map_op__alloc(map);
+ if (IS_ERR(op))
+ return PTR_ERR(op);
+
+ op->v.evsel = evsel;
+ op->op_type = BPF_MAP_OP_SET_EVSEL;
+ return 0;
+}
+
+static int
+bpf__obj_config_map_event(struct bpf_map *map,
+ struct parse_events_term *term,
+ struct perf_evlist *evlist)
+{
+ if (!term->err_val) {
+ pr_debug("Config value not set\n");
+ return -BPF_LOADER_ERRNO__OBJCONF_CONF;
+ }
+
+ if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
+ return bpf__obj_config_map_array_event(map, term, evlist);
+
+ pr_debug("ERROR: wrong value type for 'event'\n");
+ return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE;
+}
+
+
struct bpf_obj_config_map_func {
const char *config_opt;
int (*config_func)(struct bpf_map *, struct parse_events_term *,
@@ -903,6 +968,7 @@ struct bpf_obj_config_map_func {
struct bpf_obj_config_map_func bpf_obj_config_map_funcs[] = {
{"value", bpf__obj_config_map_value},
+ {"event", bpf__obj_config_map_event},
};
static int
@@ -1047,6 +1113,7 @@ bpf_map_config_foreach_key(struct bpf_map *map,
list_for_each_entry(op, &priv->ops_list, list) {
switch (def.type) {
case BPF_MAP_TYPE_ARRAY:
+ case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
switch (op->key_type) {
case BPF_MAP_KEY_ALL:
return foreach_key_array_all(func, arg, name,
@@ -1101,6 +1168,60 @@ apply_config_value_for_key(int map_fd, void *pkey,
}
static int
+apply_config_evsel_for_key(const char *name, int map_fd, void *pkey,
+ struct perf_evsel *evsel)
+{
+ struct xyarray *xy = evsel->fd;
+ struct perf_event_attr *attr;
+ unsigned int key, events;
+ bool check_pass = false;
+ int *evt_fd;
+ int err;
+
+ if (!xy) {
+ pr_debug("ERROR: evsel not ready for map %s\n", name);
+ return -BPF_LOADER_ERRNO__INTERNAL;
+ }
+
+ if (xy->row_size / xy->entry_size != 1) {
+ pr_debug("ERROR: Dimension of target event is incorrect for map %s\n",
+ name);
+ return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM;
+ }
+
+ attr = &evsel->attr;
+ if (attr->inherit) {
+ pr_debug("ERROR: Can't put inherit event into map %s\n", name);
+ return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH;
+ }
+
+ if (attr->type == PERF_TYPE_RAW)
+ check_pass = true;
+ if (attr->type == PERF_TYPE_HARDWARE)
+ check_pass = true;
+ if (attr->type == PERF_TYPE_SOFTWARE &&
+ attr->config == PERF_COUNT_SW_BPF_OUTPUT)
+ check_pass = true;
+ if (!check_pass) {
+ pr_debug("ERROR: Event type is wrong for map %s\n", name);
+ return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE;
+ }
+
+ events = xy->entries / (xy->row_size / xy->entry_size);
+ key = *((unsigned int *)pkey);
+ if (key >= events) {
+ pr_debug("ERROR: there is no event %d for map %s\n",
+ key, name);
+ return -BPF_LOADER_ERRNO__OBJCONF_MAP_MAPSIZE;
+ }
+ evt_fd = xyarray__entry(xy, key, 0);
+ err = bpf_map_update_elem(map_fd, pkey, evt_fd, BPF_ANY);
+ if (err && errno)
+ err = -errno;
+ return err;
+}
+
+static int
apply_obj_config_map_for_key(const char *name, int map_fd,
struct bpf_map_def *pdef __maybe_unused,
struct bpf_map_op *op,
@@ -1114,6 +1235,10 @@ apply_obj_config_map_for_key(const char *name, int map_fd,
pdef->value_size,
op->v.value);
break;
+ case BPF_MAP_OP_SET_EVSEL:
+ err = apply_config_evsel_for_key(name, map_fd, pkey,
+ op->v.evsel);
+ break;
default:
pr_debug("ERROR: unknown value type for '%s'\n", name);
err = -BPF_LOADER_ERRNO__INTERNAL;
@@ -1179,6 +1304,11 @@ static const char *bpf_loader_strerror_table[NR_ERRNO] = {
[ERRCODE_OFFSET(OBJCONF_MAP_TYPE)] = "Incorrect map type",
[ERRCODE_OFFSET(OBJCONF_MAP_KEYSIZE)] = "Incorrect map key size",
[ERRCODE_OFFSET(OBJCONF_MAP_VALUESIZE)] = "Incorrect map value size",
+ [ERRCODE_OFFSET(OBJCONF_MAP_NOEVT)] = "Event not found for map setting",
+ [ERRCODE_OFFSET(OBJCONF_MAP_MAPSIZE)] = "Invalid map size for event setting",
+ [ERRCODE_OFFSET(OBJCONF_MAP_EVTDIM)] = "Event dimension too large",
+ [ERRCODE_OFFSET(OBJCONF_MAP_EVTINH)] = "Doesn't support inherit event",
+ [ERRCODE_OFFSET(OBJCONF_MAP_EVTTYPE)] = "Wrong event type for map",
};
static int
@@ -1315,6 +1445,12 @@ int bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused,
int bpf__strerror_apply_obj_config(int err, char *buf, size_t size)
{
bpf__strerror_head(err, buf, size);
+ bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM,
+ "Cannot set event to BPF maps in multi-thread tracing");
+ bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH,
+ "%s (Hint: use /no-inherit/ config term or use -i)", emsg);
+ bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE,
+ "Can only put raw, hardware and BPF output event into a BPF map");
bpf__strerror_end(buf, size);
return 0;
}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index db3c34c..c9ce792 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -33,6 +33,11 @@ enum bpf_loader_errno {
BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE, /* Incorrect map type */
BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE, /* Incorrect map key size */
BPF_LOADER_ERRNO__OBJCONF_MAP_VALUESIZE,/* Incorrect map value size */
+ BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT, /* Event not found for map setting */
+ BPF_LOADER_ERRNO__OBJCONF_MAP_MAPSIZE, /* Invalid map size for event setting */
+ BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM, /* Event dimension too large */
+ BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH, /* Doesn't support inherit event */
+ BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE, /* Wrong event type for map */
__BPF_LOADER_ERRNO__END,
};
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 484c8e4..5d682dd 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -659,8 +659,10 @@ parse_events_config_bpf(struct parse_events_evlist *data,
&error_pos, err, errbuf,
sizeof(errbuf));
data->error->help = strdup(
-"Hint:\tValid config term:\n"
+"Hint:\tValid config terms:\n"
" \tmaps:[<arraymap>].value=[value]\n"
+" \tmaps:[<eventmap>].event=[event]\n"
+"\n"
" \t(add -v to see detail)");
data->error->str = strdup(errbuf);
if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
--
1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-12-08 03:30 +0100 |
| Subject | [PATCH v4 12/16] perf data: Support converting data from bpf_perf_event_output() |
| Message-ID | <qDgcq-4Bz-25@gated-at.bofh.it> |
| In reply to | #1286157 |
bpf_perf_event_output() outputs data through sample->raw_data. This
patch adds support to convert those data into CTF. A python script
then can be used to process output data from BPF programs.
Test result:
# cat ./test_bpf_output.c
/************************ BEGIN **************************/
typedef int u32;
typedef unsigned long long u64;
enum bpf_map_type {
BPF_MAP_TYPE_PERF_EVENT_ARRAY = 4,
};
struct bpf_map_def {
unsigned int type;
unsigned int key_size;
unsigned int value_size;
unsigned int max_entries;
};
#define SEC(NAME) __attribute__((section(NAME), used))
static u64 (*bpf_ktime_get_ns)(void) =
(void *)5;
static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
(void *)6;
static int (*bpf_get_smp_processor_id)(void) =
(void *)8;
static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int, void *, unsigned long) =
(void *)23;
struct bpf_map_def SEC("maps") channel = {
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(u32),
.max_entries = __NR_CPUS__,
};
static inline int __attribute__((always_inline))
func(void *ctx, int type)
{
struct {
u64 ktime;
int type;
} __attribute__((packed)) output_data;
char error_data[] = "Error: failed to output\n";
int err;
output_data.type = type;
output_data.ktime = bpf_ktime_get_ns();
err = bpf_perf_event_output(ctx, &channel, bpf_get_smp_processor_id(),
&output_data, sizeof(output_data));
if (err)
bpf_trace_printk(error_data, sizeof(error_data));
return 0;
}
SEC("func_begin=sys_nanosleep")
int func_begin(void *ctx) {return func(ctx, 1);}
SEC("func_end=sys_nanosleep%return")
int func_end(void *ctx) { return func(ctx, 2);}
char _license[] SEC("license") = "GPL";
int _version SEC("version") = LINUX_VERSION_CODE;
/************************ END ***************************/
# ./perf record -e evt=bpf-output/no-inherit/ \
-e ./test_bpf_output_2.c/maps:channel.event=evt/ \
usleep 100000
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.012 MB perf.data (2 samples) ]
# ./perf script
usleep 14942 92503.198504: evt=bpf-output/no-inherit/: ffffffff810e0ba1 sys_nanosleep (/lib/modules/4.3.0....
usleep 14942 92503.298562: evt=bpf-output/no-inherit/: ffffffff810585e9 kretprobe_trampoline_holder (/lib....
# ./perf data convert --to-ctf ./out.ctf
[ perf data convert: Converted 'perf.data' into CTF data './out.ctf' ]
[ perf data convert: Converted and wrote 0.000 MB (2 samples) ]
# babeltrace ./out.ctf
[01:41:43.198504134] (+?.?????????) evt=bpf-output/no-inherit/: { cpu_id = 0 }, { perf_ip = 0xFFFFFFFF810E0BA1, perf_tid = 14942, perf_pid = 14942, perf_id = 1044, raw_len = 3, raw_data = [ [0] = 0x32C0C07B, [1] = 0x5421, [2] = 0x1 ] }
[01:41:43.298562257] (+0.100058123) evt=bpf-output/no-inherit/: { cpu_id = 0 }, { perf_ip = 0xFFFFFFFF810585E9, perf_tid = 14942, perf_pid = 14942, perf_id = 1044, raw_len = 3, raw_data = [ [0] = 0x38B77FAA, [1] = 0x5421, [2] = 0x2 ] }
# cat ./test_bpf_output_2.py
from babeltrace import TraceCollection
tc = TraceCollection(
tc.add_trace('./out.ctf', 'ctf')
d = {1:[], 2:[]}
for event in tc.events:
if not event.name.startswith('evt=bpf-output/no-inherit/'):
continue
raw_data = event['raw_data']
(time, type) = ((raw_data[0] + (raw_data[1] << 32)), raw_data[2])
d[type].append(time)
print(list(map(lambda i: d[2][i] - d[1][i], range(len(d[1]))))));
# python3 ./test_bpf_output_2.py
[100056879]
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
tools/perf/util/data-convert-bt.c | 115 +++++++++++++++++++++++++++++++++++++-
1 file changed, 114 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 34cd1e4..1fb472b 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -352,6 +352,84 @@ static int add_tracepoint_values(struct ctf_writer *cw,
return ret;
}
+static int
+add_bpf_output_values(struct bt_ctf_event_class *event_class,
+ struct bt_ctf_event *event,
+ struct perf_sample *sample)
+{
+ struct bt_ctf_field_type *len_type, *seq_type;
+ struct bt_ctf_field *len_field, *seq_field;
+ unsigned int raw_size = sample->raw_size;
+ unsigned int nr_elements = raw_size / sizeof(u32);
+ unsigned int i;
+ int ret;
+
+ if (nr_elements * sizeof(u32) != raw_size)
+ pr_warning("Incorrect raw_size (%u) in bpf output event, skip %lu bytes\n",
+ raw_size, nr_elements * sizeof(u32) - raw_size);
+
+ len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
+ len_field = bt_ctf_field_create(len_type);
+ if (!len_field) {
+ pr_err("failed to create 'raw_len' for bpf output event\n");
+ ret = -1;
+ goto put_len_type;
+ }
+
+ ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
+ if (ret) {
+ pr_err("failed to set field value for raw_len\n");
+ goto put_len_field;
+ }
+ ret = bt_ctf_event_set_payload(event, "raw_len", len_field);
+ if (ret) {
+ pr_err("failed to set payload to raw_len\n");
+ goto put_len_field;
+ }
+
+ seq_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_data");
+ seq_field = bt_ctf_field_create(seq_type);
+ if (!seq_field) {
+ pr_err("failed to create 'raw_data' for bpf output event\n");
+ ret = -1;
+ goto put_seq_type;
+ }
+
+ ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
+ if (ret) {
+ pr_err("failed to set length of 'raw_data'\n");
+ goto put_seq_field;
+ }
+
+ for (i = 0; i < nr_elements; i++) {
+ struct bt_ctf_field *elem_field =
+ bt_ctf_field_sequence_get_field(seq_field, i);
+
+ ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
+ ((u32 *)(sample->raw_data))[i]);
+
+ bt_ctf_field_put(elem_field);
+ if (ret) {
+ pr_err("failed to set raw_data[%d]\n", i);
+ goto put_seq_field;
+ }
+ }
+
+ ret = bt_ctf_event_set_payload(event, "raw_data", seq_field);
+ if (ret)
+ pr_err("failed to set payload for raw_data\n");
+
+put_seq_field:
+ bt_ctf_field_put(seq_field);
+put_seq_type:
+ bt_ctf_field_type_put(seq_type);
+put_len_field:
+ bt_ctf_field_put(len_field);
+put_len_type:
+ bt_ctf_field_type_put(len_type);
+ return ret;
+}
+
static int add_generic_values(struct ctf_writer *cw,
struct bt_ctf_event *event,
struct perf_evsel *evsel,
@@ -597,6 +675,13 @@ static int process_sample_event(struct perf_tool *tool,
return -1;
}
+ if ((evsel->attr.type == PERF_TYPE_SOFTWARE) &&
+ (evsel->attr.config == PERF_COUNT_SW_BPF_OUTPUT)) {
+ ret = add_bpf_output_values(event_class, event, sample);
+ if (ret)
+ return -1;
+ }
+
cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel));
if (cs) {
if (is_flush_needed(cs))
@@ -744,6 +829,25 @@ static int add_tracepoint_types(struct ctf_writer *cw,
return ret;
}
+static int add_bpf_output_types(struct ctf_writer *cw,
+ struct bt_ctf_event_class *class)
+{
+ struct bt_ctf_field_type *len_type = cw->data.u32;
+ struct bt_ctf_field_type *seq_base_type = cw->data.u32_hex;
+ struct bt_ctf_field_type *seq_type;
+ int ret;
+
+ ret = bt_ctf_event_class_add_field(class, len_type, "raw_len");
+ if (ret)
+ return ret;
+
+ seq_type = bt_ctf_field_type_sequence_create(seq_base_type, "raw_len");
+ if (!seq_type)
+ return -1;
+
+ return bt_ctf_event_class_add_field(class, seq_type, "raw_data");
+}
+
static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
struct bt_ctf_event_class *event_class)
{
@@ -755,7 +859,8 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
* ctf event header
* PERF_SAMPLE_READ - TODO
* PERF_SAMPLE_CALLCHAIN - TODO
- * PERF_SAMPLE_RAW - tracepoint fields are handled separately
+ * PERF_SAMPLE_RAW - tracepoint fields and BPF output
+ * are handled separately
* PERF_SAMPLE_BRANCH_STACK - TODO
* PERF_SAMPLE_REGS_USER - TODO
* PERF_SAMPLE_STACK_USER - TODO
@@ -824,6 +929,14 @@ static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
goto err;
}
+ if ((evsel->attr.type == PERF_TYPE_SOFTWARE) &&
+ (evsel->attr.config == PERF_COUNT_SW_BPF_OUTPUT)) {
+ ret = add_bpf_output_types(cw, event_class);
+ if (ret)
+ goto err;
+
+ }
+
ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
if (ret) {
pr("Failed to add event class into stream.\n");
--
1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-12-08 03:30 +0100 |
| Subject | [PATCH v4 14/16] perf record: Support custom vmlinux path |
| Message-ID | <qDgcq-4Bz-27@gated-at.bofh.it> |
| In reply to | #1286157 |
From: He Kuang <hekuang@huawei.com>
Make perf-record command support --vmlinux option if BPF_PROLOGUE is on.
'perf record' needs vmlinux as the source of DWARF info to generate
prologue for BPF programs, so path of vmlinux should be specified.
Short name 'k' has been taken by 'clockid'. This patch skips the short
option name and use '--vmlinux' for vmlinux path.
Documentation is also updated.
Test result:
In a production (or broken) environment:
(built by
# rm -rf ~/.debug/
# mv /lib/modules/`uname -r`/build/vmlinux /tmp/
)
# ./perf record -e ./test_bpf_base.c ls
Failed to find the path for kernel: No such file or directory
event syntax error: './test_bpf_base.c'
\___ You need to check probing points in BPF file
...
# ./perf record --vmlinux /tmp/vmlinux -e ./test_bpf_base.c ls
...
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.011 MB perf.data ]
Help messages when build with NO_LIBBPF:
# ./perf record -h
--transaction sample transaction flags (special events only)
--vmlinux <file> vmlinux pathname
(not build because NO_LIBBPF=1)
# ./perf record --vmlinux /tmp/vmlinux ls /
Warning: option `vmlinux' is not built because NO_LIBBPF=1
...
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.011 MB perf.data (11 samples) ]
Help messages when build with NO_DWARF:
# ./perf record -h
--transaction sample transaction flags (special events only)
--vmlinux <file> vmlinux pathname
(not build because NO_DWARF=1)
Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
tools/perf/Documentation/perf-record.txt | 10 ++++++++--
tools/perf/builtin-record.c | 16 ++++++++++++++++
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index e630a7d..8d032f4 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -314,11 +314,17 @@ This option sets the time out limit. The default value is 500 ms.
Record context switch events i.e. events of type PERF_RECORD_SWITCH or
PERF_RECORD_SWITCH_CPU_WIDE.
---clang-path::
+--clang-path=PATH::
Path to clang binary to use for compiling BPF scriptlets.
+(enabled when BPF support is on)
---clang-opt::
+--clang-opt=OPTIONS::
Options passed to clang when compiling BPF scriptlets.
+(enabled when BPF support is on)
+
+--vmlinux=PATH::
+Specify vmlinux path which has debuginfo.
+(enabled when BPF prologue is on)
SEE ALSO
--------
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 11bf32d..2230b85 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1128,6 +1128,8 @@ struct option __record_options[] = {
"clang binary to use for compiling BPF scriptlets"),
OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
"options passed to clang when compiling BPF scriptlets"),
+ OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
+ "file", "vmlinux pathname"),
OPT_END()
};
@@ -1146,6 +1148,20 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
# undef set_nobuild
#endif
+#ifndef HAVE_BPF_PROLOGUE
+# if !defined (HAVE_DWARF_SUPPORT)
+# define REASON "NO_DWARF=1"
+# elif !defined (HAVE_LIBBPF_SUPPORT)
+# define REASON "NO_LIBBPF=1"
+# else
+# define REASON "this architecture doesn't support BPF prologue"
+# endif
+# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
+ set_nobuild('\0', "vmlinux", true);
+# undef set_nobuild
+# undef REASON
+#endif
+
rec->evlist = perf_evlist__new();
if (rec->evlist == NULL)
return -ENOMEM;
--
1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-12-08 03:30 +0100 |
| Subject | [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps |
| Message-ID | <qDgcq-4Bz-31@gated-at.bofh.it> |
| In reply to | #1286157 |
This patch introduce a new syntax to perf event parser:
# perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...
By utilizing the basic facilities in bpf-loader.c which allow setting
different slots in a BPF map separately, the newly introduced syntax
allows perf to control specific elements in a BPF map.
Test result:
# cat ./test_bpf_map_3.c
/************************ BEGIN **************************/
#define SEC(NAME) __attribute__((section(NAME), used))
enum bpf_map_type {
BPF_MAP_TYPE_ARRAY = 2,
};
struct bpf_map_def {
unsigned int type;
unsigned int key_size;
unsigned int value_size;
unsigned int max_entries;
};
static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
(void *)1;
static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
(void *)6;
struct bpf_map_def SEC("maps") channel = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(unsigned char),
.max_entries = 100,
};
SEC("func=hrtimer_nanosleep rqtp->tv_nsec")
int func(void *ctx, int err, long nsec)
{
char fmt[] = "%ld\n";
long usec = nsec * 0x10624dd3 >> 38; // nsec / 1000
int key = (int)usec;
unsigned char *pval = map_lookup_elem(&channel, &key);
if (!pval)
return 0;
bpf_trace_printk(fmt, sizeof(fmt), (unsigned char)*pval);
return 0;
}
char _license[] SEC("license") = "GPL";
int _version SEC("version") = LINUX_VERSION_CODE;
/************************* END ***************************/
Normal case:
# echo "" > /sys/kernel/debug/tracing/trace
# ./perf record -e './test_bpf_map_3.c/maps:channel.value[0,1,2,3...5]=101/' usleep 2
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.012 MB perf.data ]
# cat /sys/kernel/debug/tracing/trace | grep usleep
usleep-405 [004] d... 2745423.547822: : 101
# ./perf record -e './test_bpf_map_3.c/maps:channel.value[0...9,20...29]=102,maps:channel.value[10...19]=103/' usleep 3
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.012 MB perf.data ]
# ./perf record -e './test_bpf_map_3.c/maps:channel.value[0...9,20...29]=102,maps:channel.value[10...19]=103/' usleep 15
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.012 MB perf.data ]
# cat /sys/kernel/debug/tracing/trace | grep usleep
usleep-405 [004] d... 2745423.547822: : 101
usleep-655 [006] d... 2745434.122814: : 102
usleep-904 [006] d... 2745439.916264: : 103
# ./perf record -e './test_bpf_map_3.c/maps:channel.value[all]=104/' usleep 99
# cat /sys/kernel/debug/tracing/trace | grep usleep
usleep-405 [004] d... 2745423.547822: : 101
usleep-655 [006] d... 2745434.122814: : 102
usleep-904 [006] d... 2745439.916264: : 103
usleep-1537 [003] d... 2745538.053737: : 104
Error case:
# ./perf record -e './test_bpf_map_3.c/maps:channel.value[10...1000]=104/' usleep 99
event syntax error: '..annel.value[10...1000]=104/'
\___ Index too large
Hint: Valid config terms:
maps:[<arraymap>].value<indices>=[value]
maps:[<eventmap>].event<indices>=[event]
where <indices> is something like [0,3...5] or [all]
(add -v to see detail)
Run 'perf list' for a list of valid events
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
-e, --event <event> event selector. use 'perf list' to list available events
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
tools/perf/util/parse-events.c | 5 ++-
tools/perf/util/parse-events.l | 13 ++++++-
tools/perf/util/parse-events.y | 85 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 100 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index af3d657..abdf551 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -660,9 +660,10 @@ parse_events_config_bpf(struct parse_events_evlist *data,
sizeof(errbuf));
data->error->help = strdup(
"Hint:\tValid config terms:\n"
-" \tmaps:[<arraymap>].value=[value]\n"
-" \tmaps:[<eventmap>].event=[event]\n"
+" \tmaps:[<arraymap>].value<indices>=[value]\n"
+" \tmaps:[<eventmap>].event<indices>=[event]\n"
"\n"
+" \twhere <indices> is something like [0,3...5] or [all]\n"
" \t(add -v to see detail)");
data->error->str = strdup(errbuf);
if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 4387728..8bb3437 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -9,8 +9,8 @@
%{
#include <errno.h>
#include "../perf.h"
-#include "parse-events-bison.h"
#include "parse-events.h"
+#include "parse-events-bison.h"
char *parse_events_get_text(yyscan_t yyscanner);
YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
@@ -111,6 +111,7 @@ do { \
%x mem
%s config
%x event
+%x array
group [^,{}/]*[{][^}]*[}][^,{}/]*
event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
@@ -176,6 +177,14 @@ modifier_bp [rwx]{1,3}
}
+<array>{
+"]" { BEGIN(config); return ']'; }
+{num_dec} { return value(yyscanner, 10); }
+{num_hex} { return value(yyscanner, 16); }
+, { return ','; }
+"\.\.\." { return PE_ARRAY_RANGE; }
+}
+
<config>{
/*
* Please update parse_events_formats_error_string any time
@@ -196,6 +205,8 @@ no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
, { return ','; }
"/" { BEGIN(INITIAL); return '/'; }
{name_minus} { return str(yyscanner, PE_NAME); }
+\[all\] { return PE_ARRAY_ALL; }
+"[" { BEGIN(array); return '['; }
}
<mem>{
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index c3cbd7a..7e93b9f 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -48,6 +48,7 @@ static inc_group_count(struct list_head *list,
%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
%token PE_ERROR
%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
+%token PE_ARRAY_ALL PE_ARRAY_RANGE
%type <num> PE_VALUE
%type <num> PE_VALUE_SYM_HW
%type <num> PE_VALUE_SYM_SW
@@ -84,6 +85,9 @@ static inc_group_count(struct list_head *list,
%type <head> group_def
%type <head> group
%type <head> groups
+%type <array> array
+%type <array> array_term
+%type <array> array_terms
%union
{
@@ -95,6 +99,7 @@ static inc_group_count(struct list_head *list,
char *sys;
char *event;
} tracepoint_name;
+ struct parse_events_array array;
}
%%
@@ -601,6 +606,86 @@ PE_TERM
ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL));
$$ = term;
}
+|
+PE_NAME array '=' PE_NAME
+{
+ struct parse_events_term *term;
+ int i;
+
+ ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
+ $1, $4, &@1, &@4));
+
+ term->array = $2;
+ $$ = term;
+}
+|
+PE_NAME array '=' PE_VALUE
+{
+ struct parse_events_term *term;
+
+ ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
+ $1, $4, &@1, &@4));
+ term->array = $2;
+ $$ = term;
+}
+
+array:
+'[' array_terms ']'
+{
+ $$ = $2;
+}
+|
+PE_ARRAY_ALL
+{
+ $$.nr_ranges = 0;
+ $$.ranges = NULL;
+}
+
+array_terms:
+array_terms ',' array_term
+{
+ struct parse_events_array new_array;
+
+ new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges;
+ new_array.ranges = malloc(sizeof(new_array.ranges[0]) *
+ new_array.nr_ranges);
+ ABORT_ON(!new_array.ranges);
+ memcpy(&new_array.ranges[0], $1.ranges,
+ $1.nr_ranges * sizeof(new_array.ranges[0]));
+ memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges,
+ $3.nr_ranges * sizeof(new_array.ranges[0]));
+ free($1.ranges);
+ free($3.ranges);
+ $$ = new_array;
+}
+|
+array_term
+
+array_term:
+PE_VALUE
+{
+ struct parse_events_array array;
+
+ array.nr_ranges = 1;
+ array.ranges = malloc(sizeof(array.ranges[0]));
+ ABORT_ON(!array.ranges);
+ array.ranges[0].start = $1;
+ array.ranges[0].length = 1;
+ $$ = array;
+}
+|
+PE_VALUE PE_ARRAY_RANGE PE_VALUE
+{
+ struct parse_events_array array;
+
+ ABORT_ON($3 < $1);
+ array.nr_ranges = 1;
+ array.ranges = malloc(sizeof(array.ranges[0]));
+ ABORT_ON(!array.ranges);
+ array.ranges[0].start = $1;
+ array.ranges[0].length = $3 - $1 + 1;
+ $$ = array;
+}
sep_dc: ':' |
--
1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2015-12-11 13:20 +0100 |
| Subject | Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps |
| Message-ID | <qEuQ2-486-11@gated-at.bofh.it> |
| In reply to | #1286162 |
Em Tue, Dec 08, 2015 at 02:25:37AM +0000, Wang Nan escreveu:
> This patch introduce a new syntax to perf event parser:
>
> # perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...
Is the above example valid? Wouldn't this be "maps:mymap.value" ?
>
> By utilizing the basic facilities in bpf-loader.c which allow setting
> different slots in a BPF map separately, the newly introduced syntax
> allows perf to control specific elements in a BPF map.
>
> Test result:
>
> # cat ./test_bpf_map_3.c
> /************************ BEGIN **************************/
> #define SEC(NAME) __attribute__((section(NAME), used))
> enum bpf_map_type {
> BPF_MAP_TYPE_ARRAY = 2,
> };
> struct bpf_map_def {
> unsigned int type;
> unsigned int key_size;
> unsigned int value_size;
> unsigned int max_entries;
> };
> static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
> (void *)1;
> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
> (void *)6;
Can you explain the above a bit more? What are the magic 1 and 6 values?
> struct bpf_map_def SEC("maps") channel = {
> .type = BPF_MAP_TYPE_ARRAY,
> .key_size = sizeof(int),
> .value_size = sizeof(unsigned char),
> .max_entries = 100,
> };
> SEC("func=hrtimer_nanosleep rqtp->tv_nsec")
> int func(void *ctx, int err, long nsec)
> {
> char fmt[] = "%ld\n";
> long usec = nsec * 0x10624dd3 >> 38; // nsec / 1000
> int key = (int)usec;
> unsigned char *pval = map_lookup_elem(&channel, &key);
So that "mymap.value" name doesn't needs to be specified here?
>
> if (!pval)
> return 0;
> bpf_trace_printk(fmt, sizeof(fmt), (unsigned char)*pval);
> return 0;
> }
> char _license[] SEC("license") = "GPL";
> int _version SEC("version") = LINUX_VERSION_CODE;
> /************************* END ***************************/
>
> Normal case:
> # echo "" > /sys/kernel/debug/tracing/trace
> # ./perf record -e './test_bpf_map_3.c/maps:channel.value[0,1,2,3...5]=101/' usleep 2
> [ perf record: Woken up 1 times to write data ]
> [ perf record: Captured and wrote 0.012 MB perf.data ]
> # cat /sys/kernel/debug/tracing/trace | grep usleep
> usleep-405 [004] d... 2745423.547822: : 101
> # ./perf record -e './test_bpf_map_3.c/maps:channel.value[0...9,20...29]=102,maps:channel.value[10...19]=103/' usleep 3
> [ perf record: Woken up 1 times to write data ]
> [ perf record: Captured and wrote 0.012 MB perf.data ]
> # ./perf record -e './test_bpf_map_3.c/maps:channel.value[0...9,20...29]=102,maps:channel.value[10...19]=103/' usleep 15
> [ perf record: Woken up 1 times to write data ]
> [ perf record: Captured and wrote 0.012 MB perf.data ]
> # cat /sys/kernel/debug/tracing/trace | grep usleep
> usleep-405 [004] d... 2745423.547822: : 101
> usleep-655 [006] d... 2745434.122814: : 102
> usleep-904 [006] d... 2745439.916264: : 103
> # ./perf record -e './test_bpf_map_3.c/maps:channel.value[all]=104/' usleep 99
> # cat /sys/kernel/debug/tracing/trace | grep usleep
> usleep-405 [004] d... 2745423.547822: : 101
> usleep-655 [006] d... 2745434.122814: : 102
> usleep-904 [006] d... 2745439.916264: : 103
> usleep-1537 [003] d... 2745538.053737: : 104
>
> Error case:
> # ./perf record -e './test_bpf_map_3.c/maps:channel.value[10...1000]=104/' usleep 99
> event syntax error: '..annel.value[10...1000]=104/'
> \___ Index too large
> Hint: Valid config terms:
> maps:[<arraymap>].value<indices>=[value]
> maps:[<eventmap>].event<indices>=[event]
>
> where <indices> is something like [0,3...5] or [all]
> (add -v to see detail)
> Run 'perf list' for a list of valid events
>
> Usage: perf record [<options>] [<command>]
> or: perf record [<options>] -- <command> [<options>]
>
> -e, --event <event> event selector. use 'perf list' to list available events
>
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Zefan Li <lizefan@huawei.com>
> Cc: pi3orama@163.com
> ---
> tools/perf/util/parse-events.c | 5 ++-
> tools/perf/util/parse-events.l | 13 ++++++-
> tools/perf/util/parse-events.y | 85 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 100 insertions(+), 3 deletions(-)
>
> diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
> index af3d657..abdf551 100644
> --- a/tools/perf/util/parse-events.c
> +++ b/tools/perf/util/parse-events.c
> @@ -660,9 +660,10 @@ parse_events_config_bpf(struct parse_events_evlist *data,
> sizeof(errbuf));
> data->error->help = strdup(
> "Hint:\tValid config terms:\n"
> -" \tmaps:[<arraymap>].value=[value]\n"
> -" \tmaps:[<eventmap>].event=[event]\n"
> +" \tmaps:[<arraymap>].value<indices>=[value]\n"
> +" \tmaps:[<eventmap>].event<indices>=[event]\n"
> "\n"
> +" \twhere <indices> is something like [0,3...5] or [all]\n"
> " \t(add -v to see detail)");
> data->error->str = strdup(errbuf);
> if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
> diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
> index 4387728..8bb3437 100644
> --- a/tools/perf/util/parse-events.l
> +++ b/tools/perf/util/parse-events.l
> @@ -9,8 +9,8 @@
> %{
> #include <errno.h>
> #include "../perf.h"
> -#include "parse-events-bison.h"
> #include "parse-events.h"
> +#include "parse-events-bison.h"
>
> char *parse_events_get_text(yyscan_t yyscanner);
> YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
> @@ -111,6 +111,7 @@ do { \
> %x mem
> %s config
> %x event
> +%x array
>
> group [^,{}/]*[{][^}]*[}][^,{}/]*
> event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
> @@ -176,6 +177,14 @@ modifier_bp [rwx]{1,3}
>
> }
>
> +<array>{
> +"]" { BEGIN(config); return ']'; }
> +{num_dec} { return value(yyscanner, 10); }
> +{num_hex} { return value(yyscanner, 16); }
> +, { return ','; }
> +"\.\.\." { return PE_ARRAY_RANGE; }
> +}
> +
> <config>{
> /*
> * Please update parse_events_formats_error_string any time
> @@ -196,6 +205,8 @@ no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
> , { return ','; }
> "/" { BEGIN(INITIAL); return '/'; }
> {name_minus} { return str(yyscanner, PE_NAME); }
> +\[all\] { return PE_ARRAY_ALL; }
> +"[" { BEGIN(array); return '['; }
> }
>
> <mem>{
> diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
> index c3cbd7a..7e93b9f 100644
> --- a/tools/perf/util/parse-events.y
> +++ b/tools/perf/util/parse-events.y
> @@ -48,6 +48,7 @@ static inc_group_count(struct list_head *list,
> %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
> %token PE_ERROR
> %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
> +%token PE_ARRAY_ALL PE_ARRAY_RANGE
> %type <num> PE_VALUE
> %type <num> PE_VALUE_SYM_HW
> %type <num> PE_VALUE_SYM_SW
> @@ -84,6 +85,9 @@ static inc_group_count(struct list_head *list,
> %type <head> group_def
> %type <head> group
> %type <head> groups
> +%type <array> array
> +%type <array> array_term
> +%type <array> array_terms
>
> %union
> {
> @@ -95,6 +99,7 @@ static inc_group_count(struct list_head *list,
> char *sys;
> char *event;
> } tracepoint_name;
> + struct parse_events_array array;
> }
> %%
>
> @@ -601,6 +606,86 @@ PE_TERM
> ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL));
> $$ = term;
> }
> +|
> +PE_NAME array '=' PE_NAME
> +{
> + struct parse_events_term *term;
> + int i;
> +
> + ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
> + $1, $4, &@1, &@4));
> +
> + term->array = $2;
> + $$ = term;
> +}
> +|
> +PE_NAME array '=' PE_VALUE
> +{
> + struct parse_events_term *term;
> +
> + ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
> + $1, $4, &@1, &@4));
> + term->array = $2;
> + $$ = term;
> +}
> +
> +array:
> +'[' array_terms ']'
> +{
> + $$ = $2;
> +}
> +|
> +PE_ARRAY_ALL
> +{
> + $$.nr_ranges = 0;
> + $$.ranges = NULL;
> +}
> +
> +array_terms:
> +array_terms ',' array_term
> +{
> + struct parse_events_array new_array;
> +
> + new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges;
> + new_array.ranges = malloc(sizeof(new_array.ranges[0]) *
> + new_array.nr_ranges);
> + ABORT_ON(!new_array.ranges);
> + memcpy(&new_array.ranges[0], $1.ranges,
> + $1.nr_ranges * sizeof(new_array.ranges[0]));
> + memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges,
> + $3.nr_ranges * sizeof(new_array.ranges[0]));
> + free($1.ranges);
> + free($3.ranges);
> + $$ = new_array;
> +}
> +|
> +array_term
> +
> +array_term:
> +PE_VALUE
> +{
> + struct parse_events_array array;
> +
> + array.nr_ranges = 1;
> + array.ranges = malloc(sizeof(array.ranges[0]));
> + ABORT_ON(!array.ranges);
> + array.ranges[0].start = $1;
> + array.ranges[0].length = 1;
> + $$ = array;
> +}
> +|
> +PE_VALUE PE_ARRAY_RANGE PE_VALUE
> +{
> + struct parse_events_array array;
> +
> + ABORT_ON($3 < $1);
> + array.nr_ranges = 1;
> + array.ranges = malloc(sizeof(array.ranges[0]));
> + ABORT_ON(!array.ranges);
> + array.ranges[0].start = $1;
> + array.ranges[0].length = $3 - $1 + 1;
> + $$ = array;
> +}
>
> sep_dc: ':' |
>
> --
> 1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2015-12-11 13:20 +0100 |
| Subject | Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps |
| Message-ID | <qEuQ3-486-31@gated-at.bofh.it> |
| In reply to | #1289512 |
Em Fri, Dec 11, 2015 at 09:11:45AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Tue, Dec 08, 2015 at 02:25:37AM +0000, Wang Nan escreveu:
> > This patch introduce a new syntax to perf event parser:
> >
> > # perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...
>
> Is the above example valid? Wouldn't this be "maps:mymap.value" ?
>
> >
> > By utilizing the basic facilities in bpf-loader.c which allow setting
> > different slots in a BPF map separately, the newly introduced syntax
> > allows perf to control specific elements in a BPF map.
> >
> > Test result:
> >
> > # cat ./test_bpf_map_3.c
> > /************************ BEGIN **************************/
> > #define SEC(NAME) __attribute__((section(NAME), used))
> > enum bpf_map_type {
> > BPF_MAP_TYPE_ARRAY = 2,
> > };
> > struct bpf_map_def {
> > unsigned int type;
> > unsigned int key_size;
> > unsigned int value_size;
> > unsigned int max_entries;
> > };
> > static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
> > (void *)1;
> > static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
> > (void *)6;
>
> Can you explain the above a bit more? What are the magic 1 and 6 values?
So, from another patch:
static u64 (*bpf_ktime_get_ns)(void) =
(void *)5;
static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
(void *)6;
static int (*bpf_get_smp_processor_id)(void) =
(void *)8;
static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
void *, unsigned long) =
(void *)23;
Where can I get this magical mistery table? Could this be hidden away in
some .h file automagically included in bpf scriptlets so that n00bies
like me don't have to be wtf'ing?
- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2015-12-11 13:50 +0100 |
| Subject | Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps |
| Message-ID | <qEvj4-4o4-9@gated-at.bofh.it> |
| In reply to | #1289515 |
Em Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama escreveu:
>
>
> 发自我的 iPhone
>
> > 在 2015年12月11日,下午8:15,Arnaldo Carvalho de Melo <acme@kernel.org> 写道:
> >
> > Em Fri, Dec 11, 2015 at 09:11:45AM -0300, Arnaldo Carvalho de Melo escreveu:
> >> Em Tue, Dec 08, 2015 at 02:25:37AM +0000, Wang Nan escreveu:
> >>> This patch introduce a new syntax to perf event parser:
> >>>
> >>> # perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...
> >>
> >> Is the above example valid? Wouldn't this be "maps:mymap.value" ?
> >>
> >>>
> >>> By utilizing the basic facilities in bpf-loader.c which allow setting
> >>> different slots in a BPF map separately, the newly introduced syntax
> >>> allows perf to control specific elements in a BPF map.
> >>>
> >>> Test result:
> >>>
> >>> # cat ./test_bpf_map_3.c
> >>> /************************ BEGIN **************************/
> >>> #define SEC(NAME) __attribute__((section(NAME), used))
> >>> enum bpf_map_type {
> >>> BPF_MAP_TYPE_ARRAY = 2,
> >>> };
> >>> struct bpf_map_def {
> >>> unsigned int type;
> >>> unsigned int key_size;
> >>> unsigned int value_size;
> >>> unsigned int max_entries;
> >>> };
> >>> static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
> >>> (void *)1;
> >>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
> >>> (void *)6;
> >>
> >> Can you explain the above a bit more? What are the magic 1 and 6 values?
> >
> > So, from another patch:
> >
> > static u64 (*bpf_ktime_get_ns)(void) =
> > (void *)5;
> > static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
> > (void *)6;
> > static int (*bpf_get_smp_processor_id)(void) =
> > (void *)8;
> > static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
> > void *, unsigned long) =
> > (void *)23;
> >
> > Where can I get this magical mistery table? Could this be hidden away in
> > some .h file automagically included in bpf scriptlets so that n00bies
> > like me don't have to be wtf'ing?
> >
>
> They are function numbers defined in bpf.h and bpf-common.h, but they are Linux
> headers. Directly include them causes many error for llvm. Also, the function
> prototypes are BPF specific and can't included in Linux source. We should have
> a place holds those indices and prototypes together.
Sure, just please don't assume whoever is reading your patches has this
background, provide comments above such places, so that reviewing gets
facilitated.
I eventually figured this is some sort of trampoline to access kernel
functions:
/* integer value in 'imm' field of BPF_CALL instruction selects which
* helper function eBPF program intends to call
*/
enum bpf_func_id {
BPF_FUNC_unspec,
BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */
BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */
BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */
BPF_FUNC_probe_read, /* int bpf_probe_read(void *dst, int size, void *src) */
But if you had just:
/*
* See enum_bpf_func_id in ./include/uapi/linux/bpf.h
*/
That would've helped.
- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | pi3orama <pi3orama@163.com> |
|---|---|
| Date | 2015-12-11 14:00 +0100 |
| Subject | Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps |
| Message-ID | <qEvsL-4sJ-35@gated-at.bofh.it> |
| In reply to | #1289528 |
发自我的 iPhone
> 在 2015年12月11日,下午8:47,Arnaldo Carvalho de Melo <acme@kernel.org> 写道:
>
> Em Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama escreveu:
>>
>>
>> 发自我的 iPhone
>>
>>> 在 2015年12月11日,下午8:15,Arnaldo Carvalho de Melo <acme@kernel.org> 写道:
>>>
>>> Em Fri, Dec 11, 2015 at 09:11:45AM -0300, Arnaldo Carvalho de Melo escreveu:
>>>> Em Tue, Dec 08, 2015 at 02:25:37AM +0000, Wang Nan escreveu:
>>>>> This patch introduce a new syntax to perf event parser:
>>>>>
>>>>> # perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...
>>>>
>>>> Is the above example valid? Wouldn't this be "maps:mymap.value" ?
>>>>
>>>>>
>>>>> By utilizing the basic facilities in bpf-loader.c which allow setting
>>>>> different slots in a BPF map separately, the newly introduced syntax
>>>>> allows perf to control specific elements in a BPF map.
>>>>>
>>>>> Test result:
>>>>>
>>>>> # cat ./test_bpf_map_3.c
>>>>> /************************ BEGIN **************************/
>>>>> #define SEC(NAME) __attribute__((section(NAME), used))
>>>>> enum bpf_map_type {
>>>>> BPF_MAP_TYPE_ARRAY = 2,
>>>>> };
>>>>> struct bpf_map_def {
>>>>> unsigned int type;
>>>>> unsigned int key_size;
>>>>> unsigned int value_size;
>>>>> unsigned int max_entries;
>>>>> };
>>>>> static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
>>>>> (void *)1;
>>>>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
>>>>> (void *)6;
>>>>
>>>> Can you explain the above a bit more? What are the magic 1 and 6 values?
>>>
>>> So, from another patch:
>>>
>>> static u64 (*bpf_ktime_get_ns)(void) =
>>> (void *)5;
>>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
>>> (void *)6;
>>> static int (*bpf_get_smp_processor_id)(void) =
>>> (void *)8;
>>> static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
>>> void *, unsigned long) =
>>> (void *)23;
>>>
>>> Where can I get this magical mistery table? Could this be hidden away in
>>> some .h file automagically included in bpf scriptlets so that n00bies
>>> like me don't have to be wtf'ing?
>>
>> They are function numbers defined in bpf.h and bpf-common.h, but they are Linux
>> headers. Directly include them causes many error for llvm. Also, the function
>> prototypes are BPF specific and can't included in Linux source. We should have
>> a place holds those indices and prototypes together.
>
> Sure, just please don't assume whoever is reading your patches has this
> background, provide comments above such places, so that reviewing gets
> facilitated.
>
> I eventually figured this is some sort of trampoline to access kernel
> functions:
>
> /* integer value in 'imm' field of BPF_CALL instruction selects which
> * helper function eBPF program intends to call
> */
> enum bpf_func_id {
> BPF_FUNC_unspec,
> BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */
> BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */
> BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */
> BPF_FUNC_probe_read, /* int bpf_probe_read(void *dst, int size, void *src) */
>
>
> But if you had just:
>
> /*
> * See enum_bpf_func_id in ./include/uapi/linux/bpf.h
> */
>
> That would've helped.
>
Thank you, but I think this is a good chance to setup the policy about the header
files for BPF. I suggested to put BPF specific headers into Linux kernel include dir,
but we must find a way to avoid Linux includes them. Another useful structure is
pt_regs, however which is not as important as before because we have prologue
now.
I'd like to have a try next week.
Thank you.
> - Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | pi3orama <pi3orama@163.com> |
|---|---|
| Date | 2015-12-11 13:50 +0100 |
| Subject | Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps |
| Message-ID | <qEvj4-4o4-11@gated-at.bofh.it> |
| In reply to | #1289515 |
发自我的 iPhone
> 在 2015年12月11日,下午8:15,Arnaldo Carvalho de Melo <acme@kernel.org> 写道:
>
> Em Fri, Dec 11, 2015 at 09:11:45AM -0300, Arnaldo Carvalho de Melo escreveu:
>> Em Tue, Dec 08, 2015 at 02:25:37AM +0000, Wang Nan escreveu:
>>> This patch introduce a new syntax to perf event parser:
>>>
>>> # perf record -e bpf_file.c/maps.mymap.value[0,3...5,7]=1234/ ...
>>
>> Is the above example valid? Wouldn't this be "maps:mymap.value" ?
>>
>>>
>>> By utilizing the basic facilities in bpf-loader.c which allow setting
>>> different slots in a BPF map separately, the newly introduced syntax
>>> allows perf to control specific elements in a BPF map.
>>>
>>> Test result:
>>>
>>> # cat ./test_bpf_map_3.c
>>> /************************ BEGIN **************************/
>>> #define SEC(NAME) __attribute__((section(NAME), used))
>>> enum bpf_map_type {
>>> BPF_MAP_TYPE_ARRAY = 2,
>>> };
>>> struct bpf_map_def {
>>> unsigned int type;
>>> unsigned int key_size;
>>> unsigned int value_size;
>>> unsigned int max_entries;
>>> };
>>> static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
>>> (void *)1;
>>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
>>> (void *)6;
>>
>> Can you explain the above a bit more? What are the magic 1 and 6 values?
>
> So, from another patch:
>
> static u64 (*bpf_ktime_get_ns)(void) =
> (void *)5;
> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
> (void *)6;
> static int (*bpf_get_smp_processor_id)(void) =
> (void *)8;
> static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
> void *, unsigned long) =
> (void *)23;
>
> Where can I get this magical mistery table? Could this be hidden away in
> some .h file automagically included in bpf scriptlets so that n00bies
> like me don't have to be wtf'ing?
>
They are function numbers defined in bpf.h and bpf-common.h, but they are Linux
headers. Directly include them causes many error for llvm. Also, the function
prototypes are BPF specific and can't included in Linux source. We should have
a place holds those indices and prototypes together.
> - Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Alexei Starovoitov <alexei.starovoitov@gmail.com> |
|---|---|
| Date | 2015-12-11 19:30 +0100 |
| Subject | Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps |
| Message-ID | <qEAC5-862-5@gated-at.bofh.it> |
| In reply to | #1289534 |
On Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama wrote: > > static u64 (*bpf_ktime_get_ns)(void) = > > (void *)5; > > static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) = > > (void *)6; > > static int (*bpf_get_smp_processor_id)(void) = > > (void *)8; > > static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int, > > void *, unsigned long) = > > (void *)23; > > > > Where can I get this magical mistery table? Could this be hidden away in > > some .h file automagically included in bpf scriptlets so that n00bies > > like me don't have to be wtf'ing? > > > > They are function numbers defined in bpf.h and bpf-common.h, but they are Linux > headers. Directly include them causes many error for llvm. Also, the function > prototypes are BPF specific and can't included in Linux source. We should have > a place holds those indices and prototypes together. wait, what kind of errors? they are in uapi, so gets installed into /usr/include eventually and I haven't seen any erros either with gcc or clang. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | "Wangnan (F)" <wangnan0@huawei.com> |
|---|---|
| Date | 2015-12-14 04:30 +0100 |
| Subject | Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps |
| Message-ID | <qFrZM-we-11@gated-at.bofh.it> |
| In reply to | #1289812 |
On 2015/12/12 2:21, Alexei Starovoitov wrote: > On Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama wrote: >>> static u64 (*bpf_ktime_get_ns)(void) = >>> (void *)5; >>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) = >>> (void *)6; >>> static int (*bpf_get_smp_processor_id)(void) = >>> (void *)8; >>> static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int, >>> void *, unsigned long) = >>> (void *)23; >>> >>> Where can I get this magical mistery table? Could this be hidden away in >>> some .h file automagically included in bpf scriptlets so that n00bies >>> like me don't have to be wtf'ing? >>> >> They are function numbers defined in bpf.h and bpf-common.h, but they are Linux >> headers. Directly include them causes many error for llvm. Also, the function >> prototypes are BPF specific and can't included in Linux source. We should have >> a place holds those indices and prototypes together. > wait, what kind of errors? > they are in uapi, so gets installed into /usr/include eventually > and I haven't seen any erros either with gcc or clang. > Sorry. I saw error because I use #include <linux/bpf.h> It is okay if I use #include <uapi/linux/bpf.h> Thank you. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Alexei Starovoitov <alexei.starovoitov@gmail.com> |
|---|---|
| Date | 2015-12-14 05:30 +0100 |
| Subject | Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps |
| Message-ID | <qFsVP-17V-5@gated-at.bofh.it> |
| In reply to | #1290815 |
On Mon, Dec 14, 2015 at 11:27:36AM +0800, Wangnan (F) wrote: > > > On 2015/12/12 2:21, Alexei Starovoitov wrote: > >On Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama wrote: > >>>static u64 (*bpf_ktime_get_ns)(void) = > >>> (void *)5; > >>>static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) = > >>> (void *)6; > >>>static int (*bpf_get_smp_processor_id)(void) = > >>> (void *)8; > >>>static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int, > >>>void *, unsigned long) = > >>> (void *)23; > >>> > >>>Where can I get this magical mistery table? Could this be hidden away in > >>>some .h file automagically included in bpf scriptlets so that n00bies > >>>like me don't have to be wtf'ing? > >>> > >>They are function numbers defined in bpf.h and bpf-common.h, but they are Linux > >>headers. Directly include them causes many error for llvm. Also, the function > >>prototypes are BPF specific and can't included in Linux source. We should have > >>a place holds those indices and prototypes together. > >wait, what kind of errors? > >they are in uapi, so gets installed into /usr/include eventually > >and I haven't seen any erros either with gcc or clang. > > > Sorry. I saw error because I use > > #include <linux/bpf.h> > > It is okay if I use > > #include <uapi/linux/bpf.h> then let's use that instead of copy-paste. thanks -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | "Wangnan (F)" <wangnan0@huawei.com> |
|---|---|
| Date | 2015-12-14 05:50 +0100 |
| Subject | Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps |
| Message-ID | <qFtfc-1fM-9@gated-at.bofh.it> |
| In reply to | #1290834 |
On 2015/12/14 12:28, Alexei Starovoitov wrote:
> On Mon, Dec 14, 2015 at 11:27:36AM +0800, Wangnan (F) wrote:
>>
>> On 2015/12/12 2:21, Alexei Starovoitov wrote:
>>> On Fri, Dec 11, 2015 at 08:39:35PM +0800, pi3orama wrote:
>>>>> static u64 (*bpf_ktime_get_ns)(void) =
>>>>> (void *)5;
>>>>> static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
>>>>> (void *)6;
>>>>> static int (*bpf_get_smp_processor_id)(void) =
>>>>> (void *)8;
>>>>> static int (*bpf_perf_event_output)(void *, struct bpf_map_def *, int,
>>>>> void *, unsigned long) =
>>>>> (void *)23;
>>>>>
>>>>> Where can I get this magical mistery table? Could this be hidden away in
>>>>> some .h file automagically included in bpf scriptlets so that n00bies
>>>>> like me don't have to be wtf'ing?
>>>>>
>>>> They are function numbers defined in bpf.h and bpf-common.h, but they are Linux
>>>> headers. Directly include them causes many error for llvm. Also, the function
>>>> prototypes are BPF specific and can't included in Linux source. We should have
>>>> a place holds those indices and prototypes together.
>>> wait, what kind of errors?
>>> they are in uapi, so gets installed into /usr/include eventually
>>> and I haven't seen any erros either with gcc or clang.
>>>
>> Sorry. I saw error because I use
>>
>> #include <linux/bpf.h>
>>
>> It is okay if I use
>>
>> #include <uapi/linux/bpf.h>
> then let's use that instead of copy-paste. thanks
And what do you think about the BPF function prototype? Should we put them
into kernel headers? What about::
diff --git a/include/uapi/linux/bpf_functions.h
b/include/uapi/linux/bpf_functions.h
new file mode 100644
index 0000000..3a562d4
--- /dev/null
+++ b/include/uapi/linux/bpf_functions.h
@@ -0,0 +1,2 @@
+DEFINE_BPF_FUNC(void *, map_lookup_elem, void *, void *)
+DEFINE_BPF_FUNC(int, map_update_elem, void *, void *, void *, int)
[SNIP]
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 9ea2d22..2f2f05f 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -133,143 +133,23 @@ union bpf_attr {
};
} __attribute__((aligned(8)));
+#define DEFINE_BPF_FUNC(rettype, name, arglist...) BPF_FUNC_##name
+
+enum bpf_func_id {
+BPF_FUNC_unspec,
+#include "bpf_functions.h"
+__BPF_FUNC_MAX_ID,
+};
+
+#ifdef __BPF_SOURCE__
+#undef DEFINE_BPF_FUNC
+#define DEFINE_BPF_FUNC(rettype, name, arglist...) static rettype
(*name)(arglist) = (void *)BPF_FUNC_##name
+#include "bpf_functions.h"
+#endif
/* integer value in 'imm' field of BPF_CALL instruction selects which
helper
* function eBPF program intends to call
*/
enum bpf_func_id {
- BPF_FUNC_unspec,
[SNIP]
And when compiling BPF source file we add a __BPF_SOURCE__ directive?
Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Alexei Starovoitov <alexei.starovoitov@gmail.com> |
|---|---|
| Date | 2015-12-14 07:00 +0100 |
| Subject | Re: [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps |
| Message-ID | <qFukW-1Wg-7@gated-at.bofh.it> |
| In reply to | #1290845 |
On Mon, Dec 14, 2015 at 12:39:40PM +0800, Wangnan (F) wrote:
>
> And what do you think about the BPF function prototype? Should we put them
> into kernel headers? What about::
> +#define DEFINE_BPF_FUNC(rettype, name, arglist...) static rettype
> (*name)(arglist) = (void *)BPF_FUNC_##name
tldr: let's keep it as a part of user headers until better
solution found.
frankly
static void *(*bpf_map_lookup_elem)(void *map, void *key) =
(void *) BPF_FUNC_map_lookup_elem;
was llvm hack that I thought will be fixed quickly.
That was the easiest way to make C/llvm/bpf_loader to agree on
passing 'bpf_call #num' insn into the kernel.
It works, but it works only with -O2 and higher.
At lower optimization levels llvm generates load of constant
into register and indirect call by register, so that's not suitable
as clean api. bcc with clang::rewriter can solve it, but we don't
want to always depend on that, so currently it's a status quo.
Don't mess with what ain't broken.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-12-08 03:30 +0100 |
| Subject | [PATCH v4 13/16] perf tools: Always give options even it not compiled |
| Message-ID | <qDgcq-4Bz-29@gated-at.bofh.it> |
| In reply to | #1286157 |
This patch keeps options of perf builtins same in all conditions. If
one option is disabled because of compiling options, users should be
notified.
Masami suggested another implementation in [1] that, by adding a
OPTION_NEXT_DEPENDS option before those options in the 'struct option'
array, options parser knows an option is disabled. However, in some
cases this array is reordered (options__order()). In addition, in
parse-option.c that array is const, so we can't simply merge
information in decorator option into the affacted option.
This patch chooses a simpler implementation that, introducing a
set_option_nobuild() function and two option parsing flags. Builtins
with such options should call set_option_nobuild() before option
parsing. The complexity of this patch is because we want some of options
can be skipped safely. In this case their arguments should also be
consumed.
Options in 'perf record' and 'perf probe' are fixed in this patch.
[1] http://lkml.kernel.org/g/50399556C9727B4D88A595C8584AAB3752627CD4@GSjpTKYDCembx32.service.hitachi.net
Test result:
Normal case:
# ./perf probe --vmlinux /tmp/vmlinux sys_write
Added new event:
probe:sys_write (on sys_write)
You can now use it in all perf tools, such as:
perf record -e probe:sys_write -aR sleep 1
Build with NO_DWARF=1:
# ./perf probe -L sys_write
Error: switch `L' is not built because NO_DWARF=1
Usage: perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]
or: perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]
or: perf probe [<options>] --del '[GROUP:]EVENT' ...
or: perf probe --list [GROUP:]EVENT ...
or: perf probe [<options>] --funcs
-L, --line <FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]>
Show source code lines.
(not build because NO_DWARF=1)
# ./perf probe -k /tmp/vmlinux sys_write
Warning: switch `k' is not built because NO_DWARF=1
Added new event:
probe:sys_write (on sys_write)
You can now use it in all perf tools, such as:
perf record -e probe:sys_write -aR sleep 1
# ./perf probe --vmlinux /tmp/vmlinux sys_write
Warning: option `vmlinux' is not built because NO_DWARF=1
Added new event:
[SNIP]
# ./perf probe -l
Usage: perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]
or: perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]
...
-k, --vmlinux <file> vmlinux pathname
(not build because NO_DWARF=1)
-L, --line <FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]>
Show source code lines.
(not build because NO_DWARF=1)
...
-V, --vars <FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT>
Show accessible variables on PROBEDEF
(not build because NO_DWARF=1)
--externs Show external variables too (with --vars only)
(not build because NO_DWARF=1)
--no-inlines Don't search inlined functions
(not build because NO_DWARF=1)
--range Show variables location range in scope (with --vars only)
(not build because NO_DWARF=1)
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
tools/perf/builtin-probe.c | 15 +++++-
tools/perf/builtin-record.c | 9 +++-
tools/perf/util/parse-options.c | 113 ++++++++++++++++++++++++++++++++++++----
tools/perf/util/parse-options.h | 5 ++
4 files changed, 129 insertions(+), 13 deletions(-)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 132afc9..dbe2ea5 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -249,6 +249,9 @@ static int opt_show_vars(const struct option *opt,
return ret;
}
+#else
+# define opt_show_lines NULL
+# define opt_show_vars NULL
#endif
static int opt_add_probe_event(const struct option *opt,
const char *str, int unset __maybe_unused)
@@ -473,7 +476,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
opt_add_probe_event),
OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
" with existing name"),
-#ifdef HAVE_DWARF_SUPPORT
OPT_CALLBACK('L', "line", NULL,
"FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
"Show source code lines.", opt_show_lines),
@@ -490,7 +492,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
"directory", "path to kernel source"),
OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
"Don't search inlined functions"),
-#endif
OPT__DRY_RUN(&probe_event_dry_run),
OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
"Set how many probe points can be found for a probe."),
@@ -521,6 +522,16 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
#ifdef HAVE_DWARF_SUPPORT
set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
+#else
+# define set_nobuild(s, l, c) set_option_nobuild(options, s, l, "NO_DWARF=1", c)
+ set_nobuild('L', "line", false);
+ set_nobuild('V', "vars", false);
+ set_nobuild('\0', "externs", false);
+ set_nobuild('\0', "range", false);
+ set_nobuild('k', "vmlinux", true);
+ set_nobuild('s', "source", true);
+ set_nobuild('\0', "no-inlines", true);
+# undef set_nobuild
#endif
set_option_flag(options, 'F', "funcs", PARSE_OPT_EXCLUSIVE);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8479821..11bf32d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1124,12 +1124,10 @@ struct option __record_options[] = {
"per thread proc mmap processing timeout in ms"),
OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
"Record context switch events"),
-#ifdef HAVE_LIBBPF_SUPPORT
OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
"clang binary to use for compiling BPF scriptlets"),
OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
"options passed to clang when compiling BPF scriptlets"),
-#endif
OPT_END()
};
@@ -1141,6 +1139,13 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
struct record *rec = &record;
char errbuf[BUFSIZ];
+#ifndef HAVE_LIBBPF_SUPPORT
+# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
+ set_nobuild('\0', "clang-path", true);
+ set_nobuild('\0', "clang-opt", true);
+# undef set_nobuild
+#endif
+
rec->evlist = perf_evlist__new();
if (rec->evlist == NULL)
return -ENOMEM;
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 9fca092..105e357 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -18,20 +18,34 @@ static int opterror(const struct option *opt, const char *reason, int flags)
return error("option `%s' %s", opt->long_name, reason);
}
+static void optwarning(const struct option *opt, const char *reason, int flags)
+{
+ if (flags & OPT_SHORT)
+ warning("switch `%c' %s", opt->short_name, reason);
+ else if (flags & OPT_UNSET)
+ warning("option `no-%s' %s", opt->long_name, reason);
+ else
+ warning("option `%s' %s", opt->long_name, reason);
+}
+
static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
int flags, const char **arg)
{
+ const char *res;
+
if (p->opt) {
- *arg = p->opt;
+ res = p->opt;
p->opt = NULL;
} else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
**(p->argv + 1) == '-')) {
- *arg = (const char *)opt->defval;
+ res = (const char *)opt->defval;
} else if (p->argc > 1) {
p->argc--;
- *arg = *++p->argv;
+ res = *++p->argv;
} else
return opterror(opt, "requires a value", flags);
+ if (arg)
+ *arg = res;
return 0;
}
@@ -91,6 +105,59 @@ static int get_value(struct parse_opt_ctx_t *p,
}
}
+ if (opt->flags & PARSE_OPT_NOBUILD) {
+ char reason[128];
+ bool noarg = false;
+
+ err = snprintf(reason, sizeof(reason),
+ "is not built because %s",
+ opt->build_opt);
+ reason[sizeof(reason) - 1] = '\0';
+
+ if (err < 0)
+ strncpy(reason, "is not built", sizeof(reason));
+
+ if (!(opt->flags & PARSE_OPT_CANSKIP))
+ return opterror(opt, reason, flags);
+
+ err = 0;
+ if (unset)
+ noarg = true;
+ if (opt->flags & PARSE_OPT_NOARG)
+ noarg = true;
+ if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+ noarg = true;
+
+ switch (opt->type) {
+ case OPTION_BOOLEAN:
+ case OPTION_INCR:
+ case OPTION_BIT:
+ case OPTION_SET_UINT:
+ case OPTION_SET_PTR:
+ case OPTION_END:
+ case OPTION_ARGUMENT:
+ case OPTION_GROUP:
+ noarg = true;
+ break;
+ case OPTION_CALLBACK:
+ case OPTION_STRING:
+ case OPTION_INTEGER:
+ case OPTION_UINTEGER:
+ case OPTION_LONG:
+ case OPTION_U64:
+ default:
+ break;
+ }
+
+ if (!noarg)
+ err = get_arg(p, opt, flags, NULL);
+ if (err)
+ return err;
+
+ optwarning(opt, reason, flags);
+ return 0;
+ }
+
switch (opt->type) {
case OPTION_BIT:
if (unset)
@@ -647,6 +714,10 @@ static void print_option_help(const struct option *opts, int full)
pad = USAGE_OPTS_WIDTH;
}
fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
+ if (opts->flags & PARSE_OPT_NOBUILD)
+ fprintf(stderr, "%*s(not build because %s)\n",
+ USAGE_OPTS_WIDTH + USAGE_GAP, "",
+ opts->build_opt);
}
static int option__cmp(const void *va, const void *vb)
@@ -853,15 +924,39 @@ int parse_opt_verbosity_cb(const struct option *opt,
return 0;
}
-void set_option_flag(struct option *opts, int shortopt, const char *longopt,
- int flag)
+static struct option *
+find_option(struct option *opts, int shortopt, const char *longopt)
{
for (; opts->type != OPTION_END; opts++) {
if ((shortopt && opts->short_name == shortopt) ||
(opts->long_name && longopt &&
- !strcmp(opts->long_name, longopt))) {
- opts->flags |= flag;
- break;
- }
+ !strcmp(opts->long_name, longopt)))
+ return opts;
}
+ return NULL;
+}
+
+void set_option_flag(struct option *opts, int shortopt, const char *longopt,
+ int flag)
+{
+ struct option *opt = find_option(opts, shortopt, longopt);
+
+ if (opt)
+ opt->flags |= flag;
+ return;
+}
+
+void set_option_nobuild(struct option *opts, int shortopt,
+ const char *longopt,
+ const char *build_opt,
+ bool can_skip)
+{
+ struct option *opt = find_option(opts, shortopt, longopt);
+
+ if (!opt)
+ return;
+
+ opt->flags |= PARSE_OPT_NOBUILD;
+ opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0;
+ opt->build_opt = build_opt;
}
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index a8e407b..2cac2aa 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -41,6 +41,8 @@ enum parse_opt_option_flags {
PARSE_OPT_DISABLED = 32,
PARSE_OPT_EXCLUSIVE = 64,
PARSE_OPT_NOEMPTY = 128,
+ PARSE_OPT_NOBUILD = 256,
+ PARSE_OPT_CANSKIP = 512,
};
struct option;
@@ -96,6 +98,7 @@ struct option {
void *value;
const char *argh;
const char *help;
+ const char *build_opt;
int flags;
parse_opt_cb *callback;
@@ -226,4 +229,6 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
extern const char *parse_options_fix_filename(const char *prefix, const char *file);
void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
+void set_option_nobuild(struct option *opts, int shortopt, const char *longopt,
+ const char *build_opt, bool can_skip);
#endif /* __PERF_PARSE_OPTIONS_H */
--
1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2015-12-11 13:50 +0100 |
| Subject | Re: [PATCH v4 13/16] perf tools: Always give options even it not compiled |
| Message-ID | <qEvj4-4o4-19@gated-at.bofh.it> |
| In reply to | #1286163 |
Em Tue, Dec 08, 2015 at 02:25:41AM +0000, Wang Nan escreveu:
> This patch keeps options of perf builtins same in all conditions. If
> one option is disabled because of compiling options, users should be
> notified.
>
> Masami suggested another implementation in [1] that, by adding a
> OPTION_NEXT_DEPENDS option before those options in the 'struct option'
> array, options parser knows an option is disabled. However, in some
> cases this array is reordered (options__order()). In addition, in
> parse-option.c that array is const, so we can't simply merge
> information in decorator option into the affacted option.
>
> This patch chooses a simpler implementation that, introducing a
> set_option_nobuild() function and two option parsing flags. Builtins
> with such options should call set_option_nobuild() before option
> parsing. The complexity of this patch is because we want some of options
> can be skipped safely. In this case their arguments should also be
> consumed.
>
> Options in 'perf record' and 'perf probe' are fixed in this patch.
>
> [1] http://lkml.kernel.org/g/50399556C9727B4D88A595C8584AAB3752627CD4@GSjpTKYDCembx32.service.hitachi.net
>
> Test result:
>
> Normal case:
>
> # ./perf probe --vmlinux /tmp/vmlinux sys_write
> Added new event:
> probe:sys_write (on sys_write)
>
> You can now use it in all perf tools, such as:
>
> perf record -e probe:sys_write -aR sleep 1
>
>
> Build with NO_DWARF=1:
>
> # ./perf probe -L sys_write
> Error: switch `L' is not built because NO_DWARF=1
This should be:
Error: switch `L' is not built-in because NO_DWARF=1
But it would be better as:
Error: switch `L' is not available because NO_DWARF=1
What makes this an error is the fact that this option doesn't have that
CAN_SKIP flag, right? I.e. this SKIP flag determines the error/warning
message, for errors this should be "... is not available ..." for
warnings it should instead be "... is being ignored ...".
> Usage: perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]
> or: perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]
> or: perf probe [<options>] --del '[GROUP:]EVENT' ...
> or: perf probe --list [GROUP:]EVENT ...
> or: perf probe [<options>] --funcs
>
> -L, --line <FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]>
> Show source code lines.
> (not build because NO_DWARF=1)
>
> # ./perf probe -k /tmp/vmlinux sys_write
> Warning: switch `k' is not built because NO_DWARF=1
> Added new event:
> probe:sys_write (on sys_write)
>
> You can now use it in all perf tools, such as:
>
> perf record -e probe:sys_write -aR sleep 1
>
> # ./perf probe --vmlinux /tmp/vmlinux sys_write
> Warning: option `vmlinux' is not built because NO_DWARF=1
> Added new event:
> [SNIP]
>
> # ./perf probe -l
> Usage: perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]
> or: perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]
> ...
> -k, --vmlinux <file> vmlinux pathname
> (not build because NO_DWARF=1)
> -L, --line <FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]>
> Show source code lines.
> (not build because NO_DWARF=1)
> ...
> -V, --vars <FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT>
> Show accessible variables on PROBEDEF
> (not build because NO_DWARF=1)
> --externs Show external variables too (with --vars only)
> (not build because NO_DWARF=1)
> --no-inlines Don't search inlined functions
> (not build because NO_DWARF=1)
> --range Show variables location range in scope (with --vars only)
> (not build because NO_DWARF=1)
>
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Zefan Li <lizefan@huawei.com>
> Cc: pi3orama@163.com
> ---
> tools/perf/builtin-probe.c | 15 +++++-
> tools/perf/builtin-record.c | 9 +++-
> tools/perf/util/parse-options.c | 113 ++++++++++++++++++++++++++++++++++++----
> tools/perf/util/parse-options.h | 5 ++
> 4 files changed, 129 insertions(+), 13 deletions(-)
>
> diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
> index 132afc9..dbe2ea5 100644
> --- a/tools/perf/builtin-probe.c
> +++ b/tools/perf/builtin-probe.c
> @@ -249,6 +249,9 @@ static int opt_show_vars(const struct option *opt,
>
> return ret;
> }
> +#else
> +# define opt_show_lines NULL
> +# define opt_show_vars NULL
> #endif
> static int opt_add_probe_event(const struct option *opt,
> const char *str, int unset __maybe_unused)
> @@ -473,7 +476,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
> opt_add_probe_event),
> OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
> " with existing name"),
> -#ifdef HAVE_DWARF_SUPPORT
> OPT_CALLBACK('L', "line", NULL,
> "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
> "Show source code lines.", opt_show_lines),
> @@ -490,7 +492,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
> "directory", "path to kernel source"),
> OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
> "Don't search inlined functions"),
> -#endif
> OPT__DRY_RUN(&probe_event_dry_run),
> OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
> "Set how many probe points can be found for a probe."),
> @@ -521,6 +522,16 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
> #ifdef HAVE_DWARF_SUPPORT
> set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
> set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
> +#else
> +# define set_nobuild(s, l, c) set_option_nobuild(options, s, l, "NO_DWARF=1", c)
> + set_nobuild('L', "line", false);
> + set_nobuild('V', "vars", false);
> + set_nobuild('\0', "externs", false);
> + set_nobuild('\0', "range", false);
> + set_nobuild('k', "vmlinux", true);
> + set_nobuild('s', "source", true);
> + set_nobuild('\0', "no-inlines", true);
> +# undef set_nobuild
> #endif
> set_option_flag(options, 'F', "funcs", PARSE_OPT_EXCLUSIVE);
>
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 8479821..11bf32d 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -1124,12 +1124,10 @@ struct option __record_options[] = {
> "per thread proc mmap processing timeout in ms"),
> OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
> "Record context switch events"),
> -#ifdef HAVE_LIBBPF_SUPPORT
> OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
> "clang binary to use for compiling BPF scriptlets"),
> OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
> "options passed to clang when compiling BPF scriptlets"),
> -#endif
> OPT_END()
> };
>
> @@ -1141,6 +1139,13 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
> struct record *rec = &record;
> char errbuf[BUFSIZ];
>
> +#ifndef HAVE_LIBBPF_SUPPORT
> +# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
> + set_nobuild('\0', "clang-path", true);
> + set_nobuild('\0', "clang-opt", true);
> +# undef set_nobuild
> +#endif
> +
> rec->evlist = perf_evlist__new();
> if (rec->evlist == NULL)
> return -ENOMEM;
> diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
> index 9fca092..105e357 100644
> --- a/tools/perf/util/parse-options.c
> +++ b/tools/perf/util/parse-options.c
> @@ -18,20 +18,34 @@ static int opterror(const struct option *opt, const char *reason, int flags)
> return error("option `%s' %s", opt->long_name, reason);
> }
>
> +static void optwarning(const struct option *opt, const char *reason, int flags)
> +{
> + if (flags & OPT_SHORT)
> + warning("switch `%c' %s", opt->short_name, reason);
> + else if (flags & OPT_UNSET)
> + warning("option `no-%s' %s", opt->long_name, reason);
> + else
> + warning("option `%s' %s", opt->long_name, reason);
> +}
> +
> static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
> int flags, const char **arg)
> {
> + const char *res;
> +
> if (p->opt) {
> - *arg = p->opt;
> + res = p->opt;
> p->opt = NULL;
> } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
> **(p->argv + 1) == '-')) {
> - *arg = (const char *)opt->defval;
> + res = (const char *)opt->defval;
> } else if (p->argc > 1) {
> p->argc--;
> - *arg = *++p->argv;
> + res = *++p->argv;
> } else
> return opterror(opt, "requires a value", flags);
> + if (arg)
> + *arg = res;
> return 0;
> }
>
> @@ -91,6 +105,59 @@ static int get_value(struct parse_opt_ctx_t *p,
> }
> }
>
> + if (opt->flags & PARSE_OPT_NOBUILD) {
> + char reason[128];
> + bool noarg = false;
> +
> + err = snprintf(reason, sizeof(reason),
> + "is not built because %s",
> + opt->build_opt);
> + reason[sizeof(reason) - 1] = '\0';
> +
> + if (err < 0)
> + strncpy(reason, "is not built", sizeof(reason));
> +
> + if (!(opt->flags & PARSE_OPT_CANSKIP))
> + return opterror(opt, reason, flags);
> +
> + err = 0;
> + if (unset)
> + noarg = true;
> + if (opt->flags & PARSE_OPT_NOARG)
> + noarg = true;
> + if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
> + noarg = true;
> +
> + switch (opt->type) {
> + case OPTION_BOOLEAN:
> + case OPTION_INCR:
> + case OPTION_BIT:
> + case OPTION_SET_UINT:
> + case OPTION_SET_PTR:
> + case OPTION_END:
> + case OPTION_ARGUMENT:
> + case OPTION_GROUP:
> + noarg = true;
> + break;
> + case OPTION_CALLBACK:
> + case OPTION_STRING:
> + case OPTION_INTEGER:
> + case OPTION_UINTEGER:
> + case OPTION_LONG:
> + case OPTION_U64:
> + default:
> + break;
> + }
> +
> + if (!noarg)
> + err = get_arg(p, opt, flags, NULL);
> + if (err)
> + return err;
> +
> + optwarning(opt, reason, flags);
> + return 0;
> + }
> +
> switch (opt->type) {
> case OPTION_BIT:
> if (unset)
> @@ -647,6 +714,10 @@ static void print_option_help(const struct option *opts, int full)
> pad = USAGE_OPTS_WIDTH;
> }
> fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
> + if (opts->flags & PARSE_OPT_NOBUILD)
> + fprintf(stderr, "%*s(not build because %s)\n",
> + USAGE_OPTS_WIDTH + USAGE_GAP, "",
> + opts->build_opt);
> }
>
> static int option__cmp(const void *va, const void *vb)
> @@ -853,15 +924,39 @@ int parse_opt_verbosity_cb(const struct option *opt,
> return 0;
> }
>
> -void set_option_flag(struct option *opts, int shortopt, const char *longopt,
> - int flag)
> +static struct option *
> +find_option(struct option *opts, int shortopt, const char *longopt)
> {
> for (; opts->type != OPTION_END; opts++) {
> if ((shortopt && opts->short_name == shortopt) ||
> (opts->long_name && longopt &&
> - !strcmp(opts->long_name, longopt))) {
> - opts->flags |= flag;
> - break;
> - }
> + !strcmp(opts->long_name, longopt)))
> + return opts;
> }
> + return NULL;
> +}
> +
> +void set_option_flag(struct option *opts, int shortopt, const char *longopt,
> + int flag)
> +{
> + struct option *opt = find_option(opts, shortopt, longopt);
> +
> + if (opt)
> + opt->flags |= flag;
> + return;
> +}
> +
> +void set_option_nobuild(struct option *opts, int shortopt,
> + const char *longopt,
> + const char *build_opt,
> + bool can_skip)
> +{
> + struct option *opt = find_option(opts, shortopt, longopt);
> +
> + if (!opt)
> + return;
> +
> + opt->flags |= PARSE_OPT_NOBUILD;
> + opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0;
> + opt->build_opt = build_opt;
> }
> diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
> index a8e407b..2cac2aa 100644
> --- a/tools/perf/util/parse-options.h
> +++ b/tools/perf/util/parse-options.h
> @@ -41,6 +41,8 @@ enum parse_opt_option_flags {
> PARSE_OPT_DISABLED = 32,
> PARSE_OPT_EXCLUSIVE = 64,
> PARSE_OPT_NOEMPTY = 128,
> + PARSE_OPT_NOBUILD = 256,
> + PARSE_OPT_CANSKIP = 512,
> };
>
> struct option;
> @@ -96,6 +98,7 @@ struct option {
> void *value;
> const char *argh;
> const char *help;
> + const char *build_opt;
>
> int flags;
> parse_opt_cb *callback;
> @@ -226,4 +229,6 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
> extern const char *parse_options_fix_filename(const char *prefix, const char *file);
>
> void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
> +void set_option_nobuild(struct option *opts, int shortopt, const char *longopt,
> + const char *build_opt, bool can_skip);
> #endif /* __PERF_PARSE_OPTIONS_H */
> --
> 1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Date | 2015-12-08 03:40 +0100 |
| Subject | [PATCH v4 15/16] perf script: Add support for PERF_TYPE_BREAKPOINT |
| Message-ID | <qDgm5-4Et-1@gated-at.bofh.it> |
| In reply to | #1286157 |
Useful for getting stack traces for hardware breakpoint events.
Test result:
Before this patch:
# ~/perf record -g -e mem:0x600980 ./sample
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.011 MB perf.data (12 samples) ]
# ~/perf script
# ~/perf script -F comm,tid,pid,time,event,ip,sym,dso
sample 22520/22520 97457.836294: mem:0x600980:
5a4ad8 __clear_user (/lib/modules/4.3.0-rc4+/build/vmlinux)
...
3f41ba sys_execve (/lib/modules/4.3.0-rc4+/build/vmlinux)
979395 return_from_execve (/lib/modules/4.3.0-rc4+/build/vmlinux)
7f1b59719cf7 [unknown] ([unknown])
sample 22520/22520 97457.836648: mem:0x600980:
532 main (/home/w00229757/DataBreakpoints/sample)
21bd5 __libc_start_main (/tmp/oxygen_root-root/lib64/libc-2.18.so)
...
After this patch:
# ~/perf script
sample 22520 97457.836294: mem:0x600980:
5a4ad8 __clear_user (/lib/modules/4.3.0-rc4+/build/vmlinux)
...
3f41ba sys_execve (/lib/modules/4.3.0-rc4+/build/vmlinux)
979395 return_from_execve (/lib/modules/4.3.0-rc4+/build/vmlinux)
7f1b59719cf7 [unknown] ([unknown])
sample 22520 97457.836648: mem:0x600980:
532 main (/home/w00229757/DataBreakpoints/sample)
21bd5 __libc_start_main (/tmp/oxygen_root-root/lib64/libc-2.18.so)
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
tools/perf/builtin-script.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 3c3f8d0..d259e9a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -130,6 +130,18 @@ static struct {
.invalid_fields = PERF_OUTPUT_TRACE,
},
+
+ [PERF_TYPE_BREAKPOINT] = {
+ .user_set = false,
+
+ .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
+ PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
+ PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+ PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
+ PERF_OUTPUT_PERIOD,
+
+ .invalid_fields = PERF_OUTPUT_TRACE,
+ },
};
static bool output_set_by_user(void)
@@ -1129,6 +1141,8 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
type = PERF_TYPE_TRACEPOINT;
else if (!strcmp(str, "raw"))
type = PERF_TYPE_RAW;
+ else if (!strcmp(str, "break"))
+ type = PERF_TYPE_BREAKPOINT;
else {
fprintf(stderr, "Invalid event type in field string.\n");
rc = -EINVAL;
--
1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web