linux/tools/perf/trace/beauty/prctl.c

83 lines
2.3 KiB
C
Raw Normal View History

perf trace beauty prctl: Generate 'option' string table from kernel headers This is one more case where the way that syscall parameter values are defined in kernel headers are easy to parse using a shell script that will then generate the string table that gets used by the prctl 'option' argument beautifier. This way as soon as the header syncronization mechanism in perf's build system detects a change in a copy of a kernel ABI header and that file is syncronized, we get 'perf trace' updated automagically. Further work needed for the PR_SET_ values, as well for using eBPF to copy the non-integer arguments to/from the kernel. E.g.: System wide prctl tracing: # perf trace -e prctl 1668.028 ( 0.025 ms): TaskSchedulerR/10649 prctl(option: SET_NAME, arg2: 0x2b61d5db15d0) = 0 3365.663 ( 0.018 ms): chrome/10650 prctl(option: SET_SECCOMP, arg2: 2, arg4: 8 ) = -1 EFAULT Bad address 3366.585 ( 0.010 ms): chrome/10650 prctl(option: SET_NO_NEW_PRIVS, arg2: 1 ) = 0 3367.173 ( 0.009 ms): TaskSchedulerR/10652 prctl(option: SET_NAME, arg2: 0x2b61d2aaa300) = 0 3367.222 ( 0.003 ms): TaskSchedulerR/10653 prctl(option: SET_NAME, arg2: 0x2b61d2aaa1e0) = 0 3367.244 ( 0.002 ms): TaskSchedulerR/10654 prctl(option: SET_NAME, arg2: 0x2b61d2aaa0c0) = 0 3367.265 ( 0.002 ms): TaskSchedulerR/10655 prctl(option: SET_NAME, arg2: 0x2b61d2ac7f90) = 0 3367.281 ( 0.002 ms): Chrome_ChildIO/10656 prctl(option: SET_NAME, arg2: 0x7efbe406bb11) = 0 3367.220 ( 0.004 ms): TaskSchedulerS/10651 prctl(option: SET_NAME, arg2: 0x2b61d2ac1be0) = 0 3370.906 ( 0.010 ms): GpuMemoryThrea/10657 prctl(option: SET_NAME, arg2: 0x7efbe386ab11) = 0 3370.983 ( 0.003 ms): File/10658 prctl(option: SET_NAME, arg2: 0x7efbe3069b11 ) = 0 3384.272 ( 0.020 ms): Compositor/10659 prctl(option: SET_NAME, arg2: 0x7efbe2868b11 ) = 0 3612.091 ( 0.012 ms): DOM Worker/11489 prctl(option: SET_NAME, arg2: 0x7f49ab97ebf2 ) = 0 <SNIP> 4512.437 ( 0.004 ms): (sa1)/11490 prctl(option: SET_NAME, arg2: 0x7ffca15af844 ) = 0 4512.468 ( 0.002 ms): (sa1)/11490 prctl(option: SET_MM, arg2: ARG_START, arg3: 0x7f5cb7c81000) = 0 4512.472 ( 0.001 ms): (sa1)/11490 prctl(option: SET_MM, arg2: ARG_END, arg3: 0x7f5cb7c81006) = 0 4514.667 ( 0.002 ms): (sa1)/11490 prctl(option: GET_SECUREBITS ) = 0 Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: David Ahern <dsahern@gmail.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/n/tip-q0s2uw579o5ei6xlh2zjirgz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2017-10-27 02:19:35 +08:00
/*
* trace/beauty/prctl.c
*
* Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
*
* Released under the GPL v2. (and only v2, not any later version)
*/
#include "trace/beauty/beauty.h"
#include <linux/kernel.h>
#include <uapi/linux/prctl.h>
#include "trace/beauty/generated/prctl_option_array.c"
static size_t prctl__scnprintf_option(int option, char *bf, size_t size)
{
static DEFINE_STRARRAY(prctl_options);
return strarray__scnprintf(&strarray__prctl_options, bf, size, "%d", option);
}
static size_t prctl__scnprintf_set_mm(int option, char *bf, size_t size)
{
static DEFINE_STRARRAY(prctl_set_mm_options);
return strarray__scnprintf(&strarray__prctl_set_mm_options, bf, size, "%d", option);
}
size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_arg *arg)
{
int option = syscall_arg__val(arg, 0);
if (option == PR_SET_MM)
return prctl__scnprintf_set_mm(arg->val, bf, size);
/*
* We still don't grab the contents of pointers on entry or exit,
* so just print them as hex numbers
*/
if (option == PR_SET_NAME)
return syscall_arg__scnprintf_hex(bf, size, arg);
return syscall_arg__scnprintf_long(bf, size, arg);
}
size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg)
{
int option = syscall_arg__val(arg, 0);
if (option == PR_SET_MM)
return syscall_arg__scnprintf_hex(bf, size, arg);
return syscall_arg__scnprintf_long(bf, size, arg);
}
size_t syscall_arg__scnprintf_prctl_option(char *bf, size_t size, struct syscall_arg *arg)
{
unsigned long option = arg->val;
enum {
SPO_ARG2 = (1 << 1),
SPO_ARG3 = (1 << 2),
SPO_ARG4 = (1 << 3),
SPO_ARG5 = (1 << 4),
SPO_ARG6 = (1 << 5),
};
const u8 all_but2 = SPO_ARG3 | SPO_ARG4 | SPO_ARG5 | SPO_ARG6;
const u8 all = SPO_ARG2 | all_but2;
const u8 masks[] = {
[PR_GET_DUMPABLE] = all,
[PR_SET_DUMPABLE] = all_but2,
[PR_SET_NAME] = all_but2,
[PR_GET_CHILD_SUBREAPER] = all_but2,
[PR_SET_CHILD_SUBREAPER] = all_but2,
[PR_GET_SECUREBITS] = all,
[PR_SET_SECUREBITS] = all_but2,
[PR_SET_MM] = SPO_ARG4 | SPO_ARG5 | SPO_ARG6,
[PR_GET_PDEATHSIG] = all,
[PR_SET_PDEATHSIG] = all_but2,
};
if (option < ARRAY_SIZE(masks))
arg->mask |= masks[option];
return prctl__scnprintf_option(option, bf, size);
}