aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2015-11-16 07:10:08 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-11-18 15:51:04 -0500
commit03e01f568759ddbfdaff892e299758e7771a3478 (patch)
tree5d2f0cf93477ac50bb4e933db3f4fea94019f8bd
parent5dbd16c0c9d17ab1ab2226a5926482c26c0287ed (diff)
perf bpf: Allow BPF program config probing options
By extending the syntax of BPF object section names, this patch allows users to config probing options like what they can do in 'perf probe'. The error message in 'perf probe' is also updated. Test result: For following BPF file test_probe_glob.c: # cat test_probe_glob.c __attribute__((section("inlines=no;func=SyS_dup?"), used)) int func(void *ctx) { return 1; } char _license[] __attribute__((section("license"), used)) = "GPL"; int _version __attribute__((section("version"), used)) = 0x40300; # # ./perf record -e ./test_probe_glob.c ls / ... [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.013 MB perf.data ] # ./perf evlist perf_bpf_probe:func_1 perf_bpf_probe:func After changing "inlines=no" to "inlines=yes": # ./perf record -e ./test_probe_glob.c ls / ... [ perf record: Woken up 2 times to write data ] [ perf record: Captured and wrote 0.013 MB perf.data ] # ./perf evlist perf_bpf_probe:func_3 perf_bpf_probe:func_2 perf_bpf_probe:func_1 perf_bpf_probe:func Then test 'force': Use following program: # cat test_probe_force.c __attribute__((section("func=sys_write"), used)) int funca(void *ctx) { return 1; } __attribute__((section("force=yes;func=sys_write"), used)) int funcb(void *ctx) { return 1; } char _license[] __attribute__((section("license"), used)) = "GPL"; int _version __attribute__((section("version"), used)) = 0x40300; # # perf record -e ./test_probe_force.c usleep 1 Error: event "func" already exists. Hint: Remove existing event by 'perf probe -d' or force duplicates by 'perf probe -f' or set 'force=yes' in BPF source. event syntax error: './test_probe_force.c' \___ Probe point exist. Try 'perf probe -d "*"' and set 'force=yes' (add -v to see detail) ... Then replace 'force=no' to 'force=yes': # vim test_probe_force.c # perf record -e ./test_probe_force.c usleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.017 MB perf.data ] # perf evlist perf_bpf_probe:func_1 perf_bpf_probe:func # Signed-off-by: Wang Nan <wangnan0@huawei.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexei Starovoitov <ast@kernel.org> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Zefan Li <lizefan@huawei.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1447675815-166222-7-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/bpf-loader.c53
-rw-r--r--tools/perf/util/probe-event.c7
2 files changed, 56 insertions, 4 deletions
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index d0f02ed93804..98f2e5d1a5be 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -7,6 +7,7 @@
7 7
8#include <bpf/libbpf.h> 8#include <bpf/libbpf.h>
9#include <linux/err.h> 9#include <linux/err.h>
10#include <linux/string.h>
10#include "perf.h" 11#include "perf.h"
11#include "debug.h" 12#include "debug.h"
12#include "bpf-loader.h" 13#include "bpf-loader.h"
@@ -129,6 +130,38 @@ config__module(const char *value, struct perf_probe_event *pev)
129 return 0; 130 return 0;
130} 131}
131 132
133static int
134config__bool(const char *value,
135 bool *pbool, bool invert)
136{
137 int err;
138 bool bool_value;
139
140 if (!pbool)
141 return -EINVAL;
142
143 err = strtobool(value, &bool_value);
144 if (err)
145 return err;
146
147 *pbool = invert ? !bool_value : bool_value;
148 return 0;
149}
150
151static int
152config__inlines(const char *value,
153 struct perf_probe_event *pev __maybe_unused)
154{
155 return config__bool(value, &probe_conf.no_inlines, true);
156}
157
158static int
159config__force(const char *value,
160 struct perf_probe_event *pev __maybe_unused)
161{
162 return config__bool(value, &probe_conf.force_add, false);
163}
164
132static struct { 165static struct {
133 const char *key; 166 const char *key;
134 const char *usage; 167 const char *usage;
@@ -146,7 +179,19 @@ static struct {
146 .usage = "module=<module name> ", 179 .usage = "module=<module name> ",
147 .desc = "Set kprobe module", 180 .desc = "Set kprobe module",
148 .func = config__module, 181 .func = config__module,
149 } 182 },
183 {
184 .key = "inlines",
185 .usage = "inlines=[yes|no] ",
186 .desc = "Probe at inline symbol",
187 .func = config__inlines,
188 },
189 {
190 .key = "force",
191 .usage = "force=[yes|no] ",
192 .desc = "Forcibly add events with existing name",
193 .func = config__force,
194 },
150}; 195};
151 196
152static int 197static int
@@ -240,6 +285,10 @@ config_bpf_program(struct bpf_program *prog)
240 const char *config_str; 285 const char *config_str;
241 int err; 286 int err;
242 287
288 /* Initialize per-program probing setting */
289 probe_conf.no_inlines = false;
290 probe_conf.force_add = false;
291
243 config_str = bpf_program__title(prog, false); 292 config_str = bpf_program__title(prog, false);
244 if (IS_ERR(config_str)) { 293 if (IS_ERR(config_str)) {
245 pr_debug("bpf: unable to get title for program\n"); 294 pr_debug("bpf: unable to get title for program\n");
@@ -544,7 +593,7 @@ int bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
544 scnprintf(buf, size, "%s (add -v to see detail)", emsg); 593 scnprintf(buf, size, "%s (add -v to see detail)", emsg);
545 break; 594 break;
546 } 595 }
547 bpf__strerror_entry(EEXIST, "Probe point exist. Try use 'perf probe -d \"*\"'"); 596 bpf__strerror_entry(EEXIST, "Probe point exist. Try 'perf probe -d \"*\"' and set 'force=yes'");
548 bpf__strerror_entry(EACCES, "You need to be root"); 597 bpf__strerror_entry(EACCES, "You need to be root");
549 bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0"); 598 bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0");
550 bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file"); 599 bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file");
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 03875f9154e7..93996ec4bbe3 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2326,8 +2326,11 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2326 goto out; 2326 goto out;
2327 2327
2328 if (!allow_suffix) { 2328 if (!allow_suffix) {
2329 pr_warning("Error: event \"%s\" already exists. " 2329 pr_warning("Error: event \"%s\" already exists.\n"
2330 "(Use -f to force duplicates.)\n", buf); 2330 " Hint: Remove existing event by 'perf probe -d'\n"
2331 " or force duplicates by 'perf probe -f'\n"
2332 " or set 'force=yes' in BPF source.\n",
2333 buf);
2331 ret = -EEXIST; 2334 ret = -EEXIST;
2332 goto out; 2335 goto out;
2333 } 2336 }