aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/llvm-utils.c
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2016-06-16 04:02:40 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-06-21 12:18:34 -0400
commitf078464925f5b5c977c1196c67cae49cd82f40ff (patch)
treea1025e08ad7d796ee9a86558cb3f78ff16b49e4f /tools/perf/util/llvm-utils.c
parente861964a26b786d349add4db4825597ec65b5780 (diff)
perf llvm: Allow dump llvm output object file using llvm.dump-obj
Add a 'llvm.dump-obj' config option to enable perf dump BPF object files compiled by LLVM. This option is useful when using BPF objects in embedded platforms. LLVM compiler won't be deployed in these platforms, and currently we don't support dynamic compiling library. Before this patch users have to explicitly issue llvm commands to compile BPF scripts, and can't use helpers (like include path detection and default macros) in perf. With this option, user is allowed to use perf to compile their BPF objects then copy them into their embedded platforms. Committer notice: Testing it: # cat ~/.perfconfig [llvm] dump-obj = true # # ls -la filter.o ls: cannot access filter.o: No such file or directory # cat filter.c #include <uapi/linux/bpf.h> #define SEC(NAME) __attribute__((section(NAME), used)) SEC("func=hrtimer_nanosleep rqtp->tv_nsec") int func(void *ctx, int err, long nsec) { return nsec > 1000; } char _license[] SEC("license") = "GPL"; int _version SEC("version") = LINUX_VERSION_CODE; # trace -e nanosleep --event filter.c usleep 6 LLVM: dumping filter.o 0.007 ( 0.007 ms): usleep/13976 nanosleep(rqtp: 0x7ffc5847f640 ) ... 0.007 ( ): perf_bpf_probe:func:(ffffffff811137d0) tv_nsec=6000) 0.070 ( 0.070 ms): usleep/13976 ... [continued]: nanosleep()) = 0 # ls -la filter.o -rw-r--r--. 1 root root 776 Jun 20 17:01 filter.o # readelf -SW filter.o There are 7 section headers, starting at offset 0x148: Section Headers: [Nr] Name Type Address Off Size ES Flg Lk Inf Al [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 [ 1] .strtab STRTAB 0000000000000000 0000e8 00005a 00 0 0 1 [ 2] .text PROGBITS 0000000000000000 000040 000000 00 AX 0 0 4 [ 3] func=hrtimer_nanosleep rqtp->tv_nsec PROGBITS 0000000000000000 000040 000028 00 AX 0 0 8 [ 4] license PROGBITS 0000000000000000 000068 000004 00 WA 0 0 1 [ 5] version PROGBITS 0000000000000000 00006c 000004 00 WA 0 0 4 [ 6] .symtab SYMTAB 0000000000000000 000070 000078 18 1 2 8 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) # Signed-off-by: Wang Nan <wangnan0@huawei.com> Cc: Alexei Starovoitov <ast@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1466064161-48553-2-git-send-email-wangnan0@huawei.com [ s/dumpping/dumping/g ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/llvm-utils.c')
-rw-r--r--tools/perf/util/llvm-utils.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 33071d6159bc..878a566763c3 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -42,6 +42,8 @@ int perf_llvm_config(const char *var, const char *value)
42 llvm_param.kbuild_dir = strdup(value); 42 llvm_param.kbuild_dir = strdup(value);
43 else if (!strcmp(var, "kbuild-opts")) 43 else if (!strcmp(var, "kbuild-opts"))
44 llvm_param.kbuild_opts = strdup(value); 44 llvm_param.kbuild_opts = strdup(value);
45 else if (!strcmp(var, "dump-obj"))
46 llvm_param.dump_obj = !!perf_config_bool(var, value);
45 else 47 else
46 return -1; 48 return -1;
47 llvm_param.user_set_param = true; 49 llvm_param.user_set_param = true;
@@ -326,6 +328,42 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
326 pr_debug("include option is set to %s\n", *kbuild_include_opts); 328 pr_debug("include option is set to %s\n", *kbuild_include_opts);
327} 329}
328 330
331static void
332dump_obj(const char *path, void *obj_buf, size_t size)
333{
334 char *obj_path = strdup(path);
335 FILE *fp;
336 char *p;
337
338 if (!obj_path) {
339 pr_warning("WARNING: No enough memory, skip object dumping\n");
340 return;
341 }
342
343 p = strrchr(obj_path, '.');
344 if (!p || (strcmp(p, ".c") != 0)) {
345 pr_warning("WARNING: invalid llvm source path: '%s', skip object dumping\n",
346 obj_path);
347 goto out;
348 }
349
350 p[1] = 'o';
351 fp = fopen(obj_path, "wb");
352 if (!fp) {
353 pr_warning("WARNING: failed to open '%s': %s, skip object dumping\n",
354 obj_path, strerror(errno));
355 goto out;
356 }
357
358 pr_info("LLVM: dumping %s\n", obj_path);
359 if (fwrite(obj_buf, size, 1, fp) != 1)
360 pr_warning("WARNING: failed to write to file '%s': %s, skip object dumping\n",
361 obj_path, strerror(errno));
362 fclose(fp);
363out:
364 free(obj_path);
365}
366
329int llvm__compile_bpf(const char *path, void **p_obj_buf, 367int llvm__compile_bpf(const char *path, void **p_obj_buf,
330 size_t *p_obj_buf_sz) 368 size_t *p_obj_buf_sz)
331{ 369{
@@ -411,6 +449,10 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
411 449
412 free(kbuild_dir); 450 free(kbuild_dir);
413 free(kbuild_include_opts); 451 free(kbuild_include_opts);
452
453 if (llvm_param.dump_obj)
454 dump_obj(path, obj_buf, obj_buf_sz);
455
414 if (!p_obj_buf) 456 if (!p_obj_buf)
415 free(obj_buf); 457 free(obj_buf);
416 else 458 else