Commit 883f4def authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo-4.21-20181218' of...

Merge tag 'perf-core-for-mingo-4.21-20181218' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

- Implement BPF based syscall filtering in 'perf trace', using BPF maps and
  the augmented_raw_syscalls.c BPF proggie (Arnaldo Carvalho de Melo)

- Allow specifying in .perfconfig a set of events use in 'perf trace' in
  addition to any other specified from the command line. This initially
  will be used to always use the augmented_raw_syscalls.o precompiled
  BPF program for getting pointer contents. (Arnaldo Carvalho de Melo)

- Allow fine grained control about how the syscall output should be
  formatted. This will be used to allow producing the same output produced
  by the 'strace' tool, to then use in regression tests comparing the
  output of 'perf trace' with the one produced from 'strace' (Arnaldo Carvalho de Melo)

- Beautify the renameat2 olddirfd, newdirfd and flags arguments (Arnaldo Carvalho de Melo)

- Beautify arch_prctl 'code' syscall arg (Arnaldo Carvalho de Melo)

- Beautify fadvise64 'advice' syscall arg (Arnaldo Carvalho de Melo)

- Relax checks on perf-PID.map ownership, resulting in symbols in
  executable anonymous maps setup by JITs in things like node.js to
  be resolved in a 'perf top' session run by root without the need
  for --force to be used (Arnaldo Carvalho de Melo)

- Update asm-generic/unistd.h copy (Arnaldo Carvalho de Melo)

- Do not use the first and last symbols when setting up address filters in
  auxtrace, this fails when we don't have a symbol table, filter the entire
  area based on the dso size. (Adrian Hunter)

- Do not use kernel headers to build libsubcmd, we shouldn't use
  anything from outside tools/, fixes the build with the Android NDK (Arnaldo Carvalho de Melo)

- Add several prototypes for systems lacking those, such as open_memstream(),
  sigqueue(), fixing warnings building with Android's bionic libc that were
  preventing the use of -Werror there (Arnaldo Carvalho de Melo)

- Use LDFLAGS in the libtraceevent build commands, allowing developers
  to override its values (Jiri Olsa)

- Link libperf-jvmti.so with LDFLAGS variable, allowing distro
  packages to propagate its settings when building this library (Jiri Olsa)

- cs-etm (ARM CoreSight) fixes: (Leo Yan)

  - Correct packets swapping in cs_etm__flush()
  - Avoid stale branch samples when flush packet
  - Remove unused 'trace_on' in cs_etm_decoder
  - Refactor enumeration cs_etm_sample_type
  - Rename CS_ETM_TRACE_ON to CS_ETM_DISCONTINUITY
  - Treat NO_SYNC element as trace discontinuity
  - Treat EO_TRACE element as trace discontinuity
  - Generate branch sample for exception packet

- Use shebangs in the 'perf test' shell scripts, making them identifiable as
  shell scripts (Michael Petlan)

- Avoid segfaults caused by negated options in 'perf stat' (Michael Petlan)

- Fix processing of dereferenced args in bprintk events in libtracevent (Steven Rostedt)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents ca46afdb 89a09489
/* 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 */
......@@ -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
......
/* 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 */
......@@ -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
......
......@@ -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. */'; \
......
......@@ -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;
}
......
......@@ -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]
......@@ -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
----------
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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);
......
......@@ -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
......
......@@ -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 @@ static struct perf_evsel *perf_evsel__raw_syscall_newtp(const char *direction, v
({ 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,7 +1228,11 @@ 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);
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 @@ static int trace__add_syscall_newtp(struct trace *trace)
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 @@ static int trace__set_ev_qualifier_filter(struct trace *trace)
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->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_pgfaults & TRACE_PFMAJ)) {
pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
......@@ -2802,14 +2928,19 @@ 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;
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);
if (err < 0)
......@@ -2859,7 +2990,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
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 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
goto again;
} else {
if (trace__flush_ordered_events(trace))
if (trace__flush_events(trace))
goto out_disable;
}
} else {
......@@ -2897,6 +3028,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
perf_evlist__disable(evlist);
if (trace->sort_events)
ordered_events__flush(&trace->oe.data, OE_FLUSH__FINAL);
if (!err) {
......@@ -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)
}
}
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
......
......@@ -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
......
......@@ -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);
......@@ -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 */
......@@ -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; \
......
......@@ -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);
......
#!/bin/sh
# Add vfs_getname probe to get syscall args filenames
#
# Arnaldo Carvalho de Melo <acme@kernel.org>, 2017
......
#!/bin/sh
# probe libc's inet_pton & backtrace it with ping
# Installs a probe on libc's inet_pton function, that will use uprobes,
......
#!/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
......
#!/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
......
......@@ -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
// 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);
}
......@@ -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));
......
......@@ -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);
}
......@@ -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; \
}
......
#!/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.
......@@ -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 @@ size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_ar
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
......
......@@ -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; \
}
......
......@@ -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;
}
......
......@@ -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);
}
......
......@@ -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);
}
......@@ -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);
}
......@@ -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]);
......
......@@ -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; \
}
......
......@@ -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);
}
......@@ -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; \
}
......
......@@ -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);
}
......@@ -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; \
}
......
......@@ -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);
}
......@@ -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);
}
#!/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"
// 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);
}
......@@ -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; \
}
......
......@@ -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; \
}
......
......@@ -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);
......
......@@ -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])
......
......@@ -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);
}
......@@ -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);
......
......@@ -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; \
}
......
......@@ -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; \
}
......
#!/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
......@@ -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;
}
......
......@@ -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,
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,
resp = cs_etm_decoder__buffer_discontinuity(decoder,
trace_chan_id);
decoder->trace_on = true;
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:
......
......@@ -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;
};
......
......@@ -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 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
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;
......
......@@ -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 @@ static int data_file_size(struct dso *dso, struct machine *machine)
*/
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. */
......
......@@ -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);
......
......@@ -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)
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment