diff options
64 files changed, 842 insertions, 252 deletions
diff --git a/tools/arch/x86/include/uapi/asm/prctl.h b/tools/arch/x86/include/uapi/asm/prctl.h new file mode 100644 index 000000000000..5a6aac9fa41f --- /dev/null +++ b/tools/arch/x86/include/uapi/asm/prctl.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_X86_PRCTL_H +#define _ASM_X86_PRCTL_H + +#define ARCH_SET_GS 0x1001 +#define ARCH_SET_FS 0x1002 +#define ARCH_GET_FS 0x1003 +#define ARCH_GET_GS 0x1004 + +#define ARCH_GET_CPUID 0x1011 +#define ARCH_SET_CPUID 0x1012 + +#define ARCH_MAP_VDSO_X32 0x2001 +#define ARCH_MAP_VDSO_32 0x2002 +#define ARCH_MAP_VDSO_64 0x2003 + +#endif /* _ASM_X86_PRCTL_H */ diff --git a/tools/include/uapi/asm-generic/unistd.h b/tools/include/uapi/asm-generic/unistd.h index 538546edbfbd..c7f3321fbe43 100644 --- a/tools/include/uapi/asm-generic/unistd.h +++ b/tools/include/uapi/asm-generic/unistd.h @@ -760,8 +760,10 @@ __SYSCALL(__NR_rseq, sys_rseq) #define __NR_ftruncate __NR3264_ftruncate #define __NR_lseek __NR3264_lseek #define __NR_sendfile __NR3264_sendfile +#if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64) #define __NR_newfstatat __NR3264_fstatat #define __NR_fstat __NR3264_fstat +#endif #define __NR_mmap __NR3264_mmap #define __NR_fadvise64 __NR3264_fadvise64 #ifdef __NR3264_stat @@ -776,8 +778,10 @@ __SYSCALL(__NR_rseq, sys_rseq) #define __NR_ftruncate64 __NR3264_ftruncate #define __NR_llseek __NR3264_lseek #define __NR_sendfile64 __NR3264_sendfile +#if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64) #define __NR_fstatat64 __NR3264_fstatat #define __NR_fstat64 __NR3264_fstat +#endif #define __NR_mmap2 __NR3264_mmap #define __NR_fadvise64_64 __NR3264_fadvise64 #ifdef __NR3264_stat diff --git a/tools/include/uapi/linux/fadvise.h b/tools/include/uapi/linux/fadvise.h new file mode 100644 index 000000000000..0862b87434c2 --- /dev/null +++ b/tools/include/uapi/linux/fadvise.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef FADVISE_H_INCLUDED +#define FADVISE_H_INCLUDED + +#define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +#define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +#define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +#define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ + +/* + * The advise values for POSIX_FADV_DONTNEED and POSIX_ADV_NOREUSE + * for s390-64 differ from the values for the rest of the world. + */ +#if defined(__s390x__) +#define POSIX_FADV_DONTNEED 6 /* Don't need these pages. */ +#define POSIX_FADV_NOREUSE 7 /* Data will be accessed once. */ +#else +#define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +#define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + +#endif /* FADVISE_H_INCLUDED */ diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile index 95563b8e1ad7..ed61fb3a46c0 100644 --- a/tools/lib/subcmd/Makefile +++ b/tools/lib/subcmd/Makefile @@ -36,8 +36,6 @@ endif CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE CFLAGS += -I$(srctree)/tools/include/ -CFLAGS += -I$(srctree)/include/uapi -CFLAGS += -I$(srctree)/include SUBCMD_IN := $(OUTPUT)libsubcmd-in.o diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 67fe5d7ef190..941761d9923d 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -177,7 +177,7 @@ $(TE_IN): force $(Q)$(MAKE) $(build)=libtraceevent $(OUTPUT)libtraceevent.so.$(EVENT_PARSE_VERSION): $(TE_IN) - $(QUIET_LINK)$(CC) --shared $^ -Wl,-soname,libtraceevent.so.$(EP_VERSION) -o $@ + $(QUIET_LINK)$(CC) --shared $(LDFLAGS) $^ -Wl,-soname,libtraceevent.so.$(EP_VERSION) -o $@ @ln -sf $(@F) $(OUTPUT)libtraceevent.so @ln -sf $(@F) $(OUTPUT)libtraceevent.so.$(EP_VERSION) @@ -196,7 +196,7 @@ $(PLUGINS_IN): force $(Q)$(MAKE) $(build)=$(plugin_obj) $(OUTPUT)%.so: $(OUTPUT)%-in.o - $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $^ + $(QUIET_LINK)$(CC) $(CFLAGS) -shared $(LDFLAGS) -nostartfiles -o $@ $^ define make_version.h (echo '/* This file is automatically generated. Do not modify. */'; \ diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index a5ed291b8a9f..69a96e39f0ab 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -4973,6 +4973,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_e if (arg->type == TEP_PRINT_BSTRING) { trace_seq_puts(s, arg->string.string); + arg = arg->next; break; } diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index 661b1fb3f8ba..4ac7775fbc11 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -521,6 +521,38 @@ diff.*:: Possible values are 'delta', 'delta-abs', 'ratio' and 'wdiff'. Default is 'delta'. +trace.*:: + trace.add_events:: + Allows adding a set of events to add to the ones specified + by the user, or use as a default one if none was specified. + The initial use case is to add augmented_raw_syscalls.o to + activate the 'perf trace' logic that looks for syscall + pointer contents after the normal tracepoint payload. + + trace.args_alignment:: + Number of columns to align the argument list, default is 70, + use 40 for the strace default, zero to no alignment. + + trace.no_inherit:: + Do not follow children threads. + + trace.show_arg_names:: + Should syscall argument names be printed? If not then trace.show_zeros + will be set. + + trace.show_duration:: + Show syscall duration. + + trace.show_prefix:: + If set to 'yes' will show common string prefixes in tables. The default + is to remove the common prefix in things like "MAP_SHARED", showing just "SHARED". + + trace.show_timestamp:: + Show syscall start timestamp. + + trace.show_zeros:: + Do not suppress syscall arguments that are equal to zero. + SEE ALSO -------- linkperf:perf[1] diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index e113450503d2..631e687be4eb 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -205,6 +205,12 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. because the file may be huge. A time out is needed in such cases. This option sets the time out limit. The default value is 500 ms. +--sort-events:: + Do sorting on batches of events, use when noticing out of order events that + may happen, for instance, when a thread gets migrated to a different CPU + while processing a syscall. + + PAGEFAULTS ---------- diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index b66f97a04b12..07c1857c3d7a 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -294,6 +294,8 @@ ifndef NO_BIONIC $(call feature_check,bionic) ifeq ($(feature-bionic), 1) BIONIC := 1 + CFLAGS += -DLACKS_SIGQUEUE_PROTOTYPE + CFLAGS += -DLACKS_OPEN_MEMSTREAM_PROTOTYPE EXTLIBS := $(filter-out -lrt,$(EXTLIBS)) EXTLIBS := $(filter-out -lpthread,$(EXTLIBS)) endif diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index bfdaefd500ab..bd23e3f30895 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -396,6 +396,7 @@ SHELL = $(SHELL_PATH) linux_uapi_dir := $(srctree)/tools/include/uapi/linux asm_generic_uapi_dir := $(srctree)/tools/include/uapi/asm-generic arch_asm_uapi_dir := $(srctree)/tools/arch/$(SRCARCH)/include/uapi/asm/ +x86_arch_asm_uapi_dir := $(srctree)/tools/arch/x86/include/uapi/asm/ beauty_outdir := $(OUTPUT)trace/beauty/generated beauty_ioctl_outdir := $(beauty_outdir)/ioctl @@ -409,6 +410,12 @@ _dummy := $(shell [ -d '$(beauty_ioctl_outdir)' ] || mkdir -p '$(beauty_ioctl_ou $(drm_ioctl_array): $(drm_hdr_dir)/drm.h $(drm_hdr_dir)/i915_drm.h $(drm_ioctl_tbl) $(Q)$(SHELL) '$(drm_ioctl_tbl)' $(drm_hdr_dir) > $@ +fadvise_advice_array := $(beauty_outdir)/fadvise_advice_array.c +fadvise_advice_tbl := $(srctree)/tools/perf/trace/beauty/fadvise.sh + +$(fadvise_advice_array): $(linux_uapi_dir)/in.h $(fadvise_advice_tbl) + $(Q)$(SHELL) '$(fadvise_advice_tbl)' $(linux_uapi_dir) > $@ + pkey_alloc_access_rights_array := $(beauty_outdir)/pkey_alloc_access_rights_array.c asm_generic_hdr_dir := $(srctree)/tools/include/uapi/asm-generic/ pkey_alloc_access_rights_tbl := $(srctree)/tools/perf/trace/beauty/pkey_alloc_access_rights.sh @@ -490,6 +497,18 @@ prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh $(prctl_option_array): $(prctl_hdr_dir)/prctl.h $(prctl_option_tbl) $(Q)$(SHELL) '$(prctl_option_tbl)' $(prctl_hdr_dir) > $@ +x86_arch_prctl_code_array := $(beauty_outdir)/x86_arch_prctl_code_array.c +x86_arch_prctl_code_tbl := $(srctree)/tools/perf/trace/beauty/x86_arch_prctl.sh + +$(x86_arch_prctl_code_array): $(x86_arch_asm_uapi_dir)/prctl.h $(x86_arch_prctl_code_tbl) + $(Q)$(SHELL) '$(x86_arch_prctl_code_tbl)' $(x86_arch_asm_uapi_dir) > $@ + +rename_flags_array := $(beauty_outdir)/rename_flags_array.c +rename_flags_tbl := $(srctree)/tools/perf/trace/beauty/rename_flags.sh + +$(rename_flags_array): $(linux_uapi_dir)/fs.h $(rename_flags_tbl) + $(Q)$(SHELL) '$(rename_flags_tbl)' $(linux_uapi_dir) > $@ + arch_errno_name_array := $(beauty_outdir)/arch_errno_name_array.c arch_errno_hdr_dir := $(srctree)/tools arch_errno_tbl := $(srctree)/tools/perf/trace/beauty/arch_errno_names.sh @@ -592,6 +611,7 @@ __build-dir = $(subst $(OUTPUT),,$(dir $@)) build-dir = $(if $(__build-dir),$(__build-dir),.) prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioctl_array) \ + $(fadvise_advice_array) \ $(pkey_alloc_access_rights_array) \ $(sndrv_pcm_ioctl_array) \ $(sndrv_ctl_ioctl_array) \ @@ -604,6 +624,8 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc $(mount_flags_array) \ $(perf_ioctl_array) \ $(prctl_option_array) \ + $(x86_arch_prctl_code_array) \ + $(rename_flags_array) \ $(arch_errno_name_array) $(OUTPUT)%.o: %.c prepare FORCE @@ -647,7 +669,7 @@ $(LIBJVMTI_IN): FORCE $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=jvmti obj=jvmti $(OUTPUT)$(LIBJVMTI): $(LIBJVMTI_IN) - $(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $< + $(QUIET_LINK)$(CC) $(LDFLAGS) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $< endif $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h) @@ -887,6 +909,7 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea $(OUTPUT)util/intel-pt-decoder/inat-tables.c \ $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \ $(OUTPUT)pmu-events/pmu-events.c \ + $(OUTPUT)$(fadvise_advice_array) \ $(OUTPUT)$(madvise_behavior_array) \ $(OUTPUT)$(mmap_flags_array) \ $(OUTPUT)$(mount_flags_array) \ @@ -900,6 +923,8 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea $(OUTPUT)$(vhost_virtio_ioctl_array) \ $(OUTPUT)$(perf_ioctl_array) \ $(OUTPUT)$(prctl_option_array) \ + $(OUTPUT)$(x86_arch_prctl_code_array) \ + $(OUTPUT)$(rename_flags_array) \ $(OUTPUT)$(arch_errno_name_array) $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c index 514f70f95b57..d76f831f94c7 100644 --- a/tools/perf/builtin-config.c +++ b/tools/perf/builtin-config.c @@ -196,6 +196,7 @@ int cmd_config(int argc, const char **argv) pr_err("Error: takes no arguments\n"); parse_options_usage(config_usage, config_options, "l", 1); } else { +do_action_list: if (show_config(set) < 0) { pr_err("Nothing configured, " "please check your %s \n", config_filename); @@ -204,10 +205,8 @@ int cmd_config(int argc, const char **argv) } break; default: - if (!argc) { - usage_with_options(config_usage, config_options); - break; - } + if (!argc) + goto do_action_list; for (i = 0; argv[i]; i++) { char *var, *value; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index a635abfa77b6..1410d66192f7 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -709,7 +709,7 @@ static int parse_metric_groups(const struct option *opt, return metricgroup__parse_groups(opt, str, &stat_config.metric_events); } -static const struct option stat_options[] = { +static struct option stat_options[] = { OPT_BOOLEAN('T', "transaction", &transaction_run, "hardware transaction statistics"), OPT_CALLBACK('e', "event", &evsel_list, "event", @@ -1599,6 +1599,12 @@ int cmd_stat(int argc, const char **argv) return -ENOMEM; parse_events__shrink_config_terms(); + + /* String-parsing callback-based options would segfault when negated */ + set_option_flag(stat_options, 'e', "event", PARSE_OPT_NONEG); + set_option_flag(stat_options, 'M', "metrics", PARSE_OPT_NONEG); + set_option_flag(stat_options, 'G', "cgroup", PARSE_OPT_NONEG); + argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands, (const char **) stat_usage, PARSE_OPT_STOP_AT_NON_OPTION); diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index a827919c6263..775b99833e51 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -43,6 +43,10 @@ #include "util/data.h" #include "util/debug.h" +#ifdef LACKS_OPEN_MEMSTREAM_PROTOTYPE +FILE *open_memstream(char **ptr, size_t *sizeloc); +#endif + #define SUPPORT_OLD_POWER_EVENTS 1 #define PWR_EVENT_EXIT -1 diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 366ec3c8f580..ebde59e61133 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -22,6 +22,7 @@ #include "builtin.h" #include "util/cgroup.h" #include "util/color.h" +#include "util/config.h" #include "util/debug.h" #include "util/env.h" #include "util/event.h" @@ -76,6 +77,7 @@ struct trace { struct { int max; struct syscall *table; + struct bpf_map *map; struct { struct perf_evsel *sys_enter, *sys_exit, @@ -110,6 +112,7 @@ struct trace { } stats; unsigned int max_stack; unsigned int min_stack; + bool sort_events; bool raw_augmented_syscalls; bool not_ev_qualifier; bool live; @@ -124,6 +127,12 @@ struct trace { bool show_tool_stats; bool trace_syscalls; bool kernel_syscallchains; + s16 args_alignment; + bool show_tstamp; + bool show_duration; + bool show_zeros; + bool show_arg_names; + bool show_string_prefix; bool force; bool vfs_getname; int trace_pgfaults; @@ -352,21 +361,25 @@ out_delete: ({ struct syscall_tp *fields = evsel->priv; \ fields->name.pointer(&fields->name, sample); }) -size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val) +size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, bool show_prefix, int val) { int idx = val - sa->offset; - if (idx < 0 || idx >= sa->nr_entries || sa->entries[idx] == NULL) - return scnprintf(bf, size, intfmt, val); + if (idx < 0 || idx >= sa->nr_entries || sa->entries[idx] == NULL) { + size_t printed = scnprintf(bf, size, intfmt, val); + if (show_prefix) + printed += scnprintf(bf + printed, size - printed, " /* %s??? */", sa->prefix); + return printed; + } - return scnprintf(bf, size, "%s", sa->entries[idx]); + return scnprintf(bf, size, "%s%s", show_prefix ? sa->prefix : "", sa->entries[idx]); } static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size, const char *intfmt, struct syscall_arg *arg) { - return strarray__scnprintf(arg->parm, bf, size, intfmt, arg->val); + return strarray__scnprintf(arg->parm, bf, size, intfmt, arg->show_string_prefix, arg->val); } static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size, @@ -377,34 +390,32 @@ static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size, #define SCA_STRARRAY syscall_arg__scnprintf_strarray -struct strarrays { - int nr_entries; - struct strarray **entries; -}; - -#define DEFINE_STRARRAYS(array) struct strarrays strarrays__##array = { \ - .nr_entries = ARRAY_SIZE(array), \ - .entries = array, \ -} - -size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, - struct syscall_arg *arg) +size_t strarrays__scnprintf(struct strarrays *sas, char *bf, size_t size, const char *intfmt, bool show_prefix, int val) { - struct strarrays *sas = arg->parm; + size_t printed; int i; for (i = 0; i < sas->nr_entries; ++i) { struct strarray *sa = sas->entries[i]; - int idx = arg->val - sa->offset; + int idx = val - sa->offset; if (idx >= 0 && idx < sa->nr_entries) { if (sa->entries[idx] == NULL) break; - return scnprintf(bf, size, "%s", sa->entries[idx]); + return scnprintf(bf, size, "%s%s", show_prefix ? sa->prefix : "", sa->entries[idx]); } } - return scnprintf(bf, size, "%d", arg->val); + printed = scnprintf(bf, size, intfmt, val); + if (show_prefix) + printed += scnprintf(bf + printed, size - printed, " /* %s??? */", sas->entries[0]->prefix); + return printed; +} + +size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size, + struct syscall_arg *arg) +{ + return strarrays__scnprintf(arg->parm, bf, size, "%d", arg->show_string_prefix, arg->val); } #ifndef AT_FDCWD @@ -415,9 +426,10 @@ static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size, struct syscall_arg *arg) { int fd = arg->val; + const char *prefix = "AT_FD"; if (fd == AT_FDCWD) - return scnprintf(bf, size, "CWD"); + return scnprintf(bf, size, "%s%s", arg->show_string_prefix ? prefix : "", "CWD"); return syscall_arg__scnprintf_fd(bf, size, arg); } @@ -434,6 +446,13 @@ size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg return scnprintf(bf, size, "%#lx", arg->val); } +size_t syscall_arg__scnprintf_ptr(char *bf, size_t size, struct syscall_arg *arg) +{ + if (arg->val == 0) + return scnprintf(bf, size, "NULL"); + return syscall_arg__scnprintf_hex(bf, size, arg); +} + size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg) { return scnprintf(bf, size, "%d", arg->val); @@ -448,13 +467,13 @@ static const char *bpf_cmd[] = { "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM", "MAP_GET_NEXT_KEY", "PROG_LOAD", }; -static DEFINE_STRARRAY(bpf_cmd); +static DEFINE_STRARRAY(bpf_cmd, "BPF_"); static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", }; -static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1); +static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, "EPOLL_CTL_", 1); static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", }; -static DEFINE_STRARRAY(itimers); +static DEFINE_STRARRAY(itimers, "ITIMER_"); static const char *keyctl_options[] = { "GET_KEYRING_ID", "JOIN_SESSION_KEYRING", "UPDATE", "REVOKE", "CHOWN", @@ -463,7 +482,7 @@ static const char *keyctl_options[] = { "ASSUME_AUTHORITY", "GET_SECURITY", "SESSION_TO_PARENT", "REJECT", "INSTANTIATE_IOV", "INVALIDATE", "GET_PERSISTENT", }; -static DEFINE_STRARRAY(keyctl_options); +static DEFINE_STRARRAY(keyctl_options, "KEYCTL_"); static const char *whences[] = { "SET", "CUR", "END", #ifdef SEEK_DATA @@ -473,7 +492,7 @@ static const char *whences[] = { "SET", "CUR", "END", "HOLE", #endif }; -static DEFINE_STRARRAY(whences); +static DEFINE_STRARRAY(whences, "SEEK_"); static const char *fcntl_cmds[] = { "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK", @@ -481,7 +500,7 @@ static const char *fcntl_cmds[] = { "SETLK64", "SETLKW64", "SETOWN_EX", "GETOWN_EX", "GETOWNER_UIDS", }; -static DEFINE_STRARRAY(fcntl_cmds); +static DEFINE_STRARRAY(fcntl_cmds, "F_"); static const char *fcntl_linux_specific_cmds[] = { "SETLEASE", "GETLEASE", "NOTIFY", [5] = "CANCELLK", "DUPFD_CLOEXEC", @@ -489,7 +508,7 @@ static const char *fcntl_linux_specific_cmds[] = { "GET_RW_HINT", "SET_RW_HINT", "GET_FILE_RW_HINT", "SET_FILE_RW_HINT", }; -static DEFINE_STRARRAY_OFFSET(fcntl_linux_specific_cmds, F_LINUX_SPECIFIC_BASE); +static DEFINE_STRARRAY_OFFSET(fcntl_linux_specific_cmds, "F_", F_LINUX_SPECIFIC_BASE); static struct strarray *fcntl_cmds_arrays[] = { &strarray__fcntl_cmds, @@ -503,29 +522,31 @@ static const char *rlimit_resources[] = { "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO", "RTTIME", }; -static DEFINE_STRARRAY(rlimit_resources); +static DEFINE_STRARRAY(rlimit_resources, "RLIMIT_"); static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", }; -static DEFINE_STRARRAY(sighow); +static DEFINE_STRARRAY(sighow, "SIG_"); static const char *clockid[] = { "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID", "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE", "BOOTTIME", "REALTIME_ALARM", "BOOTTIME_ALARM", "SGI_CYCLE", "TAI" }; -static DEFINE_STRARRAY(clockid); +static DEFINE_STRARRAY(clockid, "CLOCK_"); static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *suffix = "_OK"; size_t printed = 0; int mode = arg->val; if (mode == F_OK) /* 0 */ - return scnprintf(bf, size, "F"); + return scnprintf(bf, size, "F%s", show_prefix ? suffix : ""); #define P_MODE(n) \ if (mode & n##_OK) { \ - printed += scnprintf(bf + printed, size - printed, "%s", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s", #n, show_prefix ? suffix : ""); \ mode &= ~n##_OK; \ } @@ -550,11 +571,13 @@ static size_t syscall_arg__scnprintf_filename(char *bf, size_t size, static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "O_"; int printed = 0, flags = arg->val; #define P_FLAG(n) \ if (flags & O_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ flags &= ~O_##n; \ } @@ -580,11 +603,13 @@ static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size, static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "GRND_"; int printed = 0, flags = arg->val; #define P_FLAG(n) \ if (flags & GRND_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ flags &= ~GRND_##n; \ } @@ -639,12 +664,15 @@ static struct syscall_fmt { } syscall_fmts[] = { { .name = "access", .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, }, + { .name = "arch_prctl", + .arg = { [0] = { .scnprintf = SCA_X86_ARCH_PRCTL_CODE, /* code */ }, + [1] = { .scnprintf = SCA_PTR, /* arg2 */ }, }, }, { .name = "bind", .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ }, }, }, { .name = "bpf", .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, }, { .name = "brk", .hexret = true, - .arg = { [0] = { .scnprintf = SCA_HEX, /* brk */ }, }, }, + .arg = { [0] = { .scnprintf = SCA_PTR, /* brk */ }, }, }, { .name = "clock_gettime", .arg = { [0] = STRARRAY(clk_id, clockid), }, }, { .name = "clone", .errpid = true, .nr_args = 5, @@ -722,18 +750,14 @@ static struct syscall_fmt { .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, }, { .name = "mknodat", .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, }, - { .name = "mlock", - .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, }, - { .name = "mlockall", - .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, }, { .name = "mmap", .hexret = true, /* The standard mmap maps to old_mmap on s390x */ #if defined(__s390x__) .alias = "old_mmap", #endif - .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, - [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, - [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, }, + .arg = { [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, + [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, + [5] = { .scnprintf = SCA_HEX, /* offset */ }, }, }, { .name = "mount", .arg = { [0] = { .scnprintf = SCA_FILENAME, /* dev_name */ }, [3] = { .scnprintf = SCA_MOUNT_FLAGS, /* flags */ @@ -744,13 +768,7 @@ static struct syscall_fmt { { .name = "mq_unlink", .arg = { [0] = { .scnprintf = SCA_FILENAME, /* u_name */ }, }, }, { .name = "mremap", .hexret = true, - .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, - [3] = { .scnprintf = SCA_MREMAP_FLAGS, /* flags */ }, - [4] = { .scnprintf = SCA_HEX, /* new_addr */ }, }, }, - { .name = "munlock", - .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, }, - { .name = "munmap", - .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, }, + .arg = { [3] = { .scnprintf = SCA_MREMAP_FLAGS, /* flags */ }, }, }, { .name = "name_to_handle_at", .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, }, { .name = "newfstatat", @@ -779,7 +797,7 @@ static struct syscall_fmt { [3] = { .scnprintf = SCA_INT, /* pkey */ }, }, }, { .name = "poll", .timeout = true, }, { .name = "ppoll", .timeout = true, }, - { .name = "prctl", .alias = "arch_prctl", + { .name = "prctl", .arg = { [0] = { .scnprintf = SCA_PRCTL_OPTION, /* option */ }, [1] = { .scnprintf = SCA_PRCTL_ARG2, /* arg2 */ }, [2] = { .scnprintf = SCA_PRCTL_ARG3, /* arg3 */ }, }, }, @@ -797,7 +815,12 @@ static struct syscall_fmt { { .name = "recvmsg", .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, }, { .name = "renameat", - .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, }, + .arg = { [0] = { .scnprintf = SCA_FDAT, /* olddirfd */ }, + [2] = { .scnprintf = SCA_FDAT, /* newdirfd */ }, }, }, + { .name = "renameat2", + .arg = { [0] = { .scnprintf = SCA_FDAT, /* olddirfd */ }, + [2] = { .scnprintf = SCA_FDAT, /* newdirfd */ }, + [4] = { .scnprintf = SCA_RENAMEAT2_FLAGS, /* flags */ }, }, }, { .name = "rt_sigaction", .arg = { [0] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, { .name = "rt_sigprocmask", @@ -901,6 +924,10 @@ struct syscall { struct syscall_arg_fmt *arg_fmt; }; +struct bpf_map_syscall_entry { + bool enabled; +}; + /* * 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 @@ -1132,7 +1159,7 @@ static size_t syscall_arg__scnprintf_augmented_string(struct syscall_arg *arg, c { struct augmented_arg *augmented_arg = arg->augmented.args; - return scnprintf(bf, size, "%.*s", augmented_arg->size, augmented_arg->value); + return scnprintf(bf, size, "\"%.*s\"", augmented_arg->size, augmented_arg->value); } static size_t syscall_arg__scnprintf_filename(char *bf, size_t size, @@ -1201,8 +1228,12 @@ static size_t trace__fprintf_comm_tid(struct trace *trace, struct thread *thread static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread, u64 duration, bool duration_calculated, u64 tstamp, FILE *fp) { - size_t printed = trace__fprintf_tstamp(trace, tstamp, fp); - printed += fprintf_duration(duration, duration_calculated, fp); + size_t printed = 0; + + if (trace->show_tstamp) + printed = trace__fprintf_tstamp(trace, tstamp, fp); + if (trace->show_duration) + printed += fprintf_duration(duration, duration_calculated, fp); return printed + trace__fprintf_comm_tid(trace, thread, fp); } @@ -1321,8 +1352,8 @@ static int syscall__set_arg_fmts(struct syscall *sc) strcmp(field->name, "path") == 0 || strcmp(field->name, "pathname") == 0)) sc->arg_fmt[idx].scnprintf = SCA_FILENAME; - else if (field->flags & TEP_FIELD_IS_POINTER) - sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex; + else if ((field->flags & TEP_FIELD_IS_POINTER) || strstr(field->name, "addr")) + sc->arg_fmt[idx].scnprintf = SCA_PTR; else if (strcmp(field->type, "pid_t") == 0) sc->arg_fmt[idx].scnprintf = SCA_PID; else if (strcmp(field->type, "umode_t") == 0) @@ -1555,6 +1586,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, .mask = 0, .trace = trace, .thread = thread, + .show_string_prefix = trace->show_string_prefix, }; struct thread_trace *ttrace = thread__priv(thread); @@ -1586,6 +1618,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, * strarray for it. */ if (val == 0 && + !trace->show_zeros && !(sc->arg_fmt && (sc->arg_fmt[arg.idx].show_zero || sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAY || @@ -1593,8 +1626,11 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, sc->arg_fmt[arg.idx].parm)) continue; - printed += scnprintf(bf + printed, size - printed, - "%s%s: ", printed ? ", " : "", field->name); + printed += scnprintf(bf + printed, size - printed, "%s", printed ? ", " : ""); + + if (trace->show_arg_names) + printed += scnprintf(bf + printed, size - printed, "%s: ", field->name); + printed += syscall__scnprintf_val(sc, bf + printed, size - printed, &arg, val); } } else if (IS_ERR(sc->tp_format)) { @@ -1707,7 +1743,7 @@ static int trace__printf_interrupted_entry(struct trace *trace) return 0; printed = trace__fprintf_entry_head(trace, trace->current, 0, false, ttrace->entry_time, trace->output); - printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str); + printed += fprintf(trace->output, ")%-*s ...\n", trace->args_alignment, ttrace->entry_str); ttrace->entry_pending = false; ++trace->nr_events_printed; @@ -1764,7 +1800,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, { char *msg; void *args; - size_t printed = 0; + int printed = 0; struct thread *thread; int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; int augmented_args_size = 0; @@ -1813,8 +1849,13 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, if (sc->is_exit) { if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) { + int alignment = 0; + trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output); - fprintf(trace->output, "%-70s)\n", ttrace->entry_str); + printed = fprintf(trace->output, "%s)", ttrace->entry_str); + if (trace->args_alignment > printed) + alignment = trace->args_alignment - printed; + fprintf(trace->output, "%*s= ?\n", alignment, " "); } } else { ttrace->entry_pending = true; @@ -1909,7 +1950,8 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, 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; + int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0; + int alignment = trace->args_alignment; struct syscall *sc = trace__syscall_info(trace, evsel, id); struct thread_trace *ttrace; @@ -1957,28 +1999,37 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, 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); + printed = fprintf(trace->output, "%s", ttrace->entry_str); } else { fprintf(trace->output, " ... ["); color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued"); fprintf(trace->output, "]: %s()", sc->name); } + printed++; /* the closing ')' */ + + if (alignment > printed) + alignment -= printed; + else + alignment = 0; + + fprintf(trace->output, ")%*s= ", alignment, " "); + if (sc->fmt == NULL) { if (ret < 0) goto errno_print; signed_print: - fprintf(trace->output, ") = %ld", ret); + fprintf(trace->output, "%ld", ret); } else if (ret < 0) { errno_print: { char bf[STRERR_BUFSIZE]; const char *emsg = str_error_r(-ret, bf, sizeof(bf)), *e = errno_to_name(evsel, -ret); - fprintf(trace->output, ") = -1 %s %s", e, emsg); + fprintf(trace->output, "-1 %s (%s)", e, emsg); } } else if (ret == 0 && sc->fmt->timeout) - fprintf(trace->output, ") = 0 Timeout"); + fprintf(trace->output, "0 (Timeout)"); else if (ttrace->ret_scnprintf) { char bf[1024]; struct syscall_arg arg = { @@ -1988,14 +2039,14 @@ errno_print: { }; ttrace->ret_scnprintf(bf, sizeof(bf), &arg); ttrace->ret_scnprintf = NULL; - fprintf(trace->output, ") = %s", bf); + fprintf(trace->output, "%s", bf); } else if (sc->fmt->hexret) - fprintf(trace->output, ") = %#lx", ret); + fprintf(trace->output, "%#lx", ret); else if (sc->fmt->errpid) { struct thread *child = machine__find_thread(trace->host, ret, ret); if (child != NULL) { - fprintf(trace->output, ") = %ld", ret); + fprintf(trace->output, "%ld", ret); if (child->comm_set) fprintf(trace->output, " (%s)", thread__comm_str(child)); thread__put(child); @@ -2176,7 +2227,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, trace__printf_interrupted_entry(trace); trace__fprintf_tstamp(trace, sample->time, trace->output); - if (trace->trace_syscalls) + if (trace->trace_syscalls && trace->show_duration) fprintf(trace->output, "( ): "); if (thread) @@ -2547,7 +2598,7 @@ out_delete_sys_enter: goto out; } -static int trace__set_ev_qualifier_filter(struct trace *trace) +static int trace__set_ev_qualifier_tp_filter(struct trace *trace) { int err = -1; struct perf_evsel *sys_exit; @@ -2572,6 +2623,72 @@ out_enomem: goto out; } +#ifdef HAVE_LIBBPF_SUPPORT +static int trace__set_ev_qualifier_bpf_filter(struct trace *trace) +{ + int fd = bpf_map__fd(trace->syscalls.map); + struct bpf_map_syscall_entry value = { + .enabled = !trace->not_ev_qualifier, + }; + int err = 0; + size_t i; + + for (i = 0; i < trace->ev_qualifier_ids.nr; ++i) { + int key = trace->ev_qualifier_ids.entries[i]; + + err = bpf_map_update_elem(fd, &key, &value, BPF_EXIST); + if (err) + break; + } + + return err; +} + +static int __trace__init_syscalls_bpf_map(struct trace *trace, bool enabled) +{ + int fd = bpf_map__fd(trace->syscalls.map); + struct bpf_map_syscall_entry value = { + .enabled = enabled, + }; + int err = 0, key; + + for (key = 0; key < trace->sctbl->syscalls.nr_entries; ++key) { + err = bpf_map_update_elem(fd, &key, &value, BPF_ANY); + if (err) + break; + } + + return err; +} + +static int trace__init_syscalls_bpf_map(struct trace *trace) +{ + bool enabled = true; + + if (trace->ev_qualifier_ids.nr) + enabled = trace->not_ev_qualifier; + + return __trace__init_syscalls_bpf_map(trace, enabled); +} +#else +static int trace__set_ev_qualifier_bpf_filter(struct trace *trace __maybe_unused) +{ + return 0; +} + +static int trace__init_syscalls_bpf_map(struct trace *trace __maybe_unused) +{ + return 0; +} +#endif // HAVE_LIBBPF_SUPPORT + +static int trace__set_ev_qualifier_filter(struct trace *trace) +{ + if (trace->syscalls.map) + return trace__set_ev_qualifier_bpf_filter(trace); + return trace__set_ev_qualifier_tp_filter(trace); +} + static int bpf_map__set_filter_pids(struct bpf_map *map __maybe_unused, size_t npids __maybe_unused, pid_t *pids __maybe_unused) { @@ -2641,7 +2758,7 @@ static int trace__set_filter_pids(struct trace *trace) return err; } -static int trace__deliver_event(struct trace *trace, union perf_event *event) +static int __trace__deliver_event(struct trace *trace, union perf_event *event) { struct perf_evlist *evlist = trace->evlist; struct perf_sample sample; @@ -2656,7 +2773,7 @@ static int trace__deliver_event(struct trace *trace, union perf_event *event) return 0; } -static int trace__flush_ordered_events(struct trace *trace) +static int __trace__flush_events(struct trace *trace) { u64 first = ordered_events__first_time(&trace->oe.data); u64 flush = trace->oe.last - NSEC_PER_SEC; @@ -2668,12 +2785,19 @@ static int trace__flush_ordered_events(struct trace *trace) return 0; } -static int trace__deliver_ordered_event(struct trace *trace, union perf_event *event) +static int trace__flush_events(struct trace *trace) +{ + return !trace->sort_events ? 0 : __trace__flush_events(trace); +} + +static int trace__deliver_event(struct trace *trace, union perf_event *event) { - struct perf_evlist *evlist = trace->evlist; int err; - err = perf_evlist__parse_sample_timestamp(evlist, event, &trace->oe.last); + if (!trace->sort_events) + return __trace__deliver_event(trace, event); + + err = perf_evlist__parse_sample_timestamp(trace->evlist, event, &trace->oe.last); if (err && err != -1) return err; @@ -2681,7 +2805,7 @@ static int trace__deliver_ordered_event(struct trace *trace, union perf_event *e if (err) return err; - return trace__flush_ordered_events(trace); + return trace__flush_events(trace); } static int ordered_events__deliver_event(struct ordered_events *oe, @@ -2689,7 +2813,7 @@ static int ordered_events__deliver_event(struct ordered_events *oe, { struct trace *trace = container_of(oe, struct trace, oe.data); - return trace__deliver_event(trace, event->event); + return __trace__deliver_event(trace, event->event); } static int trace__run(struct trace *trace, int argc, const char **argv) @@ -2703,11 +2827,13 @@ static int trace__run(struct trace *trace, int argc, const char **argv) trace->live = true; - if (trace->trace_syscalls && trace__add_syscall_newtp(trace)) - goto out_error_raw_syscalls; + if (!trace->raw_augmented_syscalls) { + if (trace->trace_syscalls && trace__add_syscall_newtp(trace)) + goto out_error_raw_syscalls; - if (trace->trace_syscalls) - trace->vfs_getname = perf_evlist__add_vfs_getname(evlist); + if (trace->trace_syscalls) + trace->vfs_getname = perf_evlist__add_vfs_getname(evlist); + } if ((trace->trace_pgfaults & TRACE_PFMAJ)) { pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ); @@ -2802,13 +2928,18 @@ static int trace__run(struct trace *trace, int argc, const char **argv) if (err < 0) goto out_error_mem; + if (trace->syscalls.map) + trace__init_syscalls_bpf_map(trace); + if (trace->ev_qualifier_ids.nr > 0) { err = trace__set_ev_qualifier_filter(trace); if (err < 0) goto out_errno; - pr_debug("event qualifier tracepoint filter: %s\n", - trace->syscalls.events.sys_exit->filter); + if (trace->syscalls.events.sys_exit) { + pr_debug("event qualifier tracepoint filter: %s\n", + trace->syscalls.events.sys_exit->filter); + } } err = perf_evlist__apply_filters(evlist, &evsel); @@ -2859,7 +2990,7 @@ again: while ((event = perf_mmap__read_event(md)) != NULL) { ++trace->nr_events; - err = trace__deliver_ordered_event(trace, event); + err = trace__deliver_event(trace, event); if (err) goto out_disable; @@ -2885,7 +3016,7 @@ again: goto again; } else { - if (trace__flush_ordered_events(trace)) + if (trace__flush_events(trace)) goto out_disable; } } else { @@ -2897,7 +3028,8 @@ out_disable: perf_evlist__disable(evlist); - ordered_events__flush(&trace->oe.data, OE_FLUSH__FINAL); + if (trace->sort_events) + ordered_events__flush(&trace->oe.data, OE_FLUSH__FINAL); if (!err) { if (trace->summary) @@ -3426,6 +3558,49 @@ static void trace__set_bpf_map_filtered_pids(struct trace *trace) trace->filter_pids.map = bpf__find_map_by_name("pids_filtered"); } +static void trace__set_bpf_map_syscalls(struct trace *trace) +{ + trace->syscalls.map = bpf__find_map_by_name("syscalls"); +} + +static int trace__config(const char *var, const char *value, void *arg) +{ + struct trace *trace = arg; + int err = 0; + + if (!strcmp(var, "trace.add_events")) { + struct option o = OPT_CALLBACK('e', "event", &trace->evlist, "event", + "event selector. use 'perf list' to list available events", + parse_events_option); + err = parse_events_option(&o, value, 0); + } else if (!strcmp(var, "trace.show_timestamp")) { + trace->show_tstamp = perf_config_bool(var, value); + } else if (!strcmp(var, "trace.show_duration")) { + trace->show_duration = perf_config_bool(var, value); + } else if (!strcmp(var, "trace.show_arg_names")) { + trace->show_arg_names = perf_config_bool(var, value); + if (!trace->show_arg_names) + trace->show_zeros = true; + } else if (!strcmp(var, "trace.show_zeros")) { + bool new_show_zeros = perf_config_bool(var, value); + if (!trace->show_arg_names && !new_show_zeros) { + pr_warning("trace.show_zeros has to be set when trace.show_arg_names=no\n"); + goto out; + } + trace->show_zeros = new_show_zeros; + } else if (!strcmp(var, "trace.show_prefix")) { + trace->show_string_prefix = perf_config_bool(var, value); + } else if (!strcmp(var, "trace.no_inherit")) { + trace->opts.no_inherit = perf_config_bool(var, value); + } else if (!strcmp(var, "trace.args_alignment")) { + int args_alignment = 0; + if (perf_config_int(&args_alignment, var, value) == 0) + trace->args_alignment = args_alignment; + } +out: + return err; +} + int cmd_trace(int argc, const char **argv) { const char *trace_usage[] = { @@ -3451,6 +3626,10 @@ int cmd_trace(int argc, const char **argv) }, .output = stderr, .show_comm = true, + .show_tstamp = true, + .show_duration = true, + .show_arg_names = true, + .args_alignment = 70, .trace_syscalls = false, .kernel_syscallchains = false, .max_stack = UINT_MAX, @@ -3516,6 +3695,8 @@ int cmd_trace(int argc, const char **argv) "Set the maximum stack depth when parsing the callchain, " "anything beyond the specified depth will be ignored. " "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)), + OPT_BOOLEAN(0, "sort-events", &trace.sort_events, + "Sort batch of events before processing, use if getting out of order events"), OPT_BOOLEAN(0, "print-sample", &trace.print_sample, "print the PERF_RECORD_SAMPLE PERF_SAMPLE_ info, for debugging"), OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout, @@ -3546,6 +3727,10 @@ int cmd_trace(int argc, const char **argv) goto out; } + err = perf_config(trace__config, &trace); + if (err) + goto out; + argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands, trace_usage, PARSE_OPT_STOP_AT_NON_OPTION); @@ -3564,6 +3749,7 @@ int cmd_trace(int argc, const char **argv) if (evsel) { trace.syscalls.events.augmented = evsel; trace__set_bpf_map_filtered_pids(&trace); + trace__set_bpf_map_syscalls(&trace); } err = bpf__setup_stdout(trace.evlist); @@ -3609,8 +3795,10 @@ int cmd_trace(int argc, const char **argv) } } - ordered_events__init(&trace.oe.data, ordered_events__deliver_event, &trace); - ordered_events__set_copy_on_queue(&trace.oe.data, true); + if (trace.sort_events) { + ordered_events__init(&trace.oe.data, ordered_events__deliver_event, &trace); + ordered_events__set_copy_on_queue(&trace.oe.data, true); + } /* * If we are augmenting syscalls, then combine what we put in the diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh index 9531f7bd7d9b..8e811ea0cf85 100755 --- a/tools/perf/check-headers.sh +++ b/tools/perf/check-headers.sh @@ -4,6 +4,7 @@ HEADERS=' include/uapi/drm/drm.h include/uapi/drm/i915_drm.h +include/uapi/linux/fadvise.h include/uapi/linux/fcntl.h include/uapi/linux/fs.h include/uapi/linux/kcmp.h @@ -21,6 +22,7 @@ include/uapi/linux/hw_breakpoint.h arch/x86/include/asm/disabled-features.h arch/x86/include/asm/required-features.h arch/x86/include/asm/cpufeatures.h +arch/x86/include/uapi/asm/prctl.h arch/arm/include/uapi/asm/perf_regs.h arch/arm64/include/uapi/asm/perf_regs.h arch/powerpc/include/uapi/asm/perf_regs.h diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c index 74ce7574073d..53c233370fae 100644 --- a/tools/perf/examples/bpf/augmented_raw_syscalls.c +++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c @@ -14,7 +14,6 @@ * code that will combine entry/exit in a strace like way. */ -#include <stdio.h> #include <unistd.h> #include <pid_filter.h> @@ -26,6 +25,17 @@ struct bpf_map SEC("maps") __augmented_syscalls__ = { .max_entries = __NR_CPUS__, }; +struct syscall { + bool enabled; +}; + +struct bpf_map SEC("maps") syscalls = { + .type = BPF_MAP_TYPE_ARRAY, + .key_size = sizeof(int), + .value_size = sizeof(struct syscall), + .max_entries = 512, +}; + struct syscall_enter_args { unsigned long long common_tp_fields; long syscall_nr; @@ -45,6 +55,7 @@ struct augmented_filename { }; #define SYS_OPEN 2 +#define SYS_ACCESS 21 #define SYS_OPENAT 257 pid_filter(pids_filtered); @@ -56,6 +67,7 @@ int sys_enter(struct syscall_enter_args *args) struct syscall_enter_args args; struct augmented_filename filename; } augmented_args; + struct syscall *syscall; unsigned int len = sizeof(augmented_args); const void *filename_arg = NULL; @@ -63,6 +75,10 @@ int sys_enter(struct syscall_enter_args *args) return 0; probe_read(&augmented_args.args, sizeof(augmented_args.args), args); + + syscall = bpf_map_lookup_elem(&syscalls, &augmented_args.args.syscall_nr); + if (syscall == NULL || !syscall->enabled) + return 0; /* * Yonghong and Edward Cree sayz: * @@ -104,6 +120,7 @@ int sys_enter(struct syscall_enter_args *args) * after the ctx memory access to prevent their down stream merging. */ switch (augmented_args.args.syscall_nr) { + case SYS_ACCESS: case SYS_OPEN: filename_arg = (const void *)args->args[0]; __asm__ __volatile__("": : :"memory"); break; @@ -131,7 +148,19 @@ int sys_enter(struct syscall_enter_args *args) SEC("raw_syscalls:sys_exit") int sys_exit(struct syscall_exit_args *args) { - return !pid_filter__has(&pids_filtered, getpid()); + struct syscall_exit_args exit_args; + struct syscall *syscall; + + if (pid_filter__has(&pids_filtered, getpid())) + return 0; + + probe_read(&exit_args, sizeof(exit_args), args); + + syscall = bpf_map_lookup_elem(&syscalls, &exit_args.syscall_nr); + if (syscall == NULL || !syscall->enabled) + return 0; + + return 1; } license(GPL); diff --git a/tools/perf/include/bpf/bpf.h b/tools/perf/include/bpf/bpf.h index bd5d7b4d7760..e667577207dc 100644 --- a/tools/perf/include/bpf/bpf.h +++ b/tools/perf/include/bpf/bpf.h @@ -55,4 +55,6 @@ int _version SEC("version") = LINUX_VERSION_CODE; static int (*probe_read)(void *dst, int size, const void *unsafe_addr) = (void *)BPF_FUNC_probe_read; static int (*probe_read_str)(void *dst, int size, const void *unsafe_addr) = (void *)BPF_FUNC_probe_read_str; +static int (*perf_event_output)(void *, struct bpf_map *, int, void *, unsigned long) = (void *)BPF_FUNC_perf_event_output; + #endif /* _PERF_BPF_H */ diff --git a/tools/perf/include/bpf/stdio.h b/tools/perf/include/bpf/stdio.h index 2899cb7bfed8..316af5b2ff35 100644 --- a/tools/perf/include/bpf/stdio.h +++ b/tools/perf/include/bpf/stdio.h @@ -9,9 +9,6 @@ struct bpf_map SEC("maps") __bpf_stdout__ = { .max_entries = __NR_CPUS__, }; -static int (*perf_event_output)(void *, struct bpf_map *, int, void *, unsigned long) = - (void *)BPF_FUNC_perf_event_output; - #define puts(from) \ ({ const int __len = sizeof(from); \ char __from[__len] = from; \ diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 12c09e0ece71..9852b5d624a5 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -424,6 +424,9 @@ static const char *shell_test__description(char *description, size_t size, if (!fp) return NULL; + /* Skip shebang */ + while (fgetc(fp) != '\n'); + description = fgets(description, size, fp); fclose(fp); diff --git a/tools/perf/tests/shell/probe_vfs_getname.sh b/tools/perf/tests/shell/probe_vfs_getname.sh index 9b7635184dc2..46e076e3c537 100755 --- a/tools/perf/tests/shell/probe_vfs_getname.sh +++ b/tools/perf/tests/shell/probe_vfs_getname.sh @@ -1,3 +1,4 @@ +#!/bin/sh # Add vfs_getname probe to get syscall args filenames # # Arnaldo Carvalho de Melo <acme@kernel.org>, 2017 diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh index cab7b0aea6ea..61c9f8fc6fa1 100755 --- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh +++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh @@ -1,3 +1,4 @@ +#!/bin/sh # probe libc's inet_pton & backtrace it with ping # Installs a probe on libc's inet_pton function, that will use uprobes, diff --git a/tools/perf/tests/shell/record+script_probe_vfs_getname.sh b/tools/perf/tests/shell/record+script_probe_vfs_getname.sh index ba29535b8580..9b073e7fa88c 100755 --- a/tools/perf/tests/shell/record+script_probe_vfs_getname.sh +++ b/tools/perf/tests/shell/record+script_probe_vfs_getname.sh @@ -1,3 +1,4 @@ +#!/bin/sh # Use vfs_getname probe to get syscall args filenames # Uses the 'perf test shell' library to add probe:vfs_getname to the system diff --git a/tools/perf/tests/shell/trace+probe_vfs_getname.sh b/tools/perf/tests/shell/trace+probe_vfs_getname.sh index 4ce276efe6b4..50109f27ca07 100755 --- a/tools/perf/tests/shell/trace+probe_vfs_getname.sh +++ b/tools/perf/tests/shell/trace+probe_vfs_getname.sh @@ -1,3 +1,4 @@ +#!/bin/sh # Check open filename arg using perf trace + vfs_getname # Uses the 'perf test shell' library to add probe:vfs_getname to the system diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build index 304313073242..637365099b7d 100644 --- a/tools/perf/trace/beauty/Build +++ b/tools/perf/trace/beauty/Build @@ -7,7 +7,9 @@ endif libperf-y += kcmp.o libperf-y += mount_flags.o libperf-y += pkey_alloc.o +libperf-y += arch_prctl.o libperf-y += prctl.o +libperf-y += renameat.o libperf-y += sockaddr.o libperf-y += socket.o libperf-y += statx.o diff --git a/tools/perf/trace/beauty/arch_prctl.c b/tools/perf/trace/beauty/arch_prctl.c new file mode 100644 index 000000000000..fe022ca67e60 --- /dev/null +++ b/tools/perf/trace/beauty/arch_prctl.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * trace/beauty/arch_prctl.c + * + * Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> + */ + +#include "trace/beauty/beauty.h" +#include <linux/kernel.h> + +#include "trace/beauty/generated/x86_arch_prctl_code_array.c" + +static DEFINE_STRARRAY_OFFSET(x86_arch_prctl_codes_1, "ARCH_", x86_arch_prctl_codes_1_offset); +static DEFINE_STRARRAY_OFFSET(x86_arch_prctl_codes_2, "ARCH_", x86_arch_prctl_codes_2_offset); + +static struct strarray *x86_arch_prctl_codes[] = { + &strarray__x86_arch_prctl_codes_1, + &strarray__x86_arch_prctl_codes_2, +}; + +static DEFINE_STRARRAYS(x86_arch_prctl_codes); + +static size_t x86_arch_prctl__scnprintf_code(int option, char *bf, size_t size, bool show_prefix) +{ + return strarrays__scnprintf(&strarrays__x86_arch_prctl_codes, bf, size, "%#x", show_prefix, option); +} + +size_t syscall_arg__scnprintf_x86_arch_prctl_code(char *bf, size_t size, struct syscall_arg *arg) +{ + unsigned long code = arg->val; + + return x86_arch_prctl__scnprintf_code(code, bf, size, arg->show_string_prefix); +} diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h index 039c29039b2c..83c5b202e00e 100644 --- a/tools/perf/trace/beauty/beauty.h +++ b/tools/perf/trace/beauty/beauty.h @@ -9,26 +9,41 @@ struct strarray { int offset; int nr_entries; + const char *prefix; const char **entries; }; -#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \ +#define DEFINE_STRARRAY(array, _prefix) struct strarray strarray__##array = { \ .nr_entries = ARRAY_SIZE(array), \ .entries = array, \ + .prefix = _prefix, \ } -#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \ +#define DEFINE_STRARRAY_OFFSET(array, _prefix, off) struct strarray strarray__##array = { \ .offset = off, \ .nr_entries = ARRAY_SIZE(array), \ .entries = array, \ + .prefix = _prefix, \ } -size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val); -size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, unsigned long flags); +size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, bool show_prefix, int val); +size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, bool show_prefix, unsigned long flags); struct trace; struct thread; +struct strarrays { + int nr_entries; + struct strarray **entries; +}; + +#define DEFINE_STRARRAYS(array) struct strarrays strarrays__##array = { \ + .nr_entries = ARRAY_SIZE(array), \ + .entries = array, \ +} + +size_t strarrays__scnprintf(struct strarrays *sas, char *bf, size_t size, const char *intfmt, bool show_prefix, int val); + size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size); extern struct strarray strarray__socket_families; @@ -66,6 +81,7 @@ struct augmented_arg { * @parm: private area, may be an strarray, for instance * @idx: syscall arg idx (is this the first?) * @mask: a syscall arg may mask another arg, see syscall_arg__scnprintf_futex_op + * @show_string_prefix: When there is a common prefix in a string table, show it or not */ struct syscall_arg { @@ -80,6 +96,7 @@ struct syscall_arg { void *parm; u8 idx; u8 mask; + bool show_string_prefix; }; unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx); @@ -93,6 +110,9 @@ size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg) size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg); #define SCA_HEX syscall_arg__scnprintf_hex +size_t syscall_arg__scnprintf_ptr(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_PTR syscall_arg__scnprintf_ptr + size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg); #define SCA_INT syscall_arg__scnprintf_int @@ -135,6 +155,9 @@ size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, st size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg); #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags +size_t syscall_arg__scnprintf_x86_arch_prctl_code(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_X86_ARCH_PRCTL_CODE syscall_arg__scnprintf_x86_arch_prctl_code + size_t syscall_arg__scnprintf_prctl_option(char *bf, size_t size, struct syscall_arg *arg); #define SCA_PRCTL_OPTION syscall_arg__scnprintf_prctl_option @@ -144,6 +167,9 @@ size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_a size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg); #define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3 +size_t syscall_arg__scnprintf_renameat2_flags(char *bf, size_t size, struct syscall_arg *arg); +#define SCA_RENAMEAT2_FLAGS syscall_arg__scnprintf_renameat2_flags + size_t syscall_arg__scnprintf_sockaddr(char *bf, size_t size, struct syscall_arg *arg); #define SCA_SOCKADDR syscall_arg__scnprintf_sockaddr @@ -156,7 +182,7 @@ size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_ 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 -size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size); +size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix); void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg, size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg)); diff --git a/tools/perf/trace/beauty/clone.c b/tools/perf/trace/beauty/clone.c index 010406500c30..6eb9a6636171 100644 --- a/tools/perf/trace/beauty/clone.c +++ b/tools/perf/trace/beauty/clone.c @@ -10,13 +10,14 @@ #include <sys/types.h> #include <uapi/linux/sched.h> -static size_t clone__scnprintf_flags(unsigned long flags, char *bf, size_t size) +static size_t clone__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix) { + const char *prefix = "CLONE_"; int printed = 0; #define P_FLAG(n) \ if (flags & CLONE_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ flags &= ~CLONE_##n; \ } @@ -70,5 +71,5 @@ size_t syscall_arg__scnprintf_clone_flags(char *bf, size_t size, struct syscall_ if (!(flags & CLONE_SETTLS)) arg->mask |= SCC_TLS; - return clone__scnprintf_flags(flags, bf, size); + return clone__scnprintf_flags(flags, bf, size, arg->show_string_prefix); } diff --git a/tools/perf/trace/beauty/eventfd.c b/tools/perf/trace/beauty/eventfd.c index db5b9b492113..4bab106213c6 100644 --- a/tools/perf/trace/beauty/eventfd.c +++ b/tools/perf/trace/beauty/eventfd.c @@ -13,13 +13,15 @@ static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "EFD_"; int printed = 0, flags = arg->val; if (flags == 0) return scnprintf(bf, size, "NONE"); #define P_FLAG(n) \ if (flags & EFD_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ flags &= ~EFD_##n; \ } diff --git a/tools/perf/trace/beauty/fadvise.sh b/tools/perf/trace/beauty/fadvise.sh new file mode 100755 index 000000000000..b15ae3875167 --- /dev/null +++ b/tools/perf/trace/beauty/fadvise.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-License-Identifier: LGPL-2.1 + +[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ + +printf "static const char *fadvise_advices[] = {\n" +regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+POSIX_FADV_(\w+)[[:space:]]+([[:digit:]]+)[[:space:]]+.*' + +egrep $regex ${header_dir}/fadvise.h | \ + sed -r "s/$regex/\2 \1/g" | \ + sort | xargs printf "\t[%s] = \"%s\",\n" | \ + grep -v "[6].*DONTNEED" | grep -v "[7].*NOREUSE" +printf "};\n" + +# XXX Fix this properly: + +# The grep 6/7 DONTNEED/NOREUSE are a hack to filter out the s/390 oddity See +# tools/include/uapi/linux/fadvise.h for details. + +# Probably fix this when generating the string tables per arch so that We can +# reliably process on arch FOO a perf.data file collected by 'perf trace +# record' on arch BAR, e.g. collect on s/390 and process on x86. diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c index e6de31674e24..56ef83b3d130 100644 --- a/tools/perf/trace/beauty/fcntl.c +++ b/tools/perf/trace/beauty/fcntl.c @@ -9,27 +9,28 @@ #include <linux/kernel.h> #include <uapi/linux/fcntl.h> -static size_t fcntl__scnprintf_getfd(unsigned long val, char *bf, size_t size) +static size_t fcntl__scnprintf_getfd(unsigned long val, char *bf, size_t size, bool show_prefix) { - return scnprintf(bf, size, "%s", val ? "CLOEXEC" : "0"); + return val ? scnprintf(bf, size, "%s", "0") : + scnprintf(bf, size, "%s%s", show_prefix ? "FD_" : "", "CLOEXEC"); } static size_t syscall_arg__scnprintf_fcntl_getfd(char *bf, size_t size, struct syscall_arg *arg) { - return fcntl__scnprintf_getfd(arg->val, bf, size); + return fcntl__scnprintf_getfd(arg->val, bf, size, arg->show_string_prefix); } -static size_t fcntl__scnprintf_getlease(unsigned long val, char *bf, size_t size) +static size_t fcntl__scnprintf_getlease(unsigned long val, char *bf, size_t size, bool show_prefix) { static const char *fcntl_setlease[] = { "RDLCK", "WRLCK", "UNLCK", }; - static DEFINE_STRARRAY(fcntl_setlease); + static DEFINE_STRARRAY(fcntl_setlease, "F_"); - return strarray__scnprintf(&strarray__fcntl_setlease, bf, size, "%x", val); + return strarray__scnprintf(&strarray__fcntl_setlease, bf, size, "%x", show_prefix, val); } static size_t syscall_arg__scnprintf_fcntl_getlease(char *bf, size_t size, struct syscall_arg *arg) { - return fcntl__scnprintf_getlease(arg->val, bf, size); + return fcntl__scnprintf_getlease(arg->val, bf, size, arg->show_string_prefix); } size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg) @@ -68,22 +69,23 @@ out: size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; int cmd = syscall_arg__val(arg, 1); if (cmd == F_DUPFD) return syscall_arg__scnprintf_fd(bf, size, arg); if (cmd == F_SETFD) - return fcntl__scnprintf_getfd(arg->val, bf, size); + return fcntl__scnprintf_getfd(arg->val, bf, size, show_prefix); if (cmd == F_SETFL) - return open__scnprintf_flags(arg->val, bf, size); + return open__scnprintf_flags(arg->val, bf, size, show_prefix); if (cmd == F_SETOWN) return syscall_arg__scnprintf_pid(bf, size, arg); if (cmd == F_SETLEASE) - return fcntl__scnprintf_getlease(arg->val, bf, size); + return fcntl__scnprintf_getlease(arg->val, bf, size, show_prefix); /* * We still don't grab the contents of pointers on entry or exit, * so just print them as hex numbers diff --git a/tools/perf/trace/beauty/flock.c b/tools/perf/trace/beauty/flock.c index cf02ae5f0ba6..c14274edd6d9 100644 --- a/tools/perf/trace/beauty/flock.c +++ b/tools/perf/trace/beauty/flock.c @@ -22,13 +22,15 @@ size_t syscall_arg__scnprintf_flock(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "LOCK_"; int printed = 0, op = arg->val; if (op == 0) return scnprintf(bf, size, "NONE"); #define P_CMD(cmd) \ if ((op & LOCK_##cmd) == LOCK_##cmd) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #cmd); \ op &= ~LOCK_##cmd; \ } diff --git a/tools/perf/trace/beauty/futex_op.c b/tools/perf/trace/beauty/futex_op.c index 1136bde56406..00365156782b 100644 --- a/tools/perf/trace/beauty/futex_op.c +++ b/tools/perf/trace/beauty/futex_op.c @@ -19,6 +19,8 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "FUTEX_"; enum syscall_futex_args { SCF_UADDR = (1 << 0), SCF_OP = (1 << 1), @@ -32,7 +34,7 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct sysc size_t printed = 0; switch (cmd) { -#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n); +#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, "%s%s", show_prefix ? prefix : "", #n); P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break; P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; @@ -50,10 +52,10 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct sysc } if (op & FUTEX_PRIVATE_FLAG) - printed += scnprintf(bf + printed, size - printed, "|PRIV"); + printed += scnprintf(bf + printed, size - printed, "|%s%s", show_prefix ? prefix : "", "PRIVATE_FLAG"); if (op & FUTEX_CLOCK_REALTIME) - printed += scnprintf(bf + printed, size - printed, "|CLKRT"); + printed += scnprintf(bf + printed, size - printed, "|%s%s", show_prefix ? prefix : "", "CLOCK_REALTIME"); return printed; } diff --git a/tools/perf/trace/beauty/futex_val3.c b/tools/perf/trace/beauty/futex_val3.c index 138b7d588a70..9114f7620571 100644 --- a/tools/perf/trace/beauty/futex_val3.c +++ b/tools/perf/trace/beauty/futex_val3.c @@ -7,10 +7,11 @@ static size_t syscall_arg__scnprintf_futex_val3(char *bf, size_t size, struct syscall_arg *arg) { + const char *prefix = "FUTEX_BITSET_"; unsigned int bitset = arg->val; if (bitset == FUTEX_BITSET_MATCH_ANY) - return scnprintf(bf, size, "MATCH_ANY"); + return scnprintf(bf, size, "%s%s", arg->show_string_prefix ? prefix : "", "MATCH_ANY"); return scnprintf(bf, size, "%#xd", bitset); } diff --git a/tools/perf/trace/beauty/ioctl.c b/tools/perf/trace/beauty/ioctl.c index eae59ad15ce3..9efeb6a936c2 100644 --- a/tools/perf/trace/beauty/ioctl.c +++ b/tools/perf/trace/beauty/ioctl.c @@ -36,7 +36,7 @@ static size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size) "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS", "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI", "TIOCMIWAIT", "TIOCGICOUNT", }; - static DEFINE_STRARRAY(ioctl_tty_cmd); + static DEFINE_STRARRAY(ioctl_tty_cmd, ""); if (nr < strarray__ioctl_tty_cmd.nr_entries && strarray__ioctl_tty_cmd.entries[nr] != NULL) return scnprintf(bf, size, "%s", strarray__ioctl_tty_cmd.entries[nr]); @@ -47,7 +47,7 @@ static size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size) static size_t ioctl__scnprintf_drm_cmd(int nr, int dir, char *bf, size_t size) { #include "trace/beauty/generated/ioctl/drm_ioctl_array.c" - static DEFINE_STRARRAY(drm_ioctl_cmds); + static DEFINE_STRARRAY(drm_ioctl_cmds, ""); if (nr < strarray__drm_ioctl_cmds.nr_entries && strarray__drm_ioctl_cmds.entries[nr] != NULL) return scnprintf(bf, size, "DRM_%s", strarray__drm_ioctl_cmds.entries[nr]); @@ -58,7 +58,7 @@ static size_t ioctl__scnprintf_drm_cmd(int nr, int dir, char *bf, size_t size) static size_t ioctl__scnprintf_sndrv_pcm_cmd(int nr, int dir, char *bf, size_t size) { #include "trace/beauty/generated/ioctl/sndrv_pcm_ioctl_array.c" - static DEFINE_STRARRAY(sndrv_pcm_ioctl_cmds); + static DEFINE_STRARRAY(sndrv_pcm_ioctl_cmds, ""); if (nr < strarray__sndrv_pcm_ioctl_cmds.nr_entries && strarray__sndrv_pcm_ioctl_cmds.entries[nr] != NULL) return scnprintf(bf, size, "SNDRV_PCM_%s", strarray__sndrv_pcm_ioctl_cmds.entries[nr]); @@ -69,7 +69,7 @@ static size_t ioctl__scnprintf_sndrv_pcm_cmd(int nr, int dir, char *bf, size_t s static size_t ioctl__scnprintf_sndrv_ctl_cmd(int nr, int dir, char *bf, size_t size) { #include "trace/beauty/generated/ioctl/sndrv_ctl_ioctl_array.c" - static DEFINE_STRARRAY(sndrv_ctl_ioctl_cmds); + static DEFINE_STRARRAY(sndrv_ctl_ioctl_cmds, ""); if (nr < strarray__sndrv_ctl_ioctl_cmds.nr_entries && strarray__sndrv_ctl_ioctl_cmds.entries[nr] != NULL) return scnprintf(bf, size, "SNDRV_CTL_%s", strarray__sndrv_ctl_ioctl_cmds.entries[nr]); @@ -80,7 +80,7 @@ static size_t ioctl__scnprintf_sndrv_ctl_cmd(int nr, int dir, char *bf, size_t s static size_t ioctl__scnprintf_kvm_cmd(int nr, int dir, char *bf, size_t size) { #include "trace/beauty/generated/ioctl/kvm_ioctl_array.c" - static DEFINE_STRARRAY(kvm_ioctl_cmds); + static DEFINE_STRARRAY(kvm_ioctl_cmds, ""); if (nr < strarray__kvm_ioctl_cmds.nr_entries && strarray__kvm_ioctl_cmds.entries[nr] != NULL) return scnprintf(bf, size, "KVM_%s", strarray__kvm_ioctl_cmds.entries[nr]); @@ -91,8 +91,8 @@ static size_t ioctl__scnprintf_kvm_cmd(int nr, int dir, char *bf, size_t size) static size_t ioctl__scnprintf_vhost_virtio_cmd(int nr, int dir, char *bf, size_t size) { #include "trace/beauty/generated/ioctl/vhost_virtio_ioctl_array.c" - static DEFINE_STRARRAY(vhost_virtio_ioctl_cmds); - static DEFINE_STRARRAY(vhost_virtio_ioctl_read_cmds); + static DEFINE_STRARRAY(vhost_virtio_ioctl_cmds, ""); + static DEFINE_STRARRAY(vhost_virtio_ioctl_read_cmds, ""); struct strarray *s = (dir & _IOC_READ) ? &strarray__vhost_virtio_ioctl_read_cmds : &strarray__vhost_virtio_ioctl_cmds; if (nr < s->nr_entries && s->entries[nr] != NULL) @@ -104,7 +104,7 @@ static size_t ioctl__scnprintf_vhost_virtio_cmd(int nr, int dir, char *bf, size_ static size_t ioctl__scnprintf_perf_cmd(int nr, int dir, char *bf, size_t size) { #include "trace/beauty/generated/ioctl/perf_ioctl_array.c" - static DEFINE_STRARRAY(perf_ioctl_cmds); + static DEFINE_STRARRAY(perf_ioctl_cmds, ""); if (nr < strarray__perf_ioctl_cmds.nr_entries && strarray__perf_ioctl_cmds.entries[nr] != NULL) return scnprintf(bf, size, "PERF_%s", strarray__perf_ioctl_cmds.entries[nr]); @@ -112,8 +112,9 @@ static size_t ioctl__scnprintf_perf_cmd(int nr, int dir, char *bf, size_t size) return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir); } -static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size) +static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size, bool show_prefix) { + const char *prefix = "_IOC_"; int dir = _IOC_DIR(cmd), type = _IOC_TYPE(cmd), nr = _IOC_NR(cmd), @@ -143,12 +144,14 @@ static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size) printed += scnprintf(bf + printed, size - printed, "%c", '('); if (dir == _IOC_NONE) { - printed += scnprintf(bf + printed, size - printed, "%s", "NONE"); + printed += scnprintf(bf + printed, size - printed, "%s%s", show_prefix ? prefix : "", "NONE"); } else { if (dir & _IOC_READ) - printed += scnprintf(bf + printed, size - printed, "%s", "READ"); - if (dir & _IOC_WRITE) - printed += scnprintf(bf + printed, size - printed, "%s%s", dir & _IOC_READ ? "|" : "", "WRITE"); + printed += scnprintf(bf + printed, size - printed, "%s%s", show_prefix ? prefix : "", "READ"); + if (dir & _IOC_WRITE) { + printed += scnprintf(bf + printed, size - printed, "%s%s%s", dir & _IOC_READ ? "|" : "", + show_prefix ? prefix : "", "WRITE"); + } } return printed + scnprintf(bf + printed, size - printed, ", %#x, %#x, %#x)", type, nr, sz); @@ -158,5 +161,5 @@ size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_ar { unsigned long cmd = arg->val; - return ioctl__scnprintf_cmd(cmd, bf, size); + return ioctl__scnprintf_cmd(cmd, bf, size, arg->show_string_prefix); } diff --git a/tools/perf/trace/beauty/kcmp.c b/tools/perf/trace/beauty/kcmp.c index b276a274f203..9351f84390a1 100644 --- a/tools/perf/trace/beauty/kcmp.c +++ b/tools/perf/trace/beauty/kcmp.c @@ -26,10 +26,10 @@ size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg return pid__scnprintf_fd(arg->trace, pid, fd, bf, size); } -static size_t kcmp__scnprintf_type(int type, char *bf, size_t size) +static size_t kcmp__scnprintf_type(int type, char *bf, size_t size, bool show_prefix) { - static DEFINE_STRARRAY(kcmp_types); - return strarray__scnprintf(&strarray__kcmp_types, bf, size, "%d", type); + static DEFINE_STRARRAY(kcmp_types, "KCMP_"); + return strarray__scnprintf(&strarray__kcmp_types, bf, size, "%d", show_prefix, type); } size_t syscall_arg__scnprintf_kcmp_type(char *bf, size_t size, struct syscall_arg *arg) @@ -39,5 +39,5 @@ size_t syscall_arg__scnprintf_kcmp_type(char *bf, size_t size, struct syscall_ar if (type != KCMP_FILE) arg->mask |= (1 << 3) | (1 << 4); /* Ignore idx1 and idx2 */ - return kcmp__scnprintf_type(type, bf, size); + return kcmp__scnprintf_type(type, bf, size, arg->show_string_prefix); } diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c index c534bd96ef5c..eb31089790e3 100644 --- a/tools/perf/trace/beauty/mmap.c +++ b/tools/perf/trace/beauty/mmap.c @@ -5,18 +5,20 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, struct syscall_arg *arg) { + const char *prot_prefix = "PROT_"; int printed = 0, prot = arg->val; + bool show_prefix = arg->show_string_prefix; if (prot == PROT_NONE) - return scnprintf(bf, size, "NONE"); + return scnprintf(bf, size, "%sNONE", show_prefix ? prot_prefix : ""); #define P_MMAP_PROT(n) \ if (prot & PROT_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prot_prefix :"", #n); \ prot &= ~PROT_##n; \ } - P_MMAP_PROT(EXEC); P_MMAP_PROT(READ); + P_MMAP_PROT(EXEC); P_MMAP_PROT(WRITE); P_MMAP_PROT(SEM); P_MMAP_PROT(GROWSDOWN); @@ -31,12 +33,12 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, #define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot -static size_t mmap__scnprintf_flags(unsigned long flags, char *bf, size_t size) +static size_t mmap__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix) { #include "trace/beauty/generated/mmap_flags_array.c" - static DEFINE_STRARRAY(mmap_flags); + static DEFINE_STRARRAY(mmap_flags, "MAP_"); - return strarray__scnprintf_flags(&strarray__mmap_flags, bf, size, flags); + return strarray__scnprintf_flags(&strarray__mmap_flags, bf, size, show_prefix, flags); } static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, @@ -47,7 +49,7 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, if (flags & MAP_ANONYMOUS) arg->mask |= (1 << 4) | (1 << 5); /* Mask 4th ('fd') and 5th ('offset') args, ignored */ - return mmap__scnprintf_flags(flags, bf, size); + return mmap__scnprintf_flags(flags, bf, size, arg->show_string_prefix); } #define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags @@ -55,11 +57,13 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, struct syscall_arg *arg) { + const char *flags_prefix = "MREMAP_"; + bool show_prefix = arg->show_string_prefix; int printed = 0, flags = arg->val; #define P_MREMAP_FLAG(n) \ if (flags & MREMAP_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? flags_prefix : "", #n); \ flags &= ~MREMAP_##n; \ } @@ -78,7 +82,7 @@ static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, static size_t madvise__scnprintf_behavior(int behavior, char *bf, size_t size) { #include "trace/beauty/generated/madvise_behavior_array.c" - static DEFINE_STRARRAY(madvise_advices); + static DEFINE_STRARRAY(madvise_advices, "MADV_"); if (behavior < strarray__madvise_advices.nr_entries && strarray__madvise_advices.entries[behavior] != NULL) return scnprintf(bf, size, "MADV_%s", strarray__madvise_advices.entries[behavior]); diff --git a/tools/perf/trace/beauty/mode_t.c b/tools/perf/trace/beauty/mode_t.c index 6879d36d3004..29a8fadfb7f9 100644 --- a/tools/perf/trace/beauty/mode_t.c +++ b/tools/perf/trace/beauty/mode_t.c @@ -22,11 +22,13 @@ static size_t syscall_arg__scnprintf_mode_t(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "S_"; int printed = 0, mode = arg->val; #define P_MODE(n) \ if ((mode & S_##n) == S_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ mode &= ~S_##n; \ } diff --git a/tools/perf/trace/beauty/mount_flags.c b/tools/perf/trace/beauty/mount_flags.c index 712935c6620a..10fb14cfaf8f 100644 --- a/tools/perf/trace/beauty/mount_flags.c +++ b/tools/perf/trace/beauty/mount_flags.c @@ -11,12 +11,12 @@ #include <linux/log2.h> #include <sys/mount.h> -static size_t mount__scnprintf_flags(unsigned long flags, char *bf, size_t size) +static size_t mount__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix) { #include "trace/beauty/generated/mount_flags_array.c" - static DEFINE_STRARRAY(mount_flags); + static DEFINE_STRARRAY(mount_flags, "MS_"); - return strarray__scnprintf_flags(&strarray__mount_flags, bf, size, flags); + return strarray__scnprintf_flags(&strarray__mount_flags, bf, size, show_prefix, flags); } unsigned long syscall_arg__mask_val_mount_flags(struct syscall_arg *arg __maybe_unused, unsigned long flags) @@ -39,5 +39,5 @@ size_t syscall_arg__scnprintf_mount_flags(char *bf, size_t size, struct syscall_ { unsigned long flags = arg->val; - return mount__scnprintf_flags(flags, bf, size); + return mount__scnprintf_flags(flags, bf, size, arg->show_string_prefix); } diff --git a/tools/perf/trace/beauty/msg_flags.c b/tools/perf/trace/beauty/msg_flags.c index 1b9d6306d274..d66c66315987 100644 --- a/tools/perf/trace/beauty/msg_flags.c +++ b/tools/perf/trace/beauty/msg_flags.c @@ -21,13 +21,15 @@ static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "MSG_"; int printed = 0, flags = arg->val; if (flags == 0) return scnprintf(bf, size, "NONE"); #define P_MSG_FLAG(n) \ if (flags & MSG_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ flags &= ~MSG_##n; \ } diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c index cc673fec9184..78f6566ef110 100644 --- a/tools/perf/trace/beauty/open_flags.c +++ b/tools/perf/trace/beauty/open_flags.c @@ -22,15 +22,18 @@ #undef O_LARGEFILE #define O_LARGEFILE 00100000 -size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size) +size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix) { + const char *prefix = "O_"; int printed = 0; + if ((flags & O_ACCMODE) == O_RDONLY) + printed = scnprintf(bf, size, "%s%s", show_prefix ? prefix : "", "RDONLY"); if (flags == 0) - return scnprintf(bf, size, "RDONLY"); + return printed; #define P_FLAG(n) \ if (flags & O_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ flags &= ~O_##n; \ } @@ -57,7 +60,7 @@ size_t open__scnprintf_flags(unsigned long flags, char *bf, size_t size) #endif #ifdef O_DSYNC if ((flags & O_SYNC) == O_SYNC) - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC"); + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", "SYNC"); else { P_FLAG(DSYNC); } @@ -81,5 +84,5 @@ size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_a if (!(flags & O_CREAT)) arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */ - return open__scnprintf_flags(flags, bf, size); + return open__scnprintf_flags(flags, bf, size, arg->show_string_prefix); } diff --git a/tools/perf/trace/beauty/perf_event_open.c b/tools/perf/trace/beauty/perf_event_open.c index 981185c1974b..11d47dbe63bd 100644 --- a/tools/perf/trace/beauty/perf_event_open.c +++ b/tools/perf/trace/beauty/perf_event_open.c @@ -18,6 +18,8 @@ static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "PERF_"; int printed = 0, flags = arg->val; if (flags == 0) @@ -25,7 +27,7 @@ static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size, #define P_FLAG(n) \ if (flags & PERF_FLAG_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ flags &= ~PERF_FLAG_##n; \ } diff --git a/tools/perf/trace/beauty/pkey_alloc.c b/tools/perf/trace/beauty/pkey_alloc.c index 1b8ed4cac815..f9596ed02cc4 100644 --- a/tools/perf/trace/beauty/pkey_alloc.c +++ b/tools/perf/trace/beauty/pkey_alloc.c @@ -9,14 +9,14 @@ #include <linux/kernel.h> #include <linux/log2.h> -size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, unsigned long flags) +size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, bool show_prefix, unsigned long flags) { int i, printed = 0; if (flags == 0) { const char *s = sa->entries[0]; if (s) - return scnprintf(bf, size, "%s", s); + return scnprintf(bf, size, "%s%s", show_prefix ? sa->prefix : "", s); return scnprintf(bf, size, "%d", 0); } @@ -30,7 +30,7 @@ size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, uns printed += scnprintf(bf + printed, size - printed, "|"); if (sa->entries[i] != NULL) - printed += scnprintf(bf + printed, size - printed, "%s", sa->entries[i]); + printed += scnprintf(bf + printed, size - printed, "%s%s", show_prefix ? sa->prefix : "", sa->entries[i]); else printed += scnprintf(bf + printed, size - printed, "0x%#", bit); } @@ -38,17 +38,17 @@ size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, uns return printed; } -static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, size_t size) +static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, size_t size, bool show_prefix) { #include "trace/beauty/generated/pkey_alloc_access_rights_array.c" - static DEFINE_STRARRAY(pkey_alloc_access_rights); + static DEFINE_STRARRAY(pkey_alloc_access_rights, "PKEY_"); - return strarray__scnprintf_flags(&strarray__pkey_alloc_access_rights, bf, size, access_rights); + return strarray__scnprintf_flags(&strarray__pkey_alloc_access_rights, bf, size, show_prefix, access_rights); } size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg) { unsigned long cmd = arg->val; - return pkey_alloc__scnprintf_access_rights(cmd, bf, size); + return pkey_alloc__scnprintf_access_rights(cmd, bf, size, arg->show_string_prefix); } diff --git a/tools/perf/trace/beauty/prctl.c b/tools/perf/trace/beauty/prctl.c index be7a5d395975..ba2179abed00 100644 --- a/tools/perf/trace/beauty/prctl.c +++ b/tools/perf/trace/beauty/prctl.c @@ -11,16 +11,16 @@ #include "trace/beauty/generated/prctl_option_array.c" -static size_t prctl__scnprintf_option(int option, char *bf, size_t size) +static size_t prctl__scnprintf_option(int option, char *bf, size_t size, bool show_prefix) { - static DEFINE_STRARRAY(prctl_options); - return strarray__scnprintf(&strarray__prctl_options, bf, size, "%d", option); + static DEFINE_STRARRAY(prctl_options, "PR_"); + return strarray__scnprintf(&strarray__prctl_options, bf, size, "%d", show_prefix, option); } -static size_t prctl__scnprintf_set_mm(int option, char *bf, size_t size) +static size_t prctl__scnprintf_set_mm(int option, char *bf, size_t size, bool show_prefix) { - static DEFINE_STRARRAY(prctl_set_mm_options); - return strarray__scnprintf(&strarray__prctl_set_mm_options, bf, size, "%d", option); + static DEFINE_STRARRAY(prctl_set_mm_options, "PR_SET_MM_"); + return strarray__scnprintf(&strarray__prctl_set_mm_options, bf, size, "%d", show_prefix, option); } size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_arg *arg) @@ -28,7 +28,7 @@ size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_a int option = syscall_arg__val(arg, 0); if (option == PR_SET_MM) - return prctl__scnprintf_set_mm(arg->val, bf, size); + return prctl__scnprintf_set_mm(arg->val, bf, size, arg->show_string_prefix); /* * We still don't grab the contents of pointers on entry or exit, * so just print them as hex numbers @@ -77,5 +77,5 @@ size_t syscall_arg__scnprintf_prctl_option(char *bf, size_t size, struct syscall if (option < ARRAY_SIZE(masks)) arg->mask |= masks[option]; - return prctl__scnprintf_option(option, bf, size); + return prctl__scnprintf_option(option, bf, size, arg->show_string_prefix); } diff --git a/tools/perf/trace/beauty/rename_flags.sh b/tools/perf/trace/beauty/rename_flags.sh new file mode 100755 index 000000000000..54c87c782ab2 --- /dev/null +++ b/tools/perf/trace/beauty/rename_flags.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> +# SPDX-License-Identifier: LGPL-2.1 + +[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ + +fs_header=${header_dir}/fs.h + +printf "static const char *rename_flags[] = {\n" +regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+RENAME_([[:alnum:]_]+)[[:space:]]+\(1[[:space:]]*<<[[:space:]]*([[:xdigit:]]+)[[:space:]]*\)[[:space:]]*.*' +egrep -q $regex ${fs_header} && \ +(egrep $regex ${fs_header} | \ + sed -r "s/$regex/\2 \1/g" | \ + xargs printf "\t[%d + 1] = \"%s\",\n") +printf "};\n" diff --git a/tools/perf/trace/beauty/renameat.c b/tools/perf/trace/beauty/renameat.c new file mode 100644 index 000000000000..6dab340cc506 --- /dev/null +++ b/tools/perf/trace/beauty/renameat.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: LGPL-2.1 +// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> + +#include "trace/beauty/beauty.h" +#include <uapi/linux/fs.h> + +static size_t renameat2__scnprintf_flags(unsigned long flags, char *bf, size_t size, bool show_prefix) +{ +#include "trace/beauty/generated/rename_flags_array.c" + static DEFINE_STRARRAY(rename_flags, "RENAME_"); + + return strarray__scnprintf_flags(&strarray__rename_flags, bf, size, show_prefix, flags); +} + +size_t syscall_arg__scnprintf_renameat2_flags(char *bf, size_t size, struct syscall_arg *arg) +{ + unsigned long flags = arg->val; + return renameat2__scnprintf_flags(flags, bf, size, arg->show_string_prefix); +} diff --git a/tools/perf/trace/beauty/sched_policy.c b/tools/perf/trace/beauty/sched_policy.c index 48f2b5c9aa3e..68aa59eeed8d 100644 --- a/tools/perf/trace/beauty/sched_policy.c +++ b/tools/perf/trace/beauty/sched_policy.c @@ -17,6 +17,8 @@ static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "SCHED_"; const char *policies[] = { "NORMAL", "FIFO", "RR", "BATCH", "ISO", "IDLE", "DEADLINE", }; @@ -26,13 +28,13 @@ static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size, policy &= SCHED_POLICY_MASK; if (policy <= SCHED_DEADLINE) - printed = scnprintf(bf, size, "%s", policies[policy]); + printed = scnprintf(bf, size, "%s%s", show_prefix ? prefix : "", policies[policy]); else printed = scnprintf(bf, size, "%#x", policy); #define P_POLICY_FLAG(n) \ if (flags & SCHED_##n) { \ - printed += scnprintf(bf + printed, size - printed, "|%s", #n); \ + printed += scnprintf(bf + printed, size - printed, "|%s%s", show_prefix ? prefix : "", #n); \ flags &= ~SCHED_##n; \ } diff --git a/tools/perf/trace/beauty/seccomp.c b/tools/perf/trace/beauty/seccomp.c index e36156b19c70..4600c28a3cfe 100644 --- a/tools/perf/trace/beauty/seccomp.c +++ b/tools/perf/trace/beauty/seccomp.c @@ -8,11 +8,13 @@ static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "SECOMP_SET_MODE_"; int op = arg->val; size_t printed = 0; switch (op) { -#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break +#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, "%s%s", show_prefix ? prefix : "", #n); break P_SECCOMP_SET_MODE_OP(STRICT); P_SECCOMP_SET_MODE_OP(FILTER); #undef P_SECCOMP_SET_MODE_OP @@ -31,11 +33,13 @@ static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct sy static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "SECOMP_FILTER_FLAG_"; int printed = 0, flags = arg->val; #define P_FLAG(n) \ if (flags & SECCOMP_FILTER_FLAG_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ flags &= ~SECCOMP_FILTER_FLAG_##n; \ } diff --git a/tools/perf/trace/beauty/signum.c b/tools/perf/trace/beauty/signum.c index 587fec545b8a..21220c56500a 100644 --- a/tools/perf/trace/beauty/signum.c +++ b/tools/perf/trace/beauty/signum.c @@ -3,10 +3,12 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "SIG"; int sig = arg->val; switch (sig) { -#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n) +#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, "%s%s", show_prefix ? prefix : "", #n) P_SIGNUM(HUP); P_SIGNUM(INT); P_SIGNUM(QUIT); diff --git a/tools/perf/trace/beauty/sockaddr.c b/tools/perf/trace/beauty/sockaddr.c index 9410ad230f10..173c8f760763 100644 --- a/tools/perf/trace/beauty/sockaddr.c +++ b/tools/perf/trace/beauty/sockaddr.c @@ -15,7 +15,7 @@ static const char *socket_families[] = { "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF", "ALG", "NFC", "VSOCK", }; -DEFINE_STRARRAY(socket_families); +DEFINE_STRARRAY(socket_families, "PF_"); static size_t af_inet__scnprintf(struct sockaddr *sa, char *bf, size_t size) { @@ -58,7 +58,7 @@ static size_t syscall_arg__scnprintf_augmented_sockaddr(struct syscall_arg *arg, char family[32]; size_t printed; - strarray__scnprintf(&strarray__socket_families, family, sizeof(family), "%d", sa->sa_family); + strarray__scnprintf(&strarray__socket_families, family, sizeof(family), "%d", arg->show_string_prefix, sa->sa_family); printed = scnprintf(bf, size, "{ .family: %s", family); if (sa->sa_family < ARRAY_SIZE(af_scnprintfs) && af_scnprintfs[sa->sa_family]) diff --git a/tools/perf/trace/beauty/socket.c b/tools/perf/trace/beauty/socket.c index d971a2596417..f23a3dda2902 100644 --- a/tools/perf/trace/beauty/socket.c +++ b/tools/perf/trace/beauty/socket.c @@ -9,12 +9,12 @@ #include <sys/types.h> #include <sys/socket.h> -static size_t socket__scnprintf_ipproto(int protocol, char *bf, size_t size) +static size_t socket__scnprintf_ipproto(int protocol, char *bf, size_t size, bool show_prefix) { #include "trace/beauty/generated/socket_ipproto_array.c" - static DEFINE_STRARRAY(socket_ipproto); + static DEFINE_STRARRAY(socket_ipproto, "IPPROTO_"); - return strarray__scnprintf(&strarray__socket_ipproto, bf, size, "%d", protocol); + return strarray__scnprintf(&strarray__socket_ipproto, bf, size, "%d", show_prefix, protocol); } size_t syscall_arg__scnprintf_socket_protocol(char *bf, size_t size, struct syscall_arg *arg) @@ -22,7 +22,7 @@ size_t syscall_arg__scnprintf_socket_protocol(char *bf, size_t size, struct sysc int domain = syscall_arg__val(arg, 0); if (domain == AF_INET || domain == AF_INET6) - return socket__scnprintf_ipproto(arg->val, bf, size); + return socket__scnprintf_ipproto(arg->val, bf, size, arg->show_string_prefix); return syscall_arg__scnprintf_int(bf, size, arg); } diff --git a/tools/perf/trace/beauty/socket_type.c b/tools/perf/trace/beauty/socket_type.c index a63a9a332aa0..bed8d5761ca8 100644 --- a/tools/perf/trace/beauty/socket_type.c +++ b/tools/perf/trace/beauty/socket_type.c @@ -20,6 +20,8 @@ static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "SOCK_"; size_t printed; int type = arg->val, flags = type & ~SOCK_TYPE_MASK; @@ -29,7 +31,7 @@ static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size, struct s * Can't use a strarray, MIPS may override for ABI reasons. */ switch (type) { -#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break; +#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, "%s%s", show_prefix ? prefix : "", #n); break; P_SK_TYPE(STREAM); P_SK_TYPE(DGRAM); P_SK_TYPE(RAW); diff --git a/tools/perf/trace/beauty/statx.c b/tools/perf/trace/beauty/statx.c index 630f2760dd66..811cc0eeb2d5 100644 --- a/tools/perf/trace/beauty/statx.c +++ b/tools/perf/trace/beauty/statx.c @@ -13,13 +13,15 @@ size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "AT_"; int printed = 0, flags = arg->val; if (flags == 0) - return scnprintf(bf, size, "SYNC_AS_STAT"); + return scnprintf(bf, size, "%s%s", show_prefix ? "AT_STATX_" : "", "SYNC_AS_STAT"); #define P_FLAG(n) \ if (flags & AT_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ flags &= ~AT_##n; \ } @@ -41,11 +43,13 @@ size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_ size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "STATX_"; int printed = 0, flags = arg->val; #define P_FLAG(n) \ if (flags & STATX_##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", show_prefix ? prefix : "", #n); \ flags &= ~STATX_##n; \ } diff --git a/tools/perf/trace/beauty/waitid_options.c b/tools/perf/trace/beauty/waitid_options.c index 42ff58ad613b..6897fab40dcc 100644 --- a/tools/perf/trace/beauty/waitid_options.c +++ b/tools/perf/trace/beauty/waitid_options.c @@ -5,11 +5,13 @@ static size_t syscall_arg__scnprintf_waitid_options(char *bf, size_t size, struct syscall_arg *arg) { + bool show_prefix = arg->show_string_prefix; + const char *prefix = "W"; int printed = 0, options = arg->val; #define P_OPTION(n) \ if (options & W##n) { \ - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \ + printed += scnprintf(bf + printed, size - printed, "%s%s%s", printed ? "|" : "", show_prefix ? prefix : #n); \ options &= ~W##n; \ } diff --git a/tools/perf/trace/beauty/x86_arch_prctl.sh b/tools/perf/trace/beauty/x86_arch_prctl.sh new file mode 100755 index 000000000000..7372d3cab959 --- /dev/null +++ b/tools/perf/trace/beauty/x86_arch_prctl.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> +# SPDX-License-Identifier: LGPL-2.1 + +[ $# -eq 1 ] && x86_header_dir=$1 || x86_header_dir=tools/arch/x86/include/uapi/asm/ + +prctl_arch_header=${x86_header_dir}/prctl.h + +print_range () { + local idx=$1 + local prefix=$2 + local first_entry=$3 + + printf "#define x86_arch_prctl_codes_%d_offset %s\n" $idx $first_entry + printf "static const char *x86_arch_prctl_codes_%d[] = {\n" $idx + regex=`printf '^[[:space:]]*#[[:space:]]*define[[:space:]]+ARCH_([[:alnum:]_]+)[[:space:]]+(%s[[:xdigit:]]+).*' ${prefix}` + fmt="\t[%#x - ${first_entry}]= \"%s\",\n" + egrep -q $regex ${prctl_arch_header} && \ + (egrep $regex ${prctl_arch_header} | \ + sed -r "s/$regex/\2 \1/g" | \ + xargs printf "$fmt") + printf "};\n\n" +} + +print_range 1 0x1 0x1001 +print_range 2 0x2 0x2001 diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 72d5ba2479bf..f69961c4a4f3 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -1983,17 +1983,14 @@ static int find_dso_sym(struct dso *dso, const char *sym_name, u64 *start, static int addr_filter__entire_dso(struct addr_filter *filt, struct dso *dso) { - struct symbol *first_sym = dso__first_symbol(dso); - struct symbol *last_sym = dso__last_symbol(dso); - - if (!first_sym || !last_sym) { - pr_err("Failed to determine filter for %s\nNo symbols found.\n", + if (dso__data_file_size(dso, NULL)) { + pr_err("Failed to determine filter for %s\nCannot determine file size.\n", filt->filename); return -EINVAL; } - filt->addr = first_sym->start; - filt->size = last_sym->end - first_sym->start; + filt->addr = 0; + filt->size = dso->data.file_size; return 0; } diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c index 0b4c8629f578..8c155575c6c5 100644 --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c @@ -36,7 +36,6 @@ struct cs_etm_decoder { void *data; void (*packet_printer)(const char *msg); - bool trace_on; dcd_tree_handle_t dcd_tree; cs_etm_mem_cb_type mem_access; ocsd_datapath_resp_t prev_return; @@ -291,8 +290,6 @@ static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder) decoder->packet_buffer[i].instr_count = 0; decoder->packet_buffer[i].last_instr_taken_branch = false; decoder->packet_buffer[i].last_instr_size = 0; - decoder->packet_buffer[i].exc = false; - decoder->packet_buffer[i].exc_ret = false; decoder->packet_buffer[i].cpu = INT_MIN; } } @@ -320,8 +317,6 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder, decoder->packet_buffer[et].sample_type = sample_type; decoder->packet_buffer[et].isa = CS_ETM_ISA_UNKNOWN; - decoder->packet_buffer[et].exc = false; - decoder->packet_buffer[et].exc_ret = false; decoder->packet_buffer[et].cpu = *((int *)inode->priv); decoder->packet_buffer[et].start_addr = CS_ETM_INVAL_ADDR; decoder->packet_buffer[et].end_addr = CS_ETM_INVAL_ADDR; @@ -391,11 +386,27 @@ cs_etm_decoder__buffer_range(struct cs_etm_decoder *decoder, } static ocsd_datapath_resp_t -cs_etm_decoder__buffer_trace_on(struct cs_etm_decoder *decoder, - const uint8_t trace_chan_id) +cs_etm_decoder__buffer_discontinuity(struct cs_etm_decoder *decoder, + const uint8_t trace_chan_id) { return cs_etm_decoder__buffer_packet(decoder, trace_chan_id, - CS_ETM_TRACE_ON); + CS_ETM_DISCONTINUITY); +} + +static ocsd_datapath_resp_t +cs_etm_decoder__buffer_exception(struct cs_etm_decoder *decoder, + const uint8_t trace_chan_id) +{ + return cs_etm_decoder__buffer_packet(decoder, trace_chan_id, + CS_ETM_EXCEPTION); +} + +static ocsd_datapath_resp_t +cs_etm_decoder__buffer_exception_ret(struct cs_etm_decoder *decoder, + const uint8_t trace_chan_id) +{ + return cs_etm_decoder__buffer_packet(decoder, trace_chan_id, + CS_ETM_EXCEPTION_RET); } static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( @@ -410,26 +421,25 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( switch (elem->elem_type) { case OCSD_GEN_TRC_ELEM_UNKNOWN: break; + case OCSD_GEN_TRC_ELEM_EO_TRACE: case OCSD_GEN_TRC_ELEM_NO_SYNC: - decoder->trace_on = false; - break; case OCSD_GEN_TRC_ELEM_TRACE_ON: - resp = cs_etm_decoder__buffer_trace_on(decoder, - trace_chan_id); - decoder->trace_on = true; + resp = cs_etm_decoder__buffer_discontinuity(decoder, + trace_chan_id); break; case OCSD_GEN_TRC_ELEM_INSTR_RANGE: resp = cs_etm_decoder__buffer_range(decoder, elem, trace_chan_id); break; case OCSD_GEN_TRC_ELEM_EXCEPTION: - decoder->packet_buffer[decoder->tail].exc = true; + resp = cs_etm_decoder__buffer_exception(decoder, + trace_chan_id); break; case OCSD_GEN_TRC_ELEM_EXCEPTION_RET: - decoder->packet_buffer[decoder->tail].exc_ret = true; + resp = cs_etm_decoder__buffer_exception_ret(decoder, + trace_chan_id); break; case OCSD_GEN_TRC_ELEM_PE_CONTEXT: - case OCSD_GEN_TRC_ELEM_EO_TRACE: case OCSD_GEN_TRC_ELEM_ADDR_NACC: case OCSD_GEN_TRC_ELEM_TIMESTAMP: case OCSD_GEN_TRC_ELEM_CYCLE_COUNT: diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h index b295dd2b8292..a6407d41598f 100644 --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h @@ -23,9 +23,11 @@ struct cs_etm_buffer { }; enum cs_etm_sample_type { - CS_ETM_EMPTY = 0, - CS_ETM_RANGE = 1 << 0, - CS_ETM_TRACE_ON = 1 << 1, + CS_ETM_EMPTY, + CS_ETM_RANGE, + CS_ETM_DISCONTINUITY, + CS_ETM_EXCEPTION, + CS_ETM_EXCEPTION_RET, }; enum cs_etm_isa { @@ -43,8 +45,6 @@ struct cs_etm_packet { u32 instr_count; u8 last_instr_taken_branch; u8 last_instr_size; - u8 exc; - u8 exc_ret; int cpu; }; diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 23159c33db2a..27a374ddf661 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -562,8 +562,8 @@ static inline int cs_etm__t32_instr_size(struct cs_etm_queue *etmq, static inline u64 cs_etm__first_executed_instr(struct cs_etm_packet *packet) { - /* Returns 0 for the CS_ETM_TRACE_ON packet */ - if (packet->sample_type == CS_ETM_TRACE_ON) + /* Returns 0 for the CS_ETM_DISCONTINUITY packet */ + if (packet->sample_type == CS_ETM_DISCONTINUITY) return 0; return packet->start_addr; @@ -572,8 +572,8 @@ static inline u64 cs_etm__first_executed_instr(struct cs_etm_packet *packet) static inline u64 cs_etm__last_executed_instr(const struct cs_etm_packet *packet) { - /* Returns 0 for the CS_ETM_TRACE_ON packet */ - if (packet->sample_type == CS_ETM_TRACE_ON) + /* Returns 0 for the CS_ETM_DISCONTINUITY packet */ + if (packet->sample_type == CS_ETM_DISCONTINUITY) return 0; return packet->end_addr - packet->last_instr_size; @@ -972,7 +972,7 @@ static int cs_etm__sample(struct cs_etm_queue *etmq) bool generate_sample = false; /* Generate sample for tracing on packet */ - if (etmq->prev_packet->sample_type == CS_ETM_TRACE_ON) + if (etmq->prev_packet->sample_type == CS_ETM_DISCONTINUITY) generate_sample = true; /* Generate sample for branch taken packet */ @@ -1000,6 +1000,25 @@ static int cs_etm__sample(struct cs_etm_queue *etmq) return 0; } +static int cs_etm__exception(struct cs_etm_queue *etmq) +{ + /* + * When the exception packet is inserted, whether the last instruction + * in previous range packet is taken branch or not, we need to force + * to set 'prev_packet->last_instr_taken_branch' to true. This ensures + * to generate branch sample for the instruction range before the + * exception is trapped to kernel or before the exception returning. + * + * The exception packet includes the dummy address values, so don't + * swap PACKET with PREV_PACKET. This keeps PREV_PACKET to be useful + * for generating instruction and branch samples. + */ + if (etmq->prev_packet->sample_type == CS_ETM_RANGE) + etmq->prev_packet->last_instr_taken_branch = true; + + return 0; +} + static int cs_etm__flush(struct cs_etm_queue *etmq) { int err = 0; @@ -1042,7 +1061,7 @@ static int cs_etm__flush(struct cs_etm_queue *etmq) } swap_packet: - if (etmq->etm->synth_opts.last_branch) { + if (etm->sample_branches || etm->synth_opts.last_branch) { /* * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for * the next incoming packet. @@ -1055,6 +1074,39 @@ swap_packet: return err; } +static int cs_etm__end_block(struct cs_etm_queue *etmq) +{ + int err; + + /* + * It has no new packet coming and 'etmq->packet' contains the stale + * packet which was set at the previous time with packets swapping; + * so skip to generate branch sample to avoid stale packet. + * + * For this case only flush branch stack and generate a last branch + * event for the branches left in the circular buffer at the end of + * the trace. + */ + if (etmq->etm->synth_opts.last_branch && + etmq->prev_packet->sample_type == CS_ETM_RANGE) { + /* + * Use the address of the end of the last reported execution + * range. + */ + u64 addr = cs_etm__last_executed_instr(etmq->prev_packet); + + err = cs_etm__synth_instruction_sample( + etmq, addr, + etmq->period_instructions); + if (err) + return err; + + etmq->period_instructions = 0; + } + + return 0; +} + static int cs_etm__run_decoder(struct cs_etm_queue *etmq) { struct cs_etm_auxtrace *etm = etmq->etm; @@ -1115,7 +1167,16 @@ static int cs_etm__run_decoder(struct cs_etm_queue *etmq) */ cs_etm__sample(etmq); break; - case CS_ETM_TRACE_ON: + case CS_ETM_EXCEPTION: + case CS_ETM_EXCEPTION_RET: + /* + * If the exception packet is coming, + * make sure the previous instruction + * range packet to be handled properly. + */ + cs_etm__exception(etmq); + break; + case CS_ETM_DISCONTINUITY: /* * Discontinuity in trace, flush * previous branch stack @@ -1137,7 +1198,7 @@ static int cs_etm__run_decoder(struct cs_etm_queue *etmq) if (err == 0) /* Flush any remaining branch stack entries */ - err = cs_etm__flush(etmq); + err = cs_etm__end_block(etmq); } return err; diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index cee717a3794f..62c8cf622607 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -894,7 +894,7 @@ static ssize_t cached_read(struct dso *dso, struct machine *machine, return r; } -static int data_file_size(struct dso *dso, struct machine *machine) +int dso__data_file_size(struct dso *dso, struct machine *machine) { int ret = 0; struct stat st; @@ -943,7 +943,7 @@ out: */ off_t dso__data_size(struct dso *dso, struct machine *machine) { - if (data_file_size(dso, machine)) + if (dso__data_file_size(dso, machine)) return -1; /* For now just estimate dso data size is close to file size */ @@ -953,7 +953,7 @@ off_t dso__data_size(struct dso *dso, struct machine *machine) static ssize_t data_read_offset(struct dso *dso, struct machine *machine, u64 offset, u8 *data, ssize_t size) { - if (data_file_size(dso, machine)) + if (dso__data_file_size(dso, machine)) return -1; /* Check the offset sanity. */ diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index c5380500bed4..8c8a7abe809d 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -322,6 +322,7 @@ int dso__data_get_fd(struct dso *dso, struct machine *machine); void dso__data_put_fd(struct dso *dso); void dso__data_close(struct dso *dso); +int dso__data_file_size(struct dso *dso, struct machine *machine); off_t dso__data_size(struct dso *dso, struct machine *machine); ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, u64 offset, u8 *data, ssize_t size); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index e90575192209..8c902276d4b4 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -34,6 +34,10 @@ #include <linux/log2.h> #include <linux/err.h> +#ifdef LACKS_SIGQUEUE_PROTOTYPE +int sigqueue(pid_t pid, int sig, const union sigval value); +#endif + #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 1171d8400bf4..dec6d218c31c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2698,6 +2698,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full) struct perf_header *header = &session->header; int fd = perf_data__fd(session->data); struct stat st; + time_t stctime; int ret, bit; hd.fp = fp; @@ -2707,7 +2708,8 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full) if (ret == -1) return -1; - fprintf(fp, "# captured on : %s", ctime(&st.st_ctime)); + stctime = st.st_ctime; + fprintf(fp, "# captured on : %s", ctime(&stctime)); fprintf(fp, "# header version : %u\n", header->version); fprintf(fp, "# data offset : %" PRIu64 "\n", header->data_offset); diff --git a/tools/perf/util/s390-cpumsf.c b/tools/perf/util/s390-cpumsf.c index a2eeebbfb25f..68b2570304ec 100644 --- a/tools/perf/util/s390-cpumsf.c +++ b/tools/perf/util/s390-cpumsf.c @@ -506,7 +506,7 @@ static int s390_cpumsf_samples(struct s390_cpumsf_queue *sfq, u64 *ts) aux_ts = get_trailer_time(buf); if (!aux_ts) { pr_err("[%#08" PRIx64 "] Invalid AUX trailer entry TOD clock base\n", - sfq->buffer->data_offset); + (s64)sfq->buffer->data_offset); aux_ts = ~0ULL; goto out; } diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index dcce74bae6de..01f2c7385e38 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1537,17 +1537,6 @@ int dso__load(struct dso *dso, struct map *map) dso->adjust_symbols = 0; if (perfmap) { - struct stat st; - - if (lstat(map_path, &st) < 0) - goto out; - - if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) { - pr_warning("File %s not owned by current user or root, " - "ignoring it (use -f to override).\n", map_path); - goto out; - } - ret = dso__load_perf_map(map_path, dso); dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : DSO_BINARY_TYPE__NOT_FOUND; |