perf/core improvements and fixes
Subsystems (2)
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit 3906a13a6b4e78fbc0def03a808f091f0dff1b44:
Merge tag 'perf-core-for-mingo-4.12-20170327' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2017-03-28 07:44:43 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-4.12-20170331
for you to fetch changes up to fd5cead23f54697310bd565aa2a23ae5128080a0:
perf trace: Beautify statx syscall 'flag' and 'mask' arguments (2017-03-31 14:42:31 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
New features:
- Beautify the statx syscall arguments in 'perf trace' (Arnaldo Carvalho de Melo)
e.g.:
System wide strace like session:
# trace -e statx 16612.967 ( 0.028 ms): statx/4562 statx(dfd: CWD, filename: /tmp/statx, flags: SYMLINK_NOFOLLOW, mask: TYPE|MODE|NLINK|UID|GID|ATIME|MTIME|CTIME|INO|SIZE|BLOCKS|BTIME, buffer: 0x7ffef195d660) = 0 36050.891 ( 0.007 ms): statx/4576 statx(dfd: CWD, filename: /etc/passwd, flags: SYMLINK_NOFOLLOW|STATX_DONT_SYNC, mask: BTIME, buffer: 0x7ffda9bf50f0) = 0 ^C#
User visible:
- Handle unpaired raw_syscalls:sys_exit events in 'perf trace', i.e. we shouldn't try to calculate duration or print the timestamp for a missing matching raw_syscalls:sys_enter (Arnaldo Carvalho de Melo)
- Do not print "cycles: 0" in perf report LBR lines in platforms not supporting 'cycles', such as Intel's Broadwell (Jin Yao)
- Handle missing $HOME env var (Jiri Olsa)
- Map 8-bit registers (al, bl, etc), not supported in uprobes_events, to the next best thing (ax, bx, etc) supported (Ravi Bangoria)
----------------------------------------------------------------
Arnaldo Carvalho de Melo (4):
perf tools: Remove support for command aliases
perf trace: Handle unpaired raw_syscalls:sys_exit event tools include uapi: Grab copies of stat.h and fcntl.h perf trace: Beautify statx syscall 'flag' and 'mask' arguments
Colin Ian King (1):
perf utils: Fix spelling mistake: "Invalud" -> "Invalid"
Jin Yao (1):
perf report: Drop cycles 0 for LBR print
Jiri Olsa (1):
perf tools: Do not fail in case of empty HOME env variable
Ravi Bangoria (2):
perf/sdt/x86: Add renaming logic for (missing) 8 bit registers perf/sdt/x86: Move OP parser to tools/perf/arch/x86/
tools/include/linux/types.h | 1 + tools/include/uapi/linux/fcntl.h | 72 +++++++++ tools/include/uapi/linux/stat.h | 176 ++++++++++++++++++++ tools/perf/Build | 1 + tools/perf/MANIFEST | 2 + tools/perf/arch/x86/entry/syscalls/syscall_64.tbl | 1 + tools/perf/arch/x86/util/perf_regs.c | 187 ++++++++++++++++++---- tools/perf/builtin-help.c | 13 -- tools/perf/builtin-trace.c | 57 ++++--- tools/perf/check-headers.sh | 2 + tools/perf/perf.c | 97 +---------- tools/perf/trace/beauty/Build | 1 + tools/perf/trace/beauty/beauty.h | 24 +++ tools/perf/trace/beauty/statx.c | 72 +++++++++ tools/perf/util/Build | 1 - tools/perf/util/alias.c | 78 --------- tools/perf/util/cache.h | 1 - tools/perf/util/callchain.c | 111 ++++++++----- tools/perf/util/config.c | 54 ++++--- tools/perf/util/help-unknown-cmd.c | 8 +- tools/perf/util/hist.c | 2 +- tools/perf/util/perf_regs.c | 6 +- tools/perf/util/perf_regs.h | 11 +- tools/perf/util/probe-file.c | 132 +++++---------- 24 files changed, 707 insertions(+), 403 deletions(-) create mode 100644 tools/include/uapi/linux/fcntl.h create mode 100644 tools/include/uapi/linux/stat.h create mode 100644 tools/perf/trace/beauty/Build create mode 100644 tools/perf/trace/beauty/beauty.h create mode 100644 tools/perf/trace/beauty/statx.c delete mode 100644 tools/perf/util/alias.c
Test results:
The first ones are container (docker) based builds of tools/perf with and without libelf support, objtool where it is supported and samples/bpf/, ditto. Where clang is available, it is also used to build perf with/without libelf.
For this specific pull request the samples/bpf/ was disabled, as 'make headers_install' is failing with the following error, in this case in fedora:rawhide:
INSTALL usr/include/uapi/ (0 file)
/git/linux/scripts/Makefile.headersinst:62: *** Missing generated UAPI file ./arch/x86/include/generated/uapi/asm/unistd_32.h. Stop. make[1]: *** [/git/linux/Makefile:1151: headers_install] Error 2
make[1]: Leaving directory '/tmp/build/linux'
make: *** [Makefile:152: sub-make] Error 2
make: Leaving directory '/git/linux'
I'll investigate later, perf and objtool builds just fine, with clang and gcc.
Several are cross builds, the ones with -x-ARCH, and the android one, and those may not have all the features built, due to lack of multi-arch devel packages, available and being used so far on just a few, like debian:experimental-x-{arm64,mipsel}.
The 'perf test' one will perform a variety of tests exercising tools/perf/util/, tools/lib/{bpf,traceevent,etc}, as well as run perf commands with a variety of command line event specifications to then intercept the sys_perf_event syscall to check that the perf_event_attr fields are set up as expected, among a variety of other unit tests.
Then there is the 'make -C tools/perf build-test' ones, that build tools/perf/ with a variety of feature sets, exercising the build with an incomplete set of features as well as with a complete one. It is planned to have it run on each of the containers mentioned above, using some container orchestration infrastructure. Get in contact if interested in helping having this in place.
# dm 1 alpine:3.4: Ok 2 alpine:3.5: Ok 3 alpine:edge: Ok 4 android-ndk:r12b-arm: Ok 5 archlinux:latest: Ok 6 centos:5: Ok 7 centos:6: Ok 8 centos:7: Ok 9 debian:7: Ok 10 debian:8: Ok 11 debian:9: Ok 12 debian:experimental: Ok 13 debian:experimental-x-arm64: Ok 14 debian:experimental-x-mips: Ok 15 debian:experimental-x-mips64: Ok 16 debian:experimental-x-mipsel: Ok 17 fedora:20: Ok 18 fedora:21: Ok 19 fedora:22: Ok 20 fedora:23: Ok 21 fedora:24: Ok 22 fedora:24-x-ARC-uClibc: Ok 23 fedora:25: Ok 24 fedora:rawhide: Ok 25 mageia:5: Ok 26 opensuse:13.2: Ok 27 opensuse:42.1: Ok 28 opensuse:tumbleweed: Ok 29 ubuntu:12.04.5: Ok 30 ubuntu:14.04.4: Ok 31 ubuntu:14.04.4-x-linaro-arm64: Ok 32 ubuntu:15.10: Ok 33 ubuntu:16.04: Ok 34 ubuntu:16.04-x-arm: Ok 35 ubuntu:16.04-x-arm64: Ok 36 ubuntu:16.04-x-powerpc: Ok 37 ubuntu:16.04-x-powerpc64: Ok 38 ubuntu:16.04-x-s390: Ok 39 ubuntu:16.10: Ok 40 ubuntu:17.04: Ok #
# uname -a Linux jouet 4.11.0-rc2+ #5 SMP Mon Mar 20 18:12:29 -03 2017 x86_64 x86_64 x86_64 GNU/Linux # 'perf test tsc' already fixed by peterz in tip # perf test 1: vmlinux symtab matches kallsyms : Ok 2: Detect openat syscall event : Ok 3: Detect openat syscall event on all cpus : Ok 4: Read samples using the mmap interface : Ok 5: Parse event definition strings : Ok 6: Simple expression parser : Ok 7: PERF_RECORD_* events & perf_sample fields : Ok 8: Parse perf pmu format : Ok 9: DSO data read : Ok 10: DSO data cache : Ok 11: DSO data reopen : Ok 12: Roundtrip evsel->name : Ok 13: Parse sched tracepoints fields : Ok 14: syscalls:sys_enter_openat event fields : Ok 15: Setup struct perf_event_attr : Ok 16: Match and link multiple hists : Ok 17: 'import perf' in python : Ok 18: Breakpoint overflow signal handler : Ok 19: Breakpoint overflow sampling : Ok 20: Number of exit events of a simple workload : Ok 21: Software clock events period values : Ok 22: Object code reading : Ok 23: Sample parsing : Ok 24: Use a dummy software event to keep tracking: Ok 25: Parse with no sample_id_all bit set : Ok 26: Filter hist entries : Ok 27: Lookup mmap thread : Ok 28: Share thread mg : Ok 29: Sort output of hist entries : Ok 30: Cumulate child hist entries : Ok 31: Track with sched_switch : Ok 32: Filter fds with revents mask in a fdarray : Ok 33: Add fd to a fdarray, making it autogrow : Ok 34: kmod_path__parse : Ok 35: Thread map : Ok 36: LLVM search and compile : 36.1: Basic BPF llvm compile : Ok 36.2: kbuild searching : Ok 36.3: Compile source for BPF prologue generation: Ok 36.4: Compile source for BPF relocation : Ok 37: Session topology : Ok 38: BPF filter : 38.1: Basic BPF filtering : Ok 38.2: BPF pinning : Ok 38.3: BPF prologue generation : Ok 38.4: BPF relocation checker : Ok 39: Synthesize thread map : Ok 40: Remove thread map : Ok 41: Synthesize cpu map : Ok 42: Synthesize stat config : Ok 43: Synthesize stat : Ok 44: Synthesize stat round : Ok 45: Synthesize attr update : Ok 46: Event times : Ok 47: Read backward ring buffer : Ok 48: Print cpu map : Ok 49: Probe SDT events : Ok 50: is_printable_array : Ok 51: Print bitmap : Ok 52: perf hooks : Ok 53: builtin clang support : Skip (not compiled in) 54: unit_number__scnprintf : Ok 55: x86 rdpmc : Ok 56: Convert perf time to TSC : FAILED! 57: DWARF unwind : Ok 58: x86 instruction decoder - new instructions : Ok 59: Intel cqm nmi context read : Skip
$ make -C tools/perf build-test
make_no_libdw_dwarf_unwind_O: make NO_LIBDW_DWARF_UNWIND=1
make_minimal_O: make NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1
make_no_gtk2_O: make NO_GTK2=1
make_no_newt_O: make NO_NEWT=1
make_debug_O: make DEBUG=1
make_no_backtrace_O: make NO_BACKTRACE=1
make_with_clangllvm_O: make LIBCLANGLLVM=1
make_tags_O: make tags
make_no_demangle_O: make NO_DEMANGLE=1
make_install_bin_O: make install-bin
make_no_libpython_O: make NO_LIBPYTHON=1
make_no_slang_O: make NO_SLANG=1
make_no_auxtrace_O: make NO_AUXTRACE=1
make_util_pmu_bison_o_O: make util/pmu-bison.o
make_no_ui_O: make NO_NEWT=1 NO_SLANG=1 NO_GTK2=1
make_no_scripts_O: make NO_LIBPYTHON=1 NO_LIBPERL=1
make_no_libbpf_O: make NO_LIBBPF=1
make_with_babeltrace_O: make LIBBABELTRACE=1
make_util_map_o_O: make util/map.o
make_static_O: make LDFLAGS=-static
make_help_O: make help
make_pure_O: make
make_perf_o_O: make perf.o
make_no_libnuma_O: make NO_LIBNUMA=1
make_no_libperl_O: make NO_LIBPERL=1
make_no_libunwind_O: make NO_LIBUNWIND=1
make_no_libbionic_O: make NO_LIBBIONIC=1
make_doc_O: make doc
make_no_libelf_O: make NO_LIBELF=1
make_clean_all_O: make clean all
make_install_prefix_O: make install prefix=/tmp/krava
make_no_libaudit_O: make NO_LIBAUDIT=1
make_install_O: make install
make_install_prefix_slash_O: make install prefix=/tmp/krava/
OK
make: Leaving directory '/home/acme/git/linux/tools/perf'
$Arnaldo Carvalho de Melo
maintainerPATCH 1/9 perf tools: Remove support for command aliases
From: Arnaldo Carvalho de Melo <[email protected]>
This came from 'git', but isn't documented anywhere in tools/perf/Documentation/, looks like baggage we can do without, ditch it.
--- tools/perf/builtin-help.c | 13 ----- tools/perf/perf.c | 97 +++----------------------------------- tools/perf/util/Build | 1 - tools/perf/util/alias.c | 78 ------------------------------ tools/perf/util/cache.h | 1 - tools/perf/util/help-unknown-cmd.c | 8 +--- 6 files changed, 8 insertions(+), 190 deletions(-) delete mode 100644 tools/perf/util/alias.c
tools/perf/builtin-help.c +0 -13
@@ -301,12 +301,6 @@ void list_common_cmds_help(void) } } -static int is_perf_command (const char *s) -{ -return is_in_cmdlist (&main_cmds, s) || -is_in_cmdlist (&other_cmds, s); -} -static const char *cmd_to_page (const char *perf_cmd) {char *s;
@@ -446,7 +440,6 @@ int cmd_help(int argc, const char **argv)"perf help [--all] [--man|--web|--info] [command]" , NULL }; -const char *alias;int rc;load_command_list ("perf-" , &main_cmds, &other_cmds);
@@ -472,12 +465,6 @@ int cmd_help(int argc, const char **argv)return 0 ; } - alias =alias_lookup (argv[0 ]); -if (alias && !is_perf_command (argv[0 ])) { -printf ("`perf %s' is aliased to `%s'\n" , argv[0 ], alias); -return 0 ; - } -switch (help_format) {case HELP_FORMAT_MAN : rc =show_man_page (argv[0 ]);
tools/perf/perf.c +7 -90
120 lines not on this page · raw message
tools/perf/util/Build +0 -1
@@ -1,4 +1,3 @@ -libperf-y += alias.o libperf-y += annotate.o libperf-y += block-range.o libperf-y += build-id.o
tools/perf/util/alias.c deleted +0 -78
78 lines not on this page · raw message
tools/perf/util/cache.h +0 -1
@@ -15,7 +15,6 @@#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"#define PERF_PAGER_ENVIRONMENT "PERF_PAGER" -char *alias_lookup (const char *alias);int split_cmdline (char *cmdline,const char ***argv);#define alloc_nr (x) (((x)+16)*3/2)
tools/perf/util/help-unknown-cmd.c +1 -7
@@ -6,16 +6,12 @@#include "levenshtein.h" static int autocorrect; -static struct cmdnames aliases;static int perf_unknown_cmd_config (const char *var,const char *value,void *cb__maybe_unused ) {if (!strcmp (var,"help.autocorrect" )) autocorrect =perf_config_int (var,value); -/* Also use aliases for command lookup */ -if (!prefixcmp (var,"alias." )) -add_cmdname (&aliases, var +6 ,strlen (var +6 ));return 0 ; }
@@ -59,14 +55,12 @@ const char *help_unknown_cmd(const char *cmd)memset (&main_cmds,0 ,sizeof (main_cmds));memset (&other_cmds,0 ,sizeof (main_cmds)); -memset (&aliases,0 ,sizeof (aliases));perf_config (perf_unknown_cmd_config,NULL );load_command_list ("perf-" , &main_cmds, &other_cmds); -if (add_cmd_list (&main_cmds, &aliases) <0 || -add_cmd_list (&main_cmds, &other_cmds) <0 ) { +if (add_cmd_list (&main_cmds, &other_cmds) <0 ) {fprintf (stderr,"ERROR: Failed to allocate command list for unknown command.\n" ); goto end; }
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 2/9 perf/sdt/x86: Add renaming logic for (missing) 8 bit registers
In reply to Arnaldo Carvalho de MeloFrom: Ravi Bangoria <[email protected]>
I found couple of events using al, bl, cl and dl registers for argument. These are not directly accepted by uprobe_events and thus needs to be mapped to ax, bx, cx and dx respectively.
Few ex,
/usr/bin/qemu-system-s390x
css_adapter_interrupt: 1@%bl
css_chpid_add: 1@%cl 1@%sil 1@%dl
dma_bdrv_io: 8@%rbx 8@%rbp -8@%r14 1@%al /usr/bin/postgres
buffer__read__done: ... -1@-bash -1@%al
buffer__read__start: ... -1@%alI don't find any sdt events using ah, bh,... registers. But I also don't see any reason to not use them, so there might be rare events using these registers, and if so, perf should have a renaming logic for them too.
--- tools/perf/arch/x86/util/perf_regs.c | 8 ++++++++ 1 file changed, 8 insertions(+)
tools/perf/arch/x86/util/perf_regs.c +8 -0
@@ -40,12 +40,20 @@ struct sdt_name_reg {static const struct sdt_name_reg sdt_reg_renamings[] = {SDT_NAME_REG (eax, ax),SDT_NAME_REG (rax, ax), +SDT_NAME_REG (al, ax), +SDT_NAME_REG (ah, ax),SDT_NAME_REG (ebx, bx),SDT_NAME_REG (rbx, bx), +SDT_NAME_REG (bl, bx), +SDT_NAME_REG (bh, bx),SDT_NAME_REG (ecx, cx),SDT_NAME_REG (rcx, cx), +SDT_NAME_REG (cl, cx), +SDT_NAME_REG (ch, cx),SDT_NAME_REG (edx, dx),SDT_NAME_REG (rdx, dx), +SDT_NAME_REG (dl, dx), +SDT_NAME_REG (dh, dx),SDT_NAME_REG (esi, si),SDT_NAME_REG (rsi, si),SDT_NAME_REG (sil, si),
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 3/9 perf/sdt/x86: Move OP parser to tools/perf/arch/x86/
In reply to Arnaldo Carvalho de MeloFrom: Ravi Bangoria <[email protected]>
SDT marker argument is in N@OP format. N is the size of argument and OP is the actual assembly operand. OP is arch dependent component and hence it's parsing logic also should be placed under tools/perf/arch/.
--- tools/perf/arch/x86/util/perf_regs.c | 179 ++++++++++++++++++++++++++++------- tools/perf/util/perf_regs.c | 6 +- tools/perf/util/perf_regs.h | 11 ++- tools/perf/util/probe-file.c | 132 ++++++++------------------ 4 files changed, 194 insertions(+), 134 deletions(-)
tools/perf/arch/x86/util/perf_regs.c +147 -32
@@ -1,8 +1,10 @@#include <string.h> +#include <regex.h> #include "../../perf.h" #include "../../util/util.h" #include "../../util/perf_regs.h" +#include "../../util/debug.h" const struct sample_reg sample_reg_masks[] = {SMPL_REG (AX ,PERF_REG_X86_AX ),
@@ -37,7 +39,7 @@ struct sdt_name_reg {#define SDT_NAME_REG (n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL} -static const struct sdt_name_reg sdt_reg_renamings[] = { +static const struct sdt_name_reg sdt_reg_tbl[] = {SDT_NAME_REG (eax, ax),SDT_NAME_REG (rax, ax),SDT_NAME_REG (al, ax),
@@ -95,45 +97,158 @@ static const struct sdt_name_reg sdt_reg_renamings[] = { SDT_NAME_REG_END, }; -int sdt_rename_register (char **pdesc,char *old_name) +/* +* Perf only supports OP which is in +/-NUM(REG) form. +* Here plus-minus sign, NUM and parenthesis are optional, +* only REG is mandatory. +* +* SDT events also supports indirect addressing mode with a +* symbol as offset, scaled mode and constants in OP. But +* perf does not support them yet. Below are few examples. +* +* OP with scaled mode: +* (%rax,%rsi,8) +* 10(%ras,%rsi,8) +* +* OP with indirect addressing mode: +* check_action(%rip) +* mp_+52(%rip) +* 44+mp_(%rip) +* +* OP with constant values: +* $0 +* $123 +* $-1 +*/ +#define SDT_OP_REGEX "^([+\\-]?)([0-9]*)(\\(?)(%[a-z][a-z0-9]+)(\\)?)$" + +static regex_t sdt_op_regex; + +static int sdt_init_op_regex (void ) { -const struct sdt_name_reg *rnames = sdt_reg_renamings; -char *new_desc, *old_desc = *pdesc; -size_t prefix_len, sdt_len, uprobe_len, old_desc_len, offset; -int ret =-1 ; - -while (ret !=0 && rnames->sdt_name !=NULL ) { - sdt_len =strlen (rnames->sdt_name); - ret =strncmp (old_name, rnames->sdt_name, sdt_len); - rnames += !!ret; - } +static int initialized; +int ret =0 ; -if (rnames->sdt_name ==NULL ) +if (initialized)return 0 ; - sdt_len =strlen (rnames->sdt_name); - uprobe_len =strlen (rnames->uprobe_name); - old_desc_len =strlen (old_desc) +1 ; + ret =regcomp (&sdt_op_regex,SDT_OP_REGEX ,REG_EXTENDED ); +if (ret <0 ) { +pr_debug4 ("Regex compilation error.\n" ); +return ret; + } - new_desc =zalloc (old_desc_len + uprobe_len - sdt_len); -if (new_desc ==NULL ) -return -1 ; + initialized =1 ; +return 0 ; +} -/* Copy the chars before the register name (at least '%') */ - prefix_len = old_name - old_desc; -memcpy (new_desc, old_desc, prefix_len); +/* +* Max x86 register name length is 5(ex: %r15d). So, 6th char +* should always contain NULL. This helps to find register name +* length using strlen, insted of maintaing one more variable. +*/ +#define SDT_REG_NAME_SIZE 6 -/* Copy the new register name */ -memcpy (new_desc + prefix_len, rnames->uprobe_name, uprobe_len); +/* +* The uprobe parser does not support all gas register names; +* so, we have to replace them (ex. for x86_64: %rax -> %ax). +* Note: If register does not require renaming, just copy +* paste as it is, but don't leave it empty. +*/ +static void sdt_rename_register (char *sdt_reg,int sdt_len,char *uprobe_reg) +{ +int i =0 ; -/* Copy the chars after the register name (if need be) */ - offset = prefix_len + sdt_len; -if (offset < old_desc_len) -memcpy (new_desc + prefix_len + uprobe_len, - old_desc + offset, old_desc_len - offset); +for (i =0 ; sdt_reg_tbl[i].sdt_name !=NULL ; i++) { +if (!strncmp (sdt_reg_tbl[i].sdt_name, sdt_reg, sdt_len)) { +strcpy (uprobe_reg, sdt_reg_tbl[i].uprobe_name); +return ; + } + } -free (old_desc); - *pdesc = new_desc; +strncpy (uprobe_reg, sdt_reg, sdt_len); +} -return 0 ; +int arch_sdt_arg_parse_op (char *old_op,char **new_op) +{ +char new_reg[SDT_REG_NAME_SIZE ] = {0 }; +int new_len =0 , ret; +/* +* rm[0]: +/-NUM(REG) +* rm[1]: +/- +* rm[2]: NUM +* rm[3]: ( +* rm[4]: REG +* rm[5]: ) +*/ +regmatch_t rm[6 ]; +/* +* Max prefix length is 2 as it may contains sign(+/-) +* and displacement 0 (Both sign and displacement 0 are +* optional so it may be empty). Use one more character +* to hold last NULL so that strlen can be used to find +* prefix length, instead of maintaing one more variable. +*/ +char prefix[3 ] = {0 }; + + ret =sdt_init_op_regex (); +if (ret <0 ) +return ret; + +/* +* If unsupported OR does not match with regex OR +* register name too long, skip it. +*/ +if (strchr (old_op,',' ) ||strchr (old_op,'$' ) || +regexec (&sdt_op_regex, old_op,6 , rm,0 ) || + rm[4 ].rm_eo - rm[4 ].rm_so >SDT_REG_NAME_SIZE ) { +pr_debug4 ("Skipping unsupported SDT argument: %s\n" , old_op); +return SDT_ARG_SKIP ; + } + +/* +* Prepare prefix. +* If SDT OP has parenthesis but does not provide +* displacement, add 0 for displacement. +* SDT Uprobe Prefix +* ----------------------------- +* +24(%rdi) +24(%di) + +* 24(%rdi) +24(%di) + +* %rdi %di +* (%rdi) +0(%di) +0 +* -80(%rbx) -80(%bx) - +*/ +if (rm[3 ].rm_so != rm[3 ].rm_eo) { +if (rm[1 ].rm_so != rm[1 ].rm_eo) + prefix[0 ] = *(old_op + rm[1 ].rm_so); +else if (rm[2 ].rm_so != rm[2 ].rm_eo) + prefix[0 ] ='+' ; +else +strncpy (prefix,"+0" ,2 ); + } + +/* Rename register */ +sdt_rename_register (old_op + rm[4 ].rm_so, rm[4 ].rm_eo - rm[4 ].rm_so, + new_reg); + +/* Prepare final OP which should be valid for uprobe_events */ + new_len =strlen (prefix) + + (rm[2 ].rm_eo - rm[2 ].rm_so) + + (rm[3 ].rm_eo - rm[3 ].rm_so) + +strlen (new_reg) + + (rm[5 ].rm_eo - rm[5 ].rm_so) + +1 ;/* NULL */ + + *new_op =zalloc (new_len); +if (!*new_op) +return -ENOMEM ; + +scnprintf (*new_op, new_len,"%.*s%.*s%.*s%.*s%.*s" , +strlen (prefix), prefix, + (int )(rm[2 ].rm_eo - rm[2 ].rm_so), old_op + rm[2 ].rm_so, + (int )(rm[3 ].rm_eo - rm[3 ].rm_so), old_op + rm[3 ].rm_so, +strlen (new_reg), new_reg, + (int )(rm[5 ].rm_eo - rm[5 ].rm_so), old_op + rm[5 ].rm_so); + +return SDT_ARG_VALID ; }
tools/perf/util/perf_regs.c +3 -3
@@ -6,10 +6,10 @@ const struct sample_reg __weak sample_reg_masks[] = { SMPL_REG_END }; -int __weak sdt_rename_register (char **pdesc__maybe_unused , -char *old_name__maybe_unused ) +int __weak arch_sdt_arg_parse_op (char *old_op__maybe_unused , +char **new_op__maybe_unused ) { -return 0 ; +return SDT_ARG_SKIP ; }#ifdef HAVE_PERF_REGS_SUPPORT
tools/perf/util/perf_regs.h +6 -5
@@ -15,11 +15,12 @@ struct sample_reg {extern const struct sample_reg sample_reg_masks[]; -/* -* The table sdt_reg_renamings is used for adjusting gcc/gas-generated -* registers before filling the uprobe tracer interface. -*/ -int sdt_rename_register (char **pdesc,char *old_name); +enum { +SDT_ARG_VALID =0 , +SDT_ARG_SKIP , +}; + +int arch_sdt_arg_parse_op (char *old_op,char **new_op);#ifdef HAVE_PERF_REGS_SUPPORT #include <perf_regs.h>
tools/perf/util/probe-file.c +38 -94
160 lines not on this page · raw message
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 4/9 perf report: Drop cycles 0 for LBR print
In reply to Arnaldo Carvalho de MeloFrom: Jin Yao <[email protected]>
For some platforms, for example Broadwell, it doesn't support cycles for LBR. But the perf always prints cycles:0, it's not necessary.
The patch refactors the LBR info print code and drops the cycles:0.
For example: perf report --branch-history --no-children --stdio
On Broadwell:
--0.91%--__random_r random_r.c:394 (iterations:2)
__random_r random_r.c:360 (predicted:0.0%)
__random_r random_r.c:380 (predicted:0.0%)
__random_r random_r.c:357On Skylake:
--1.07%--main div.c:39 (predicted:52.4% cycles:1 iterations:17)
main div.c:44 (predicted:52.4% cycles:1)
main div.c:42 (cycles:2)
compute_flag div.c:28 (cycles:2)
compute_flag div.c:27 (cycles:1)
rand rand.c:28 (cycles:1)
rand rand.c:28 (cycles:1)
__random random.c:298 (cycles:1)
__random random.c:297 (cycles:1)
__random random.c:295 (cycles:1)
__random random.c:295 (cycles:1)
__random random.c:295 (cycles:1)--- tools/perf/util/callchain.c | 111 +++++++++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 37 deletions(-)
tools/perf/util/callchain.c +74 -37
@@ -1105,63 +1105,100 @@ int callchain_branch_counts(struct callchain_root *root, cycles_count); } -static int callchain_counts_printf (FILE *fp,char *bf,int bfsize, -u64 branch_count,u64 predicted_count, -u64 abort_count,u64 cycles_count, -u64 iter_count,u64 samples_count) +static int counts_str_build (char *bf,int bfsize, +u64 branch_count,u64 predicted_count, +u64 abort_count,u64 cycles_count, +u64 iter_count,u64 samples_count) {double predicted_percent =0.0 ;const char *null_str ="" ;char iter_str[32 ]; -char *str; -u64 cycles =0 ; - -if (branch_count ==0 ) { -if (fp) -return fprintf (fp," (calltrace)" ); +char cycle_str[32 ]; +char *istr, *cstr; +u64 cycles; +if (branch_count ==0 )return scnprintf (bf, bfsize," (calltrace)" ); - } + + cycles = cycles_count / branch_count;if (iter_count && samples_count) { -scnprintf (iter_str,sizeof (iter_str), -", iterations:%" PRId64"" , - iter_count / samples_count); - str = iter_str; +if (cycles >0 ) +scnprintf (iter_str,sizeof (iter_str), +" iterations:%" PRId64"" , + iter_count / samples_count); +else +scnprintf (iter_str,sizeof (iter_str), +"iterations:%" PRId64"" , + iter_count / samples_count); + istr = iter_str; + }else + istr = (char *)null_str; + +if (cycles >0 ) { +scnprintf (cycle_str,sizeof (cycle_str), +"cycles:%" PRId64"" , cycles); + cstr = cycle_str; }else - str = (char *)null_str; + cstr = (char *)null_str; predicted_percent = predicted_count *100.0 / branch_count; - cycles = cycles_count / branch_count; -if ((predicted_percent >=100.0 ) && (abort_count ==0 )) { -if (fp) -return fprintf (fp," (cycles:%" PRId64"%s)" , - cycles, str); +if ((predicted_count == branch_count) && (abort_count ==0 )) { +if ((cycles >0 ) || (istr != (char *)null_str)) +return scnprintf (bf, bfsize," (%s%s)" , cstr, istr); +else +return scnprintf (bf, bfsize,"%s" , (char *)null_str); + } -return scnprintf (bf, bfsize," (cycles:%" PRId64"%s)" , - cycles, str); +if ((predicted_count < branch_count) && (abort_count ==0 )) { +if ((cycles >0 ) || (istr != (char *)null_str)) +return scnprintf (bf, bfsize, +" (predicted:%.1f%% %s%s)" , + predicted_percent, cstr, istr); +else { +return scnprintf (bf, bfsize, +" (predicted:%.1f%%)" , + predicted_percent); + } } -if ((predicted_percent <100.0 ) && (abort_count ==0 )) { -if (fp) -return fprintf (fp, -" (predicted:%.1f%%, cycles:%" PRId64"%s)" , - predicted_percent, cycles, str); +if ((predicted_count == branch_count) && (abort_count >0 )) { +if ((cycles >0 ) || (istr != (char *)null_str)) +return scnprintf (bf, bfsize, +" (abort:%" PRId64" %s%s)" , + abort_count, cstr, istr); +else +return scnprintf (bf, bfsize, +" (abort:%" PRId64")" , + abort_count); + } +if ((cycles >0 ) || (istr != (char *)null_str))return scnprintf (bf, bfsize, -" (predicted:%.1f%%, cycles:%" PRId64"%s)" , - predicted_percent, cycles, str); - } +" (predicted:%.1f%% abort:%" PRId64" %s%s)" , + predicted_percent, abort_count, cstr, istr); + +return scnprintf (bf, bfsize, +" (predicted:%.1f%% abort:%" PRId64")" , + predicted_percent, abort_count); +} + +static int callchain_counts_printf (FILE *fp,char *bf,int bfsize, +u64 branch_count,u64 predicted_count, +u64 abort_count,u64 cycles_count, +u64 iter_count,u64 samples_count) +{ +char str[128 ]; + +counts_str_build (str,sizeof (str), branch_count, + predicted_count, abort_count, cycles_count, + iter_count, samples_count);if (fp) -return fprintf (fp, -" (predicted:%.1f%%, abort:%" PRId64", cycles:%" PRId64"%s)" , - predicted_percent, abort_count, cycles, str); +return fprintf (fp,"%s" , str); -return scnprintf (bf, bfsize, -" (predicted:%.1f%%, abort:%" PRId64", cycles:%" PRId64"%s)" , - predicted_percent, abort_count, cycles, str); +return scnprintf (bf, bfsize,"%s" , str); } int callchain_list_counts__printf_value(struct callchain_node *node,
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 5/9 perf trace: Handle unpaired raw_syscalls:sys_exit event
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Which may happen when we start a tracing session and a thread is waiting for something like "poll" to return, in which case we better print "?" both for the syscall entry timestamp and for the duration.
E.g.:
Tracing existing mutt session:
# perf trace -p `pidof mutt`
? ( ? ): mutt/17135 ... [continued]: poll()) = 1
0.027 ( 0.013 ms): mutt/17135 read(buf: 0x7ffcb3c42cef, count: 1) = 1
0.047 ( 0.008 ms): mutt/17135 poll(ufds: 0x7ffcb3c42c50, nfds: 1, timeout_msecs: 1000) = 1
0.059 ( 0.008 ms): mutt/17135 read(buf: 0x7ffcb3c42cef, count: 1) = 1
<SNIP>Before it would print a large number because we'd do:
ttrace->entry_time - trace->base_time
And entry_time would be 0, while base_time would be the timestamp for the first event 'perf trace' reads, oops.
--- tools/perf/builtin-trace.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-)
tools/perf/builtin-trace.c +34 -9
@@ -821,12 +821,21 @@ struct syscall {void **arg_parm; }; -static size_t fprintf_duration (unsigned long t,FILE *fp) +/* +* We need to have this 'calculated' boolean because in some cases we really +* don't know what is the duration of a syscall, for instance, when we start +* a session and some threads are waiting for a syscall to finish, say 'poll', +* in which case all we can do is to print "( ? ) for duration and for the +* start timestamp. +*/ +static size_t fprintf_duration (unsigned long t,bool calculated,FILE *fp) {double duration = (double )t /NSEC_PER_MSEC ;size_t printed =fprintf (fp,"(" ); -if (duration >=1.0 ) +if (!calculated) + printed +=fprintf (fp," ? " ); +else if (duration >=1.0 ) printed +=color_fprintf (fp,PERF_COLOR_RED ,"%6.3f ms" , duration);else if (duration >=0.01 ) printed +=color_fprintf (fp,PERF_COLOR_YELLOW ,"%6.3f ms" , duration);
@@ -1028,13 +1037,27 @@ static bool trace__filter_duration(struct trace *trace, double t)return t < (trace->duration_filter *NSEC_PER_MSEC ); } -static size_t trace__fprintf_tstamp (struct trace *trace,u64 tstamp,FILE *fp) +static size_t __trace__fprintf_tstamp (struct trace *trace,u64 tstamp,FILE *fp) {double ts = (double )(tstamp - trace->base_time) /NSEC_PER_MSEC ;return fprintf (fp,"%10.3f " , ts); } +/* +* We're handling tstamp=0 as an undefined tstamp, i.e. like when we are +* using ttrace->entry_time for a thread that receives a sys_exit without +* first having received a sys_enter ("poll" issued before tracing session +* starts, lost sys_enter exit due to ring buffer overflow). +*/ +static size_t trace__fprintf_tstamp (struct trace *trace,u64 tstamp,FILE *fp) +{ +if (tstamp >0 ) +return __trace__fprintf_tstamp (trace, tstamp, fp); + +return fprintf (fp," ? " ); +} +static bool done = false;static bool interrupted = false;
@@ -1045,10 +1068,10 @@ static void sig_handler(int sig) }static size_t trace__fprintf_entry_head (struct trace *trace,struct thread *thread, -u64 duration,u64 tstamp,FILE *fp) +u64 duration,bool duration_calculated,u64 tstamp,FILE *fp) {size_t printed =trace__fprintf_tstamp (trace, tstamp, fp); - printed +=fprintf_duration (duration, fp); + printed +=fprintf_duration (duration, duration_calculated, fp);if (trace->multiple_threads) {if (trace->show_comm)
@@ -1450,7 +1473,7 @@ static int trace__printf_interrupted_entry(struct trace *trace, struct perf_samp duration = sample->time - ttrace->entry_time; - printed =trace__fprintf_entry_head (trace, trace->current, duration, ttrace->entry_time, trace->output); + printed =trace__fprintf_entry_head (trace, trace->current, duration, true, ttrace->entry_time, trace->output); printed +=fprintf (trace->output,"%-70s) ...\n" , ttrace->entry_str); ttrace->entry_pending = false;
@@ -1497,7 +1520,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,if (sc->is_exit) {if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { -trace__fprintf_entry_head (trace, thread,1 , ttrace->entry_time, trace->output); +trace__fprintf_entry_head (trace, thread,0 , false, ttrace->entry_time, trace->output);fprintf (trace->output,"%-70s)\n" , ttrace->entry_str); } }else {
@@ -1545,6 +1568,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, {long ret;u64 duration =0 ; +bool duration_calculated = false;struct thread *thread;int id =perf_evsel__sc_tp_uint (evsel, id, sample), err =-1 , callchain_ret =0 ;struct syscall *sc =trace__syscall_info (trace, evsel, id);
@@ -1573,6 +1597,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, duration = sample->time - ttrace->entry_time;if (trace__filter_duration (trace, duration)) goto out; + duration_calculated = true; }else if (trace->duration_filter) goto out;
@@ -1588,7 +1613,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,if (trace->summary_only) goto out; -trace__fprintf_entry_head (trace, thread, duration, ttrace->entry_time, trace->output); +trace__fprintf_entry_head (trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output);if (ttrace->entry_pending) {fprintf (trace->output,"%-70s" , ttrace->entry_str);
@@ -1855,7 +1880,7 @@ static int trace__pgfault(struct trace *trace,thread__find_addr_location (thread, sample->cpumode,MAP__FUNCTION , sample->ip, &al); -trace__fprintf_entry_head (trace, thread,0 , sample->time, trace->output); +trace__fprintf_entry_head (trace, thread,0 , true, sample->time, trace->output); fprintf(trace->output, "%sfault [", evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 6/9 perf utils: Fix spelling mistake: "Invalud" -> "Invalid"
In reply to Arnaldo Carvalho de MeloFrom: Colin Ian King <[email protected]>
Trivial fix to spelling mistake in pr_debug message.
--- tools/perf/util/hist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/hist.c +1 -1
@@ -2459,7 +2459,7 @@ int parse_filter_percentage(const struct option *opt __maybe_unused,else if (!strcmp (arg,"absolute" )) symbol_conf.filter_relative = false;else { -pr_debug ("Invalud percentage: %s\n" , arg); +pr_debug ("Invalid percentage: %s\n" , arg);return -1 ; }
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 7/9 tools include uapi: Grab copies of stat.h and fcntl.h
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We will need it to build tools/perf/trace/beauty/statx.h.
--- tools/include/linux/types.h | 1 + tools/include/uapi/linux/fcntl.h | 72 ++++++++++++++++ tools/include/uapi/linux/stat.h | 176 +++++++++++++++++++++++++++++++++++++++ tools/perf/MANIFEST | 2 + tools/perf/check-headers.sh | 2 + 5 files changed, 253 insertions(+) create mode 100644 tools/include/uapi/linux/fcntl.h create mode 100644 tools/include/uapi/linux/stat.h
tools/include/linux/types.h +1 -0
@@ -7,6 +7,7 @@#define __SANE_USERSPACE_TYPES__/* For PPC64, to get LL64 types */ #include <asm/types.h> +#include <asm/posix_types.h> struct page ;struct kmem_cache ;
tools/include/uapi/linux/fcntl.h new file +72 -0
72 lines not on this page · raw message
tools/include/uapi/linux/stat.h new file +176 -0
176 lines not on this page · raw message
tools/perf/MANIFEST +2 -0
@@ -73,9 +73,11 @@ tools/include/uapi/asm-generic/mman-common.h tools/include/uapi/asm-generic/mman.h tools/include/uapi/linux/bpf.h tools/include/uapi/linux/bpf_common.h +tools/include/uapi/linux/fcntl.h tools/include/uapi/linux/hw_breakpoint.h tools/include/uapi/linux/mman.h tools/include/uapi/linux/perf_event.h +tools/include/uapi/linux/stat.h tools/include/linux/poison.h tools/include/linux/rbtree.h tools/include/linux/rbtree_augmented.h
tools/perf/check-headers.sh +2 -0
@@ -1,7 +1,9 @@ #!/bin/sh HEADERS=' +include/uapi/linux/fcntl.h include/uapi/linux/perf_event.h +include/uapi/linux/stat.h include/linux/hash.h include/uapi/linux/hw_breakpoint.h arch/x86/include/asm/disabled-features.h
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 8/9 perf tools: Do not fail in case of empty HOME env variable
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Currently we fail in the following case:
$ unset HOME $ ./perf record ls $ echo $? 255
It's because the config code init fails due to a missing HOME variable value. Fix this by skipping the user config init if there's no HOME variable value.
--- tools/perf/util/config.c | 54 +++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 23 deletions(-)
tools/perf/util/config.c +31 -23
@@ -627,6 +627,8 @@ static int perf_config_set__init(struct perf_config_set *set) {int ret =-1 ;const char *home =NULL ; +char *user_config; +struct stat st;/* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ if (config_exclusive_filename)
@@ -637,35 +639,41 @@ static int perf_config_set__init(struct perf_config_set *set) } home =getenv ("HOME" ); -if (perf_config_global () && home) { -char *user_config =strdup (mkpath ("%s/.perfconfig" , home)); -struct stat st; -if (user_config ==NULL ) { -warning ("Not enough memory to process %s/.perfconfig, " -"ignoring it." , home); - goto out; - } +/* +* Skip reading user config if: +* - there is no place to read it from (HOME) +* - we are asked not to (PERF_CONFIG_NOGLOBAL=1) +*/ +if (!home || !*home || !perf_config_global ()) +return 0 ; -if (stat (user_config, &st) <0 ) { -if (errno ==ENOENT ) - ret =0 ; - goto out_free; - } + user_config =strdup (mkpath ("%s/.perfconfig" , home)); +if (user_config ==NULL ) { +warning ("Not enough memory to process %s/.perfconfig, " +"ignoring it." , home); + goto out; + } + +if (stat (user_config, &st) <0 ) { +if (errno ==ENOENT ) + ret =0 ; + goto out_free; + } - ret =0 ; + ret =0 ; -if (st.st_uid && (st.st_uid !=geteuid ())) { -warning ("File %s not owned by current user or root, " -"ignoring it." , user_config); - goto out_free; - } +if (st.st_uid && (st.st_uid !=geteuid ())) { +warning ("File %s not owned by current user or root, " +"ignoring it." , user_config); + goto out_free; + } + +if (st.st_size) + ret =perf_config_from_file (collect_config, user_config, set); -if (st.st_size) - ret =perf_config_from_file (collect_config, user_config, set); out_free: -free (user_config); - } +free (user_config); out:return ret; }
Signature · 1 line
2.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 9/9 perf trace: Beautify statx syscall 'flag' and 'mask' arguments
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
To test it, build samples/statx/test_statx, which I did as:
$ make headers_install $ cc -I ~/git/linux/usr/include samples/statx/test-statx.c -o /tmp/statx
And then use perf trace on it:
# perf trace -e statx /tmp/statx /etc/passwd
statx(/etc/passwd) = 0
results=7ff
Size: 3496 Blocks: 8 IO Block: 4096 regular file
Device: fd:00 Inode: 280156 Links: 1
Access: (0644/-rw-r--r--) Uid: 0 Gid: 0
Access: 2017-03-29 16:01:01.650073438-0300
Modify: 2017-03-10 16:25:14.156479354-0300
Change: 2017-03-10 16:25:14.171479328-0300
0.000 ( 0.007 ms): statx/30648 statx(dfd: CWD, filename: 0x7ef503f4, flags: SYMLINK_NOFOLLOW, mask: TYPE|MODE|NLINK|UID|GID|ATIME|MTIME|CTIME|INO|SIZE|BLOCKS|BTIME, buffer: 0x7fff7ef4eb10) = 0
#Using the test-stat.c options to change the mask:
# perf trace -e statx /tmp/statx -O /etc/passwd > /dev/null
0.000 ( 0.008 ms): statx/30745 statx(dfd: CWD, filename: 0x3a0753f4, flags: SYMLINK_NOFOLLOW, mask: BTIME, buffer: 0x7ffd3a0735c0) = 0
#
# perf trace -e statx /tmp/statx -A /etc/passwd > /dev/null
0.000 ( 0.010 ms): statx/30757 statx(dfd: CWD, filename: 0xa94e63f4, flags: SYMLINK_NOFOLLOW|NO_AUTOMOUNT, mask: TYPE|MODE|NLINK|UID|GID|ATIME|MTIME|CTIME|INO|SIZE|BLOCKS|BTIME, buffer: 0x7ffea94e49d0) = 0
#
# trace --no-inherit -e statx /tmp/statx -F /etc/passwd > /dev/null
0.000 ( 0.011 ms): statx(dfd: CWD, filename: 0x3b02d3f3, flags: SYMLINK_NOFOLLOW|STATX_FORCE_SYNC, mask: TYPE|MODE|NLINK|UID|GID|ATIME|MTIME|CTIME|INO|SIZE|BLOCKS|BTIME, buffer: 0x7ffd3b02c850) = 0
#
# trace --no-inherit -e statx /tmp/statx -F -L /etc/passwd > /dev/null
0.000 ( 0.008 ms): statx(dfd: CWD, filename: 0x15cff3f3, flags: STATX_FORCE_SYNC, mask: TYPE|MODE|NLINK|UID|GID|ATIME|MTIME|CTIME|INO|SIZE|BLOCKS|BTIME, buffer: 0x7fff15cfdda0) = 0
#
# trace --no-inherit -e statx /tmp/statx -D -O /etc/passwd > /dev/null
0.000 ( 0.009 ms): statx(dfd: CWD, filename: 0xfa37f3f3, flags: SYMLINK_NOFOLLOW|STATX_DONT_SYNC, mask: BTIME, buffer: 0x7ffffa37da20) = 0
#Adding a probe to get the filename collected as well:
# perf probe 'vfs_getname=getname_flags:72 pathname=result->name:string'
Added new event:
probe:vfs_getname (on getname_flags:72 with pathname=result->name:string)You can now use it in all perf tools, such as:
perf record -e probe:vfs_getname -aR sleep 1
# trace --no-inherit -e statx /tmp/statx -D -O /etc/passwd > /dev/null
0.169 ( 0.007 ms): statx(dfd: CWD, filename: /etc/passwd, flags: SYMLINK_NOFOLLOW|STATX_DONT_SYNC, mask: BTIME, buffer: 0x7ffda9bf50f0) = 0
#Same technique could be used to collect and beautify the result put in the 'buffer' argument.
Finally do a system wide 'perf trace' session looking for any use of statx, then run the test proggie with various flags:
# trace -e statx 16612.967 ( 0.028 ms): statx/4562 statx(dfd: CWD, filename: /tmp/statx, flags: SYMLINK_NOFOLLOW, mask: TYPE|MODE|NLINK|UID|GID|ATIME|MTIME|CTIME|INO|SIZE|BLOCKS|BTIME, buffer: 0x7ffef195d660) = 0 33064.447 ( 0.011 ms): statx/4569 statx(dfd: CWD, filename: /tmp/statx, flags: SYMLINK_NOFOLLOW|STATX_FORCE_SYNC, mask: TYPE|MODE|NLINK|UID|GID|ATIME|MTIME|CTIME|INO|SIZE|BLOCKS|BTIME, buffer: 0x7ffc5484c790) = 0 36050.891 ( 0.023 ms): statx/4576 statx(dfd: CWD, filename: /tmp/statx, flags: SYMLINK_NOFOLLOW, mask: BTIME, buffer: 0x7ffeb18b66e0) = 0 38039.889 ( 0.023 ms): statx/4584 statx(dfd: CWD, filename: /tmp/statx, flags: SYMLINK_NOFOLLOW, mask: TYPE|MODE|NLINK|UID|GID|ATIME|MTIME|CTIME|INO|SIZE|BLOCKS|BTIME, buffer: 0x7fff1db0ea90) = 0 ^C#
This one also starts moving the beautifiers from files directly included in builtin-trace.c to separate objects + a beauty.h header with prototypes, so that we can add test cases in tools/perf/tests/ to fire syscalls with various arguments and then get them intercepted as syscalls:sys_enter_foo or raw_syscalls:sys_enter + sys_exit to then format and check that the formatted output is the one we expect.
--- tools/perf/Build | 1 + tools/perf/arch/x86/entry/syscalls/syscall_64.tbl | 1 + tools/perf/builtin-trace.c | 14 ++--- tools/perf/trace/beauty/Build | 1 + tools/perf/trace/beauty/beauty.h | 24 ++++++++ tools/perf/trace/beauty/statx.c | 72 +++++++++++++++++++++++ 6 files changed, 104 insertions(+), 9 deletions(-) create mode 100644 tools/perf/trace/beauty/Build create mode 100644 tools/perf/trace/beauty/beauty.h create mode 100644 tools/perf/trace/beauty/statx.c
tools/perf/Build +1 -0
@@ -50,5 +50,6 @@ libperf-y += util/ libperf-y += arch/ libperf-y += ui/ libperf-y += scripts/ +libperf-y += trace/beauty/ gtk-y += ui/gtk/
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl +1 -0
@@ -338,6 +338,7 @@ 329 common pkey_mprotect sys_pkey_mprotect 330 common pkey_alloc sys_pkey_alloc 331 common pkey_free sys_pkey_free +332 common statx sys_statx # # x32-specific system call numbers start at 512 to avoid cache impact
tools/perf/builtin-trace.c +5 -9
@@ -31,6 +31,7 @@#include "util/intlist.h" #include "util/thread_map.h" #include "util/stat.h" +#include "trace/beauty/beauty.h" #include "trace-event.h" #include "util/parse-events.h" #include "util/bpf-loader.h"
@@ -267,15 +268,6 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void ({struct syscall_tp *fields = evsel->priv; \ fields->name.pointer(&fields->name, sample); }) -struct syscall_arg { -unsigned long val; -struct thread *thread; -struct trace *trace; -void *parm; -u8 idx; -u8 mask; -}; -struct strarray {int offset;int nr_entries;
@@ -771,6 +763,10 @@ static struct syscall_fmt { .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, { .name = "stat", .errmsg = true, .alias = "newstat", }, { .name = "statfs", .errmsg = true, }, + { .name = "statx", .errmsg = true, + .arg_scnprintf = { [0] = SCA_FDAT, /* flags */ + [2] = SCA_STATX_FLAGS, /* flags */ + [3] = SCA_STATX_MASK, /* mask */ }, }, { .name = "swapoff", .errmsg = true, .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, { .name = "swapon", .errmsg = true,
tools/perf/trace/beauty/Build new file +1 -0
@@ -0,0 +1 @@ +libperf-y += statx.o
tools/perf/trace/beauty/beauty.h new file +24 -0
@@ -0,0 +1,24 @@ +#ifndef _PERF_TRACE_BEAUTY_H +#define _PERF_TRACE_BEAUTY_H + +#include <linux/types.h> + +struct trace ; +struct thread ; + +struct syscall_arg { +unsigned long val; +struct thread *thread; +struct trace *trace; +void *parm; +u8 idx; +u8 mask; +}; + +size_t syscall_arg__scnprintf_statx_flags (char *bf,size_t size,struct syscall_arg *arg); +#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags + +size_t syscall_arg__scnprintf_statx_mask (char *bf,size_t size,struct syscall_arg *arg); +#define SCA_STATX_MASK syscall_arg__scnprintf_statx_mask + +#endif /* _PERF_TRACE_BEAUTY_H */
tools/perf/trace/beauty/statx.c new file +72 -0
72 lines not on this page · raw message
Signature · 1 line
2.9.3
Quoted 95 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit
3906a13a6b4e78fbc0def03a808f091f0dff1b44:Merge tag 'perf-core-for-mingo-4.12-20170327' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxinto perf/core (2017-03-28 07:44:43 +0200)are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingo-4.12-20170331for you to fetch changes up to
fd5cead23f54697310bd565aa2a23ae5128080a0:perf trace: Beautify statx syscall 'flag' and 'mask' arguments (2017-03-31 14:42:31 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:New features:
- Beautify the statx syscall arguments in 'perf trace' (Arnaldo Carvalho de Melo)
e.g.:System wide strace like session:
# trace -e statx 16612.967 ( 0.028 ms): statx/4562 statx(dfd: CWD, filename: /tmp/statx, flags: SYMLINK_NOFOLLOW, mask: TYPE|MODE|NLINK|UID|GID|ATIME|MTIME|CTIME|INO|SIZE|BLOCKS|BTIME, buffer: 0x7ffef195d660) = 0 36050.891 ( 0.007 ms): statx/4576 statx(dfd: CWD, filename: /etc/passwd, flags: SYMLINK_NOFOLLOW|STATX_DONT_SYNC, mask: BTIME, buffer: 0x7ffda9bf50f0) = 0 ^C#User visible:
- Handle unpaired raw_syscalls:sys_exit events in 'perf trace', i.e. we shouldn't try to calculate duration or print the timestamp for a missing matching raw_syscalls:sys_enter (Arnaldo Carvalho de Melo)
- Do not print "cycles: 0" in perf report LBR lines in platforms not supporting 'cycles', such as Intel's Broadwell (Jin Yao)
- Handle missing $HOME env var (Jiri Olsa)
- Map 8-bit registers (al, bl, etc), not supported in
uprobes_events, to the next best thing (ax, bx, etc) supported (Ravi Bangoria)Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Arnaldo Carvalho de Melo (4):
perf tools: Remove support for command aliases
perf trace: Handle unpaired raw_syscalls:sys_exit event tools include uapi: Grab copies ofstat.handfcntl.hperf trace: Beautify statx syscall 'flag' and 'mask' argumentsColin Ian King (1):
perf utils: Fix spelling mistake: "Invalud" -> "Invalid"Jin Yao (1):
perf report: Drop cycles 0 for LBR printJiri Olsa (1):
perf tools: Do not fail in case of empty HOME env variableRavi Bangoria (2):
perf/sdt/x86: Add renaming logic for (missing) 8 bit registers perf/sdt/x86: Move OP parser totools/perf/arch/x86/tools/include/linux/types.h | 1 + tools/include/uapi/linux/fcntl.h | 72 +++++++++ tools/include/uapi/linux/stat.h | 176 ++++++++++++++++++++ tools/perf/Build | 1 + tools/perf/MANIFEST | 2 + tools/perf/arch/x86/entry/syscalls/syscall_64.tbl | 1 + tools/perf/arch/x86/util/perf_regs.c | 187 ++++++++++++++++++---- tools/perf/builtin-help.c | 13 -- tools/perf/builtin-trace.c | 57 ++++--- tools/perf/check-headers.sh | 2 + tools/perf/perf.c | 97 +---------- tools/perf/trace/beauty/Build | 1 + tools/perf/trace/beauty/beauty.h | 24 +++ tools/perf/trace/beauty/statx.c | 72 +++++++++ tools/perf/util/Build | 1 - tools/perf/util/alias.c | 78 --------- tools/perf/util/cache.h | 1 - tools/perf/util/callchain.c | 111 ++++++++----- tools/perf/util/config.c | 54 ++++--- tools/perf/util/help-unknown-cmd.c | 8 +- tools/perf/util/hist.c | 2 +- tools/perf/util/perf_regs.c | 6 +- tools/perf/util/perf_regs.h | 11 +-
Quoted 8 lines
tools/perf/util/probe-file.c | 132 +++++---------- 24 files changed, 707 insertions(+), 403 deletions(-) create mode 100644 tools/include/uapi/linux/fcntl.h create mode 100644 tools/include/uapi/linux/stat.h create mode 100644 tools/perf/trace/beauty/Build create mode 100644 tools/perf/trace/beauty/beauty.h create mode 100644 tools/perf/trace/beauty/statx.c delete mode 100644 tools/perf/util/alias.c
Pulled, thanks a lot Arnaldo!
Ingo