linux/tools/perf/trace/beauty/prctl.c
Arnaldo Carvalho de Melo d688d0376c 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 09:10:10 -03:00

83 lines
2.3 KiB
C

/*
* 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);
}