- Introduce 'perf ftrace' a perf front end to the kernel's ftrace function and function_graph tracer, defaulting to the "function_graph" tracer, more work will be done in reviving this effort, forward porting it from its initial patch submission (Namhyung Kim) - Add 'e' and 'c' hotkeys to expand/collapse call chains for a single hist entry in the 'perf report' and 'perf top' TUI (Jiri Olsa) Fixes: - Fix wrong register name for arm64, used in 'perf probe' (He Kuang) - Fix map offsets in relocation in libbpf (Joe Stringer) - Fix looking up dwarf unwind stack info (Matija Glavinic Pecotic) Infrastructure: - libbpf prog functions sync with what is exported via uapi (Joe Stringer) Trivial: - Remove unnecessary checks and assignments in 'perf probe's try_to_find_absolute_address() (Markus Elfring) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJYig7UAAoJENZQFvNTUqpAhJQP/iI0T7A8TNekPGLv7j20c302 89N9+9TAFtVqjgr1hIzqQgGOqbOdAW1tU3VTPW92nNDBn9JV5qwuF9YWEiDaAVv2 0bmV5hLnrNlymddm3pdg/PbD1TVlwk2NFxtrkPxuf/vx0ZhEGqsSrRUCR/xGXbtQ TcMg3rQquspV9JNv4HzFdQC9nsG1CGNotZKsE1avRw70pWAqCtF81B0m8teb6OWo 5qnN+AMJlYcC+OGffROemUksuehkMvi5L8v1e/6RO/lU1qt9Jrc/2sT9cqvjVFNR k4c76cUgWOCYzDEotENMpU4bc6e/24DE2ydFeovihdXw8Qs4ajEA9LXKM4yW+ZoE MZE3GS153a8n+CvTfkB9Ow1QJ8rgmR/L0BuhmGb6bYW/MtuTRTShhSduZwOrIyap 9KckHYti4p3oN3CKFYGO9PN3DRUdx+Xqg/miwrgjkPo09QFp+lzfFFOk0P2/Zqw2 yfvdWeHxkkrwoWQIyMHVKp/E9jQPuyYqwnKdp68LCN+DgNiFpPpSA8id5e47RQDE otqrK8U/82ktakfrBijSPBI6EEqFg7ltip2KT/xlDMfnP9HtxgFhzrk52dyi6pM/ jkBhJaTQhVZTyaFvUXuaLmBSdPpcaaGM4KJ+2iAayA2r0KLiDj6IdzD5ROCRFOvJ SFA472mIxNxUjpQEUTtc =tYKN -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo-4.11-20170126' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core Pull the latest perf/core updates from Arnaldo Carvalho de Melo: New features: - Introduce 'perf ftrace' a perf front end to the kernel's ftrace function and function_graph tracer, defaulting to the "function_graph" tracer, more work will be done in reviving this effort, forward porting it from its initial patch submission (Namhyung Kim) - Add 'e' and 'c' hotkeys to expand/collapse call chains for a single hist entry in the 'perf report' and 'perf top' TUI (Jiri Olsa) Fixes: - Fix wrong register name for arm64, used in 'perf probe' (He Kuang) - Fix map offsets in relocation in libbpf (Joe Stringer) - Fix looking up dwarf unwind stack info (Matija Glavinic Pecotic) Infrastructure changes: - libbpf prog functions sync with what is exported via uapi (Joe Stringer) Trivial changes: - Remove unnecessary checks and assignments in 'perf probe's try_to_find_absolute_address() (Markus Elfring) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>tirimbino
commit
e2cf00c257
@ -0,0 +1,36 @@ |
||||
perf-ftrace(1) |
||||
============= |
||||
|
||||
NAME |
||||
---- |
||||
perf-ftrace - simple wrapper for kernel's ftrace functionality |
||||
|
||||
|
||||
SYNOPSIS |
||||
-------- |
||||
[verse] |
||||
'perf ftrace' <command> |
||||
|
||||
DESCRIPTION |
||||
----------- |
||||
The 'perf ftrace' command is a simple wrapper of kernel's ftrace |
||||
functionality. It only supports single thread tracing currently and |
||||
just reads trace_pipe in text and then write it to stdout. |
||||
|
||||
The following options apply to perf ftrace. |
||||
|
||||
OPTIONS |
||||
------- |
||||
|
||||
-t:: |
||||
--tracer=:: |
||||
Tracer to use: function_graph or function. |
||||
|
||||
-v:: |
||||
--verbose=:: |
||||
Verbosity level. |
||||
|
||||
|
||||
SEE ALSO |
||||
-------- |
||||
linkperf:perf-record[1], linkperf:perf-trace[1] |
@ -0,0 +1,243 @@ |
||||
/*
|
||||
* builtin-ftrace.c |
||||
* |
||||
* Copyright (c) 2013 LG Electronics, Namhyung Kim <namhyung@kernel.org> |
||||
* |
||||
* Released under the GPL v2. |
||||
*/ |
||||
|
||||
#include "builtin.h" |
||||
#include "perf.h" |
||||
|
||||
#include <unistd.h> |
||||
#include <signal.h> |
||||
|
||||
#include "debug.h" |
||||
#include <subcmd/parse-options.h> |
||||
#include "evlist.h" |
||||
#include "target.h" |
||||
#include "thread_map.h" |
||||
|
||||
|
||||
#define DEFAULT_TRACER "function_graph" |
||||
|
||||
struct perf_ftrace { |
||||
struct perf_evlist *evlist; |
||||
struct target target; |
||||
const char *tracer; |
||||
}; |
||||
|
||||
static bool done; |
||||
|
||||
static void sig_handler(int sig __maybe_unused) |
||||
{ |
||||
done = true; |
||||
} |
||||
|
||||
/*
|
||||
* perf_evlist__prepare_workload will send a SIGUSR1 if the fork fails, since |
||||
* we asked by setting its exec_error to the function below, |
||||
* ftrace__workload_exec_failed_signal. |
||||
* |
||||
* XXX We need to handle this more appropriately, emitting an error, etc. |
||||
*/ |
||||
static void ftrace__workload_exec_failed_signal(int signo __maybe_unused, |
||||
siginfo_t *info __maybe_unused, |
||||
void *ucontext __maybe_unused) |
||||
{ |
||||
/* workload_exec_errno = info->si_value.sival_int; */ |
||||
done = true; |
||||
} |
||||
|
||||
static int write_tracing_file(const char *name, const char *val) |
||||
{ |
||||
char *file; |
||||
int fd, ret = -1; |
||||
ssize_t size = strlen(val); |
||||
|
||||
file = get_tracing_file(name); |
||||
if (!file) { |
||||
pr_debug("cannot get tracing file: %s\n", name); |
||||
return -1; |
||||
} |
||||
|
||||
fd = open(file, O_WRONLY); |
||||
if (fd < 0) { |
||||
pr_debug("cannot open tracing file: %s\n", name); |
||||
goto out; |
||||
} |
||||
|
||||
if (write(fd, val, size) == size) |
||||
ret = 0; |
||||
else |
||||
pr_debug("write '%s' to tracing/%s failed\n", val, name); |
||||
|
||||
close(fd); |
||||
out: |
||||
put_tracing_file(file); |
||||
return ret; |
||||
} |
||||
|
||||
static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused) |
||||
{ |
||||
if (write_tracing_file("tracing_on", "0") < 0) |
||||
return -1; |
||||
|
||||
if (write_tracing_file("current_tracer", "nop") < 0) |
||||
return -1; |
||||
|
||||
if (write_tracing_file("set_ftrace_pid", " ") < 0) |
||||
return -1; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv) |
||||
{ |
||||
char *trace_file; |
||||
int trace_fd; |
||||
char *trace_pid; |
||||
char buf[4096]; |
||||
struct pollfd pollfd = { |
||||
.events = POLLIN, |
||||
}; |
||||
|
||||
if (geteuid() != 0) { |
||||
pr_err("ftrace only works for root!\n"); |
||||
return -1; |
||||
} |
||||
|
||||
if (argc < 1) |
||||
return -1; |
||||
|
||||
signal(SIGINT, sig_handler); |
||||
signal(SIGUSR1, sig_handler); |
||||
signal(SIGCHLD, sig_handler); |
||||
|
||||
reset_tracing_files(ftrace); |
||||
|
||||
/* reset ftrace buffer */ |
||||
if (write_tracing_file("trace", "0") < 0) |
||||
goto out; |
||||
|
||||
if (perf_evlist__prepare_workload(ftrace->evlist, &ftrace->target, |
||||
argv, false, ftrace__workload_exec_failed_signal) < 0) |
||||
goto out; |
||||
|
||||
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) { |
||||
pr_err("failed to set current_tracer to %s\n", ftrace->tracer); |
||||
goto out; |
||||
} |
||||
|
||||
if (asprintf(&trace_pid, "%d", thread_map__pid(ftrace->evlist->threads, 0)) < 0) { |
||||
pr_err("failed to allocate pid string\n"); |
||||
goto out; |
||||
} |
||||
|
||||
if (write_tracing_file("set_ftrace_pid", trace_pid) < 0) { |
||||
pr_err("failed to set pid: %s\n", trace_pid); |
||||
goto out_free_pid; |
||||
} |
||||
|
||||
trace_file = get_tracing_file("trace_pipe"); |
||||
if (!trace_file) { |
||||
pr_err("failed to open trace_pipe\n"); |
||||
goto out_free_pid; |
||||
} |
||||
|
||||
trace_fd = open(trace_file, O_RDONLY); |
||||
|
||||
put_tracing_file(trace_file); |
||||
|
||||
if (trace_fd < 0) { |
||||
pr_err("failed to open trace_pipe\n"); |
||||
goto out_free_pid; |
||||
} |
||||
|
||||
fcntl(trace_fd, F_SETFL, O_NONBLOCK); |
||||
pollfd.fd = trace_fd; |
||||
|
||||
if (write_tracing_file("tracing_on", "1") < 0) { |
||||
pr_err("can't enable tracing\n"); |
||||
goto out_close_fd; |
||||
} |
||||
|
||||
perf_evlist__start_workload(ftrace->evlist); |
||||
|
||||
while (!done) { |
||||
if (poll(&pollfd, 1, -1) < 0) |
||||
break; |
||||
|
||||
if (pollfd.revents & POLLIN) { |
||||
int n = read(trace_fd, buf, sizeof(buf)); |
||||
if (n < 0) |
||||
break; |
||||
if (fwrite(buf, n, 1, stdout) != 1) |
||||
break; |
||||
} |
||||
} |
||||
|
||||
write_tracing_file("tracing_on", "0"); |
||||
|
||||
/* read remaining buffer contents */ |
||||
while (true) { |
||||
int n = read(trace_fd, buf, sizeof(buf)); |
||||
if (n <= 0) |
||||
break; |
||||
if (fwrite(buf, n, 1, stdout) != 1) |
||||
break; |
||||
} |
||||
|
||||
out_close_fd: |
||||
close(trace_fd); |
||||
out_free_pid: |
||||
free(trace_pid); |
||||
out: |
||||
reset_tracing_files(ftrace); |
||||
|
||||
return done ? 0 : -1; |
||||
} |
||||
|
||||
int cmd_ftrace(int argc, const char **argv, const char *prefix __maybe_unused) |
||||
{ |
||||
int ret; |
||||
struct perf_ftrace ftrace = { |
||||
.tracer = "function_graph", |
||||
.target = { .uid = UINT_MAX, }, |
||||
}; |
||||
const char * const ftrace_usage[] = { |
||||
"perf ftrace [<options>] <command>", |
||||
"perf ftrace [<options>] -- <command> [<options>]", |
||||
NULL |
||||
}; |
||||
const struct option ftrace_options[] = { |
||||
OPT_STRING('t', "tracer", &ftrace.tracer, "tracer", |
||||
"tracer to use: function_graph(default) or function"), |
||||
OPT_INCR('v', "verbose", &verbose, |
||||
"be more verbose"), |
||||
OPT_END() |
||||
}; |
||||
|
||||
argc = parse_options(argc, argv, ftrace_options, ftrace_usage, |
||||
PARSE_OPT_STOP_AT_NON_OPTION); |
||||
if (!argc) |
||||
usage_with_options(ftrace_usage, ftrace_options); |
||||
|
||||
ftrace.evlist = perf_evlist__new(); |
||||
if (ftrace.evlist == NULL) |
||||
return -ENOMEM; |
||||
|
||||
ret = perf_evlist__create_maps(ftrace.evlist, &ftrace.target); |
||||
if (ret < 0) |
||||
goto out_delete_evlist; |
||||
|
||||
if (ftrace.tracer == NULL) |
||||
ftrace.tracer = DEFAULT_TRACER; |
||||
|
||||
ret = __cmd_ftrace(&ftrace, argc, argv); |
||||
|
||||
out_delete_evlist: |
||||
perf_evlist__delete(ftrace.evlist); |
||||
|
||||
return ret; |
||||
} |
Loading…
Reference in new issue