perf/core improvements and fixes:
User visible:
- Beautify more syscall arguments in 'perf trace', using the type column in
tracepoint /format fields to attach, for instance, a pid_t resolver to the
thread COMM, also attach a mode_t beautifier in the same fashion
(Arnaldo Carvalho de Melo)
- Build the syscall table id <-> name resolver using the same .tbl file
used in the kernel to generate headers, to avoid the delay in getting
new syscalls supported in the audit-libs external dependency, done so
far only for x86_64 (Arnaldo Carvalho de Melo)
- Improve the documentation of event specifications (Andi Kleen)
- Process update events in 'perf script', fixing up this use case:
# perf stat -a -I 1000 -e cycles record | perf script -s script.py
- Shared object symbol adjustment fixes, fixing symbol resolution in
Android (Wang Nan)
Infrastructure:
- Add dedicated unwind addr_space member into thread struct, to allow
tools to use thread->priv, noticed while working on having callchains
in 'perf trace' (Jiri Olsa)
Build fixes:
- Fix the build in Ubuntu 12.04 (Arnaldo Carvalho de Melo, Vinson Lee)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQIcBAABCAAGBQJXB646AAoJENZQFvNTUqpAvroP/1BE/cViqrM3v351qkPDh2Dw
Mat7ZDTDUxsZ2XqzJQTsRiao1oi2ALF1Kyh3UzgRLqsDuahQHhwpm4M9pegtgDsu
I77yGGFVw/rdZLdJGHrGXE8HeOrvW6NKk7HqmnMlwpLpNkMfPVpqlq82/rUHcA46
F98/7DTG/PNstbIxuCgV3fI1aB8/v+lVGLw+S7vnf/Xuba4MNdqTQNEzkXaAubzv
c2I6YBwSO3v+oVgu3Vr679gGxNx3P/iGkgIb2WqJxezNiZUVdh4McJ4Dg3/mm5hj
Q1scLuW2MGXy3WaQW4i7sjoAwlOX+4kkUO8l5yk67GXKLwstnx4SWJNyeupMxDcp
UKl2mPcZIPaCPjR7aFnR6Xvxv71QkEEgeQlvR1gwAZeONBtZ9kOFD2jJfK5tbwyS
GG3rF5dB4KJqjr31tDcGYxuti4ggiJIvi/ujyrKvJUl7JChkJVDbqENOK35qistR
iHV1nSEQM1O2+NNaH4Ise9WYjQOH5tERc9L9XOpaR9x6KDsz1TR7bqqBu8HdASJs
v9x02RaPjDc/x3MUrhZ1sEDOqEqLO2eHhq1stnFTz4x9r7k+YPySS43FtnARB1CZ
H8Pc21gyxt1pzO0ogvnLoji1715+DaSaEWas+vrfzJ1cJ4Tf6v5zYEuOfYJhDQrC
dK75s0KDR6DCO/cwUEr1
=AF/P
-----END PGP SIGNATURE-----
Merge tag 'perf-core-for-mingo-20160408' 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:
User visible changes:
- Beautify more syscall arguments in 'perf trace', using the type column in
tracepoint /format fields to attach, for instance, a pid_t resolver to the
thread COMM, also attach a mode_t beautifier in the same fashion
(Arnaldo Carvalho de Melo)
- Build the syscall table id <-> name resolver using the same .tbl file
used in the kernel to generate headers, to avoid the delay in getting
new syscalls supported in the audit-libs external dependency, done so
far only for x86_64 (Arnaldo Carvalho de Melo)
- Improve the documentation of event specifications (Andi Kleen)
- Process update events in 'perf script', fixing up this use case:
# perf stat -a -I 1000 -e cycles record | perf script -s script.py
- Shared object symbol adjustment fixes, fixing symbol resolution in
Android (Wang Nan)
Infrastructure changes:
- Add dedicated unwind addr_space member into thread struct, to allow
tools to use thread->priv, noticed while working on having callchains
in 'perf trace' (Jiri Olsa)
Build fixes:
- Fix the build in Ubuntu 12.04 (Arnaldo Carvalho de Melo, Vinson Lee)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
pull/290/head
commit
aeaae7d612
|
|
@ -30,6 +30,7 @@ endef
|
|||
FEATURE_TESTS_BASIC := \
|
||||
backtrace \
|
||||
dwarf \
|
||||
dwarf_getlocations \
|
||||
fortify-source \
|
||||
sync-compare-and-swap \
|
||||
glibc \
|
||||
|
|
@ -78,6 +79,7 @@ endif
|
|||
|
||||
FEATURE_DISPLAY ?= \
|
||||
dwarf \
|
||||
dwarf_getlocations \
|
||||
glibc \
|
||||
gtk2 \
|
||||
libaudit \
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ FILES= \
|
|||
test-backtrace.bin \
|
||||
test-bionic.bin \
|
||||
test-dwarf.bin \
|
||||
test-dwarf_getlocations.bin \
|
||||
test-fortify-source.bin \
|
||||
test-sync-compare-and-swap.bin \
|
||||
test-glibc.bin \
|
||||
|
|
@ -82,6 +83,9 @@ endif
|
|||
$(OUTPUT)test-dwarf.bin:
|
||||
$(BUILD) $(DWARFLIBS)
|
||||
|
||||
$(OUTPUT)test-dwarf_getlocations.bin:
|
||||
$(BUILD) $(DWARFLIBS)
|
||||
|
||||
$(OUTPUT)test-libelf-mmap.bin:
|
||||
$(BUILD) -lelf
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@
|
|||
# include "test-dwarf.c"
|
||||
#undef main
|
||||
|
||||
#define main main_test_dwarf_getlocations
|
||||
# include "test-dwarf_getlocations.c"
|
||||
#undef main
|
||||
|
||||
#define main main_test_libelf_getphdrnum
|
||||
# include "test-libelf-getphdrnum.c"
|
||||
#undef main
|
||||
|
|
@ -143,6 +147,7 @@ int main(int argc, char *argv[])
|
|||
main_test_libelf_mmap();
|
||||
main_test_glibc();
|
||||
main_test_dwarf();
|
||||
main_test_dwarf_getlocations();
|
||||
main_test_libelf_getphdrnum();
|
||||
main_test_libunwind();
|
||||
main_test_libaudit();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
#include <stdlib.h>
|
||||
#include <elfutils/libdw.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Dwarf_Addr base, start, end;
|
||||
Dwarf_Attribute attr;
|
||||
Dwarf_Op *op;
|
||||
size_t nops;
|
||||
ptrdiff_t offset = 0;
|
||||
return (int)dwarf_getlocations(&attr, offset, &base, &start, &end, &op, &nops);
|
||||
}
|
||||
|
|
@ -93,6 +93,67 @@ raw encoding of 0x1A8 can be used:
|
|||
You should refer to the processor specific documentation for getting these
|
||||
details. Some of them are referenced in the SEE ALSO section below.
|
||||
|
||||
ARBITRARY PMUS
|
||||
--------------
|
||||
|
||||
perf also supports an extended syntax for specifying raw parameters
|
||||
to PMUs. Using this typically requires looking up the specific event
|
||||
in the CPU vendor specific documentation.
|
||||
|
||||
The available PMUs and their raw parameters can be listed with
|
||||
|
||||
ls /sys/devices/*/format
|
||||
|
||||
For example the raw event "LSD.UOPS" core pmu event above could
|
||||
be specified as
|
||||
|
||||
perf stat -e cpu/event=0xa8,umask=0x1,name=LSD.UOPS_CYCLES,cmask=1/ ...
|
||||
|
||||
PER SOCKET PMUS
|
||||
---------------
|
||||
|
||||
Some PMUs are not associated with a core, but with a whole CPU socket.
|
||||
Events on these PMUs generally cannot be sampled, but only counted globally
|
||||
with perf stat -a. They can be bound to one logical CPU, but will measure
|
||||
all the CPUs in the same socket.
|
||||
|
||||
This example measures memory bandwidth every second
|
||||
on the first memory controller on socket 0 of a Intel Xeon system
|
||||
|
||||
perf stat -C 0 -a uncore_imc_0/cas_count_read/,uncore_imc_0/cas_count_write/ -I 1000 ...
|
||||
|
||||
Each memory controller has its own PMU. Measuring the complete system
|
||||
bandwidth would require specifying all imc PMUs (see perf list output),
|
||||
and adding the values together.
|
||||
|
||||
This example measures the combined core power every second
|
||||
|
||||
perf stat -I 1000 -e power/energy-cores/ -a
|
||||
|
||||
ACCESS RESTRICTIONS
|
||||
-------------------
|
||||
|
||||
For non root users generally only context switched PMU events are available.
|
||||
This is normally only the events in the cpu PMU, the predefined events
|
||||
like cycles and instructions and some software events.
|
||||
|
||||
Other PMUs and global measurements are normally root only.
|
||||
Some event qualifiers, such as "any", are also root only.
|
||||
|
||||
This can be overriden by setting the kernel.perf_event_paranoid
|
||||
sysctl to -1, which allows non root to use these events.
|
||||
|
||||
For accessing trace point events perf needs to have read access to
|
||||
/sys/kernel/debug/tracing, even when perf_event_paranoid is in a relaxed
|
||||
setting.
|
||||
|
||||
TRACING
|
||||
-------
|
||||
|
||||
Some PMUs control advanced hardware tracing capabilities, such as Intel PT,
|
||||
that allows low overhead execution tracing. These are described in a separate
|
||||
intel-pt.txt document.
|
||||
|
||||
PARAMETERIZED EVENTS
|
||||
--------------------
|
||||
|
||||
|
|
@ -106,6 +167,50 @@ also be supplied. For example:
|
|||
|
||||
perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ...
|
||||
|
||||
EVENT GROUPS
|
||||
------------
|
||||
|
||||
Perf supports time based multiplexing of events, when the number of events
|
||||
active exceeds the number of hardware performance counters. Multiplexing
|
||||
can cause measurement errors when the workload changes its execution
|
||||
profile.
|
||||
|
||||
When metrics are computed using formulas from event counts, it is useful to
|
||||
ensure some events are always measured together as a group to minimize multiplexing
|
||||
errors. Event groups can be specified using { }.
|
||||
|
||||
perf stat -e '{instructions,cycles}' ...
|
||||
|
||||
The number of available performance counters depend on the CPU. A group
|
||||
cannot contain more events than available counters.
|
||||
For example Intel Core CPUs typically have four generic performance counters
|
||||
for the core, plus three fixed counters for instructions, cycles and
|
||||
ref-cycles. Some special events have restrictions on which counter they
|
||||
can schedule, and may not support multiple instances in a single group.
|
||||
When too many events are specified in the group none of them will not
|
||||
be measured.
|
||||
|
||||
Globally pinned events can limit the number of counters available for
|
||||
other groups. On x86 systems, the NMI watchdog pins a counter by default.
|
||||
The nmi watchdog can be disabled as root with
|
||||
|
||||
echo 0 > /proc/sys/kernel/nmi_watchdog
|
||||
|
||||
Events from multiple different PMUs cannot be mixed in a group, with
|
||||
some exceptions for software events.
|
||||
|
||||
LEADER SAMPLING
|
||||
---------------
|
||||
|
||||
perf also supports group leader sampling using the :S specifier.
|
||||
|
||||
perf record -e '{cycles,instructions}:S' ...
|
||||
perf report --group
|
||||
|
||||
Normally all events in a event group sample, but with :S only
|
||||
the first event (the leader) samples, and it only reads the values of the
|
||||
other events in the group.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
|
|
@ -143,5 +248,5 @@ SEE ALSO
|
|||
--------
|
||||
linkperf:perf-stat[1], linkperf:perf-top[1],
|
||||
linkperf:perf-record[1],
|
||||
http://www.intel.com/Assets/PDF/manual/253669.pdf[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide],
|
||||
http://www.intel.com/sdm/[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide],
|
||||
http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming]
|
||||
|
|
|
|||
|
|
@ -183,6 +183,11 @@ endif
|
|||
include config/Makefile
|
||||
endif
|
||||
|
||||
ifeq ($(config),0)
|
||||
include $(srctree)/tools/scripts/Makefile.arch
|
||||
-include arch/$(ARCH)/Makefile
|
||||
endif
|
||||
|
||||
# The FEATURE_DUMP_EXPORT holds location of the actual
|
||||
# FEATURE_DUMP file to be used to bypass feature detection
|
||||
# (for bpf or any other subproject)
|
||||
|
|
@ -297,8 +302,6 @@ endif
|
|||
# because maintaining the nesting to match is a pain. If
|
||||
# we had "elif" things would have been much nicer...
|
||||
|
||||
-include arch/$(ARCH)/Makefile
|
||||
|
||||
ifneq ($(OUTPUT),)
|
||||
CFLAGS += -I$(OUTPUT)
|
||||
endif
|
||||
|
|
@ -390,7 +393,7 @@ endif
|
|||
__build-dir = $(subst $(OUTPUT),,$(dir $@))
|
||||
build-dir = $(if $(__build-dir),$(__build-dir),.)
|
||||
|
||||
prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep
|
||||
prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep archheaders
|
||||
|
||||
$(OUTPUT)%.o: %.c prepare FORCE
|
||||
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
|
||||
|
|
@ -430,7 +433,7 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
|
|||
|
||||
LIBPERF_IN := $(OUTPUT)libperf-in.o
|
||||
|
||||
$(LIBPERF_IN): fixdep FORCE
|
||||
$(LIBPERF_IN): prepare fixdep FORCE
|
||||
$(Q)$(MAKE) $(build)=libperf
|
||||
|
||||
$(LIB_FILE): $(LIBPERF_IN)
|
||||
|
|
@ -625,7 +628,7 @@ config-clean:
|
|||
$(call QUIET_CLEAN, config)
|
||||
$(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null
|
||||
|
||||
clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean
|
||||
clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean
|
||||
$(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
|
||||
$(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
|
||||
$(Q)$(RM) $(OUTPUT).config-detected
|
||||
|
|
@ -662,5 +665,5 @@ FORCE:
|
|||
.PHONY: all install clean config-clean strip install-gtk
|
||||
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
|
||||
.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare
|
||||
.PHONY: libtraceevent_plugins
|
||||
.PHONY: libtraceevent_plugins archheaders
|
||||
|
||||
|
|
|
|||
|
|
@ -4,3 +4,26 @@ endif
|
|||
HAVE_KVM_STAT_SUPPORT := 1
|
||||
PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
|
||||
PERF_HAVE_JITDUMP := 1
|
||||
|
||||
###
|
||||
# Syscall table generation
|
||||
#
|
||||
|
||||
out := $(OUTPUT)arch/x86/include/generated/asm
|
||||
header := $(out)/syscalls_64.c
|
||||
sys := $(srctree)/tools/perf/arch/x86/entry/syscalls
|
||||
systbl := $(sys)/syscalltbl.sh
|
||||
|
||||
# Create output directory if not already present
|
||||
_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
|
||||
|
||||
$(header): $(sys)/syscall_64.tbl $(systbl)
|
||||
@(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
|
||||
(diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \
|
||||
|| echo "Warning: x86_64's syscall_64.tbl differs from kernel" >&2 )) || true
|
||||
$(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@
|
||||
|
||||
clean::
|
||||
rm -f $(header)
|
||||
|
||||
archheaders: $(header)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,374 @@
|
|||
#
|
||||
# 64-bit system call numbers and entry vectors
|
||||
#
|
||||
# The format is:
|
||||
# <number> <abi> <name> <entry point>
|
||||
#
|
||||
# The abi is "common", "64" or "x32" for this file.
|
||||
#
|
||||
0 common read sys_read
|
||||
1 common write sys_write
|
||||
2 common open sys_open
|
||||
3 common close sys_close
|
||||
4 common stat sys_newstat
|
||||
5 common fstat sys_newfstat
|
||||
6 common lstat sys_newlstat
|
||||
7 common poll sys_poll
|
||||
8 common lseek sys_lseek
|
||||
9 common mmap sys_mmap
|
||||
10 common mprotect sys_mprotect
|
||||
11 common munmap sys_munmap
|
||||
12 common brk sys_brk
|
||||
13 64 rt_sigaction sys_rt_sigaction
|
||||
14 common rt_sigprocmask sys_rt_sigprocmask
|
||||
15 64 rt_sigreturn sys_rt_sigreturn/ptregs
|
||||
16 64 ioctl sys_ioctl
|
||||
17 common pread64 sys_pread64
|
||||
18 common pwrite64 sys_pwrite64
|
||||
19 64 readv sys_readv
|
||||
20 64 writev sys_writev
|
||||
21 common access sys_access
|
||||
22 common pipe sys_pipe
|
||||
23 common select sys_select
|
||||
24 common sched_yield sys_sched_yield
|
||||
25 common mremap sys_mremap
|
||||
26 common msync sys_msync
|
||||
27 common mincore sys_mincore
|
||||
28 common madvise sys_madvise
|
||||
29 common shmget sys_shmget
|
||||
30 common shmat sys_shmat
|
||||
31 common shmctl sys_shmctl
|
||||
32 common dup sys_dup
|
||||
33 common dup2 sys_dup2
|
||||
34 common pause sys_pause
|
||||
35 common nanosleep sys_nanosleep
|
||||
36 common getitimer sys_getitimer
|
||||
37 common alarm sys_alarm
|
||||
38 common setitimer sys_setitimer
|
||||
39 common getpid sys_getpid
|
||||
40 common sendfile sys_sendfile64
|
||||
41 common socket sys_socket
|
||||
42 common connect sys_connect
|
||||
43 common accept sys_accept
|
||||
44 common sendto sys_sendto
|
||||
45 64 recvfrom sys_recvfrom
|
||||
46 64 sendmsg sys_sendmsg
|
||||
47 64 recvmsg sys_recvmsg
|
||||
48 common shutdown sys_shutdown
|
||||
49 common bind sys_bind
|
||||
50 common listen sys_listen
|
||||
51 common getsockname sys_getsockname
|
||||
52 common getpeername sys_getpeername
|
||||
53 common socketpair sys_socketpair
|
||||
54 64 setsockopt sys_setsockopt
|
||||
55 64 getsockopt sys_getsockopt
|
||||
56 common clone sys_clone/ptregs
|
||||
57 common fork sys_fork/ptregs
|
||||
58 common vfork sys_vfork/ptregs
|
||||
59 64 execve sys_execve/ptregs
|
||||
60 common exit sys_exit
|
||||
61 common wait4 sys_wait4
|
||||
62 common kill sys_kill
|
||||
63 common uname sys_newuname
|
||||
64 common semget sys_semget
|
||||
65 common semop sys_semop
|
||||
66 common semctl sys_semctl
|
||||
67 common shmdt sys_shmdt
|
||||
68 common msgget sys_msgget
|
||||
69 common msgsnd sys_msgsnd
|
||||
70 common msgrcv sys_msgrcv
|
||||
71 common msgctl sys_msgctl
|
||||
72 common fcntl sys_fcntl
|
||||
73 common flock sys_flock
|
||||
74 common fsync sys_fsync
|
||||
75 common fdatasync sys_fdatasync
|
||||
76 common truncate sys_truncate
|
||||
77 common ftruncate sys_ftruncate
|
||||
78 common getdents sys_getdents
|
||||
79 common getcwd sys_getcwd
|
||||
80 common chdir sys_chdir
|
||||
81 common fchdir sys_fchdir
|
||||
82 common rename sys_rename
|
||||
83 common mkdir sys_mkdir
|
||||
84 common rmdir sys_rmdir
|
||||
85 common creat sys_creat
|
||||
86 common link sys_link
|
||||
87 common unlink sys_unlink
|
||||
88 common symlink sys_symlink
|
||||
89 common readlink sys_readlink
|
||||
90 common chmod sys_chmod
|
||||
91 common fchmod sys_fchmod
|
||||
92 common chown sys_chown
|
||||
93 common fchown sys_fchown
|
||||
94 common lchown sys_lchown
|
||||
95 common umask sys_umask
|
||||
96 common gettimeofday sys_gettimeofday
|
||||
97 common getrlimit sys_getrlimit
|
||||
98 common getrusage sys_getrusage
|
||||
99 common sysinfo sys_sysinfo
|
||||
100 common times sys_times
|
||||
101 64 ptrace sys_ptrace
|
||||
102 common getuid sys_getuid
|
||||
103 common syslog sys_syslog
|
||||
104 common getgid sys_getgid
|
||||
105 common setuid sys_setuid
|
||||
106 common setgid sys_setgid
|
||||
107 common geteuid sys_geteuid
|
||||
108 common getegid sys_getegid
|
||||
109 common setpgid sys_setpgid
|
||||
110 common getppid sys_getppid
|
||||
111 common getpgrp sys_getpgrp
|
||||
112 common setsid sys_setsid
|
||||
113 common setreuid sys_setreuid
|
||||
114 common setregid sys_setregid
|
||||
115 common getgroups sys_getgroups
|
||||
116 common setgroups sys_setgroups
|
||||
117 common setresuid sys_setresuid
|
||||
118 common getresuid sys_getresuid
|
||||
119 common setresgid sys_setresgid
|
||||
120 common getresgid sys_getresgid
|
||||
121 common getpgid sys_getpgid
|
||||
122 common setfsuid sys_setfsuid
|
||||
123 common setfsgid sys_setfsgid
|
||||
124 common getsid sys_getsid
|
||||
125 common capget sys_capget
|
||||
126 common capset sys_capset
|
||||
127 64 rt_sigpending sys_rt_sigpending
|
||||
128 64 rt_sigtimedwait sys_rt_sigtimedwait
|
||||
129 64 rt_sigqueueinfo sys_rt_sigqueueinfo
|
||||
130 common rt_sigsuspend sys_rt_sigsuspend
|
||||
131 64 sigaltstack sys_sigaltstack
|
||||
132 common utime sys_utime
|
||||
133 common mknod sys_mknod
|
||||
134 64 uselib
|
||||
135 common personality sys_personality
|
||||
136 common ustat sys_ustat
|
||||
137 common statfs sys_statfs
|
||||
138 common fstatfs sys_fstatfs
|
||||
139 common sysfs sys_sysfs
|
||||
140 common getpriority sys_getpriority
|
||||
141 common setpriority sys_setpriority
|
||||
142 common sched_setparam sys_sched_setparam
|
||||
143 common sched_getparam sys_sched_getparam
|
||||
144 common sched_setscheduler sys_sched_setscheduler
|
||||
145 common sched_getscheduler sys_sched_getscheduler
|
||||
146 common sched_get_priority_max sys_sched_get_priority_max
|
||||
147 common sched_get_priority_min sys_sched_get_priority_min
|
||||
148 common sched_rr_get_interval sys_sched_rr_get_interval
|
||||
149 common mlock sys_mlock
|
||||
150 common munlock sys_munlock
|
||||
151 common mlockall sys_mlockall
|
||||
152 common munlockall sys_munlockall
|
||||
153 common vhangup sys_vhangup
|
||||
154 common modify_ldt sys_modify_ldt
|
||||
155 common pivot_root sys_pivot_root
|
||||
156 64 _sysctl sys_sysctl
|
||||
157 common prctl sys_prctl
|
||||
158 common arch_prctl sys_arch_prctl
|
||||
159 common adjtimex sys_adjtimex
|
||||
160 common setrlimit sys_setrlimit
|
||||
161 common chroot sys_chroot
|
||||
162 common sync sys_sync
|
||||
163 common acct sys_acct
|
||||
164 common settimeofday sys_settimeofday
|
||||
165 common mount sys_mount
|
||||
166 common umount2 sys_umount
|
||||
167 common swapon sys_swapon
|
||||
168 common swapoff sys_swapoff
|
||||
169 common reboot sys_reboot
|
||||
170 common sethostname sys_sethostname
|
||||
171 common setdomainname sys_setdomainname
|
||||
172 common iopl sys_iopl/ptregs
|
||||
173 common ioperm sys_ioperm
|
||||
174 64 create_module
|
||||
175 common init_module sys_init_module
|
||||
176 common delete_module sys_delete_module
|
||||
177 64 get_kernel_syms
|
||||
178 64 query_module
|
||||
179 common quotactl sys_quotactl
|
||||
180 64 nfsservctl
|
||||
181 common getpmsg
|
||||
182 common putpmsg
|
||||
183 common afs_syscall
|
||||
184 common tuxcall
|
||||
185 common security
|
||||
186 common gettid sys_gettid
|
||||
187 common readahead sys_readahead
|
||||
188 common setxattr sys_setxattr
|
||||
189 common lsetxattr sys_lsetxattr
|
||||
190 common fsetxattr sys_fsetxattr
|
||||
191 common getxattr sys_getxattr
|
||||
192 common lgetxattr sys_lgetxattr
|
||||
193 common fgetxattr sys_fgetxattr
|
||||
194 common listxattr sys_listxattr
|
||||
195 common llistxattr sys_llistxattr
|
||||
196 common flistxattr sys_flistxattr
|
||||
197 common removexattr sys_removexattr
|
||||
198 common lremovexattr sys_lremovexattr
|
||||
199 common fremovexattr sys_fremovexattr
|
||||
200 common tkill sys_tkill
|
||||
201 common time sys_time
|
||||
202 common futex sys_futex
|
||||
203 common sched_setaffinity sys_sched_setaffinity
|
||||
204 common sched_getaffinity sys_sched_getaffinity
|
||||
205 64 set_thread_area
|
||||
206 64 io_setup sys_io_setup
|
||||
207 common io_destroy sys_io_destroy
|
||||
208 common io_getevents sys_io_getevents
|
||||
209 64 io_submit sys_io_submit
|
||||
210 common io_cancel sys_io_cancel
|
||||
211 64 get_thread_area
|
||||
212 common lookup_dcookie sys_lookup_dcookie
|
||||
213 common epoll_create sys_epoll_create
|
||||
214 64 epoll_ctl_old
|
||||
215 64 epoll_wait_old
|
||||
216 common remap_file_pages sys_remap_file_pages
|
||||
217 common getdents64 sys_getdents64
|
||||
218 common set_tid_address sys_set_tid_address
|
||||
219 common restart_syscall sys_restart_syscall
|
||||
220 common semtimedop sys_semtimedop
|
||||
221 common fadvise64 sys_fadvise64
|
||||
222 64 timer_create sys_timer_create
|
||||
223 common timer_settime sys_timer_settime
|
||||
224 common timer_gettime sys_timer_gettime
|
||||
225 common timer_getoverrun sys_timer_getoverrun
|
||||
226 common timer_delete sys_timer_delete
|
||||
227 common clock_settime sys_clock_settime
|
||||
228 common clock_gettime sys_clock_gettime
|
||||
229 common clock_getres sys_clock_getres
|
||||
230 common clock_nanosleep sys_clock_nanosleep
|
||||
231 common exit_group sys_exit_group
|
||||
232 common epoll_wait sys_epoll_wait
|
||||
233 common epoll_ctl sys_epoll_ctl
|
||||
234 common tgkill sys_tgkill
|
||||
235 common utimes sys_utimes
|
||||
236 64 vserver
|
||||
237 common mbind sys_mbind
|
||||
238 common set_mempolicy sys_set_mempolicy
|
||||
239 common get_mempolicy sys_get_mempolicy
|
||||
240 common mq_open sys_mq_open
|
||||
241 common mq_unlink sys_mq_unlink
|
||||
242 common mq_timedsend sys_mq_timedsend
|
||||
243 common mq_timedreceive sys_mq_timedreceive
|
||||
244 64 mq_notify sys_mq_notify
|
||||
245 common mq_getsetattr sys_mq_getsetattr
|
||||
246 64 kexec_load sys_kexec_load
|
||||
247 64 waitid sys_waitid
|
||||
248 common add_key sys_add_key
|
||||
249 common request_key sys_request_key
|
||||
250 common keyctl sys_keyctl
|
||||
251 common ioprio_set sys_ioprio_set
|
||||
252 common ioprio_get sys_ioprio_get
|
||||
253 common inotify_init sys_inotify_init
|
||||
254 common inotify_add_watch sys_inotify_add_watch
|
||||
255 common inotify_rm_watch sys_inotify_rm_watch
|
||||
256 common migrate_pages sys_migrate_pages
|
||||
257 common openat sys_openat
|
||||
258 common mkdirat sys_mkdirat
|
||||
259 common mknodat sys_mknodat
|
||||
260 common fchownat sys_fchownat
|
||||
261 common futimesat sys_futimesat
|
||||
262 common newfstatat sys_newfstatat
|
||||
263 common unlinkat sys_unlinkat
|
||||
264 common renameat sys_renameat
|
||||
265 common linkat sys_linkat
|
||||
266 common symlinkat sys_symlinkat
|
||||
267 common readlinkat sys_readlinkat
|
||||
268 common fchmodat sys_fchmodat
|
||||
269 common faccessat sys_faccessat
|
||||
270 common pselect6 sys_pselect6
|
||||
271 common ppoll sys_ppoll
|
||||
272 common unshare sys_unshare
|
||||
273 64 set_robust_list sys_set_robust_list
|
||||
274 64 get_robust_list sys_get_robust_list
|
||||
275 common splice sys_splice
|
||||
276 common tee sys_tee
|
||||
277 common sync_file_range sys_sync_file_range
|
||||
278 64 vmsplice sys_vmsplice
|
||||
279 64 move_pages sys_move_pages
|
||||
280 common utimensat sys_utimensat
|
||||
281 common epoll_pwait sys_epoll_pwait
|
||||
282 common signalfd sys_signalfd
|
||||
283 common timerfd_create sys_timerfd_create
|
||||
284 common eventfd sys_eventfd
|
||||
285 common fallocate sys_fallocate
|
||||
286 common timerfd_settime sys_timerfd_settime
|
||||
287 common timerfd_gettime sys_timerfd_gettime
|
||||
288 common accept4 sys_accept4
|
||||
289 common signalfd4 sys_signalfd4
|
||||
290 common eventfd2 sys_eventfd2
|
||||
291 common epoll_create1 sys_epoll_create1
|
||||
292 common dup3 sys_dup3
|
||||
293 common pipe2 sys_pipe2
|
||||
294 common inotify_init1 sys_inotify_init1
|
||||
295 64 preadv sys_preadv
|
||||
296 64 pwritev sys_pwritev
|
||||
297 64 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo
|
||||
298 common perf_event_open sys_perf_event_open
|
||||
299 64 recvmmsg sys_recvmmsg
|
||||
300 common fanotify_init sys_fanotify_init
|
||||
301 common fanotify_mark sys_fanotify_mark
|
||||
302 common prlimit64 sys_prlimit64
|
||||
303 common name_to_handle_at sys_name_to_handle_at
|
||||
304 common open_by_handle_at sys_open_by_handle_at
|
||||
305 common clock_adjtime sys_clock_adjtime
|
||||
306 common syncfs sys_syncfs
|
||||
307 64 sendmmsg sys_sendmmsg
|
||||
308 common setns sys_setns
|
||||
309 common getcpu sys_getcpu
|
||||
310 64 process_vm_readv sys_process_vm_readv
|
||||
311 64 process_vm_writev sys_process_vm_writev
|
||||
312 common kcmp sys_kcmp
|
||||
313 common finit_module sys_finit_module
|
||||
314 common sched_setattr sys_sched_setattr
|
||||
315 common sched_getattr sys_sched_getattr
|
||||
316 common renameat2 sys_renameat2
|
||||
317 common seccomp sys_seccomp
|
||||
318 common getrandom sys_getrandom
|
||||
319 common memfd_create sys_memfd_create
|
||||
320 common kexec_file_load sys_kexec_file_load
|
||||
321 common bpf sys_bpf
|
||||
322 64 execveat sys_execveat/ptregs
|
||||
323 common userfaultfd sys_userfaultfd
|
||||
324 common membarrier sys_membarrier
|
||||
325 common mlock2 sys_mlock2
|
||||
326 common copy_file_range sys_copy_file_range
|
||||
|
||||
#
|
||||
# x32-specific system call numbers start at 512 to avoid cache impact
|
||||
# for native 64-bit operation.
|
||||
#
|
||||
512 x32 rt_sigaction compat_sys_rt_sigaction
|
||||
513 x32 rt_sigreturn sys32_x32_rt_sigreturn
|
||||
514 x32 ioctl compat_sys_ioctl
|
||||
515 x32 readv compat_sys_readv
|
||||
516 x32 writev compat_sys_writev
|
||||
517 x32 recvfrom compat_sys_recvfrom
|
||||
518 x32 sendmsg compat_sys_sendmsg
|
||||
519 x32 recvmsg compat_sys_recvmsg
|
||||
520 x32 execve compat_sys_execve/ptregs
|
||||
521 x32 ptrace compat_sys_ptrace
|
||||
522 x32 rt_sigpending compat_sys_rt_sigpending
|
||||
523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait
|
||||
524 x32 rt_sigqueueinfo compat_sys_rt_sigqueueinfo
|
||||
525 x32 sigaltstack compat_sys_sigaltstack
|
||||
526 x32 timer_create compat_sys_timer_create
|
||||
527 x32 mq_notify compat_sys_mq_notify
|
||||
528 x32 kexec_load compat_sys_kexec_load
|
||||
529 x32 waitid compat_sys_waitid
|
||||
530 x32 set_robust_list compat_sys_set_robust_list
|
||||
531 x32 get_robust_list compat_sys_get_robust_list
|
||||
532 x32 vmsplice compat_sys_vmsplice
|
||||
533 x32 move_pages compat_sys_move_pages
|
||||
534 x32 preadv compat_sys_preadv64
|
||||
535 x32 pwritev compat_sys_pwritev64
|
||||
536 x32 rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
|
||||
537 x32 recvmmsg compat_sys_recvmmsg
|
||||
538 x32 sendmmsg compat_sys_sendmmsg
|
||||
539 x32 process_vm_readv compat_sys_process_vm_readv
|
||||
540 x32 process_vm_writev compat_sys_process_vm_writev
|
||||
541 x32 setsockopt compat_sys_setsockopt
|
||||
542 x32 getsockopt compat_sys_getsockopt
|
||||
543 x32 io_setup compat_sys_io_setup
|
||||
544 x32 io_submit compat_sys_io_submit
|
||||
545 x32 execveat compat_sys_execveat/ptregs
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#!/bin/sh
|
||||
|
||||
in="$1"
|
||||
arch="$2"
|
||||
|
||||
syscall_macro() {
|
||||
nr="$1"
|
||||
name="$2"
|
||||
|
||||
echo " [$nr] = \"$name\","
|
||||
}
|
||||
|
||||
emit() {
|
||||
nr="$1"
|
||||
entry="$2"
|
||||
|
||||
syscall_macro "$nr" "$entry"
|
||||
}
|
||||
|
||||
echo "static const char *syscalltbl_${arch}[] = {"
|
||||
|
||||
sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
|
||||
grep '^[0-9]' "$in" | sort -n > $sorted_table
|
||||
|
||||
max_nr=0
|
||||
while read nr abi name entry compat; do
|
||||
if [ $nr -ge 512 ] ; then # discard compat sycalls
|
||||
break
|
||||
fi
|
||||
|
||||
emit "$nr" "$name"
|
||||
max_nr=$nr
|
||||
done < $sorted_table
|
||||
|
||||
rm -f $sorted_table
|
||||
|
||||
echo "};"
|
||||
|
||||
echo "#define SYSCALLTBL_${arch}_MAX_ID ${max_nr}"
|
||||
|
|
@ -1961,6 +1961,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||
.exit = perf_event__process_exit,
|
||||
.fork = perf_event__process_fork,
|
||||
.attr = process_attr,
|
||||
.event_update = perf_event__process_event_update,
|
||||
.tracing_data = perf_event__process_tracing_data,
|
||||
.build_id = perf_event__process_build_id,
|
||||
.id_index = perf_event__process_id_index,
|
||||
|
|
|
|||
|
|
@ -34,8 +34,9 @@
|
|||
#include "trace-event.h"
|
||||
#include "util/parse-events.h"
|
||||
#include "util/bpf-loader.h"
|
||||
#include "syscalltbl.h"
|
||||
|
||||
#include <libaudit.h>
|
||||
#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <linux/futex.h>
|
||||
|
|
@ -112,6 +113,56 @@
|
|||
# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
|
||||
#endif
|
||||
|
||||
struct trace {
|
||||
struct perf_tool tool;
|
||||
struct syscalltbl *sctbl;
|
||||
struct {
|
||||
int max;
|
||||
struct syscall *table;
|
||||
struct {
|
||||
struct perf_evsel *sys_enter,
|
||||
*sys_exit;
|
||||
} events;
|
||||
} syscalls;
|
||||
struct record_opts opts;
|
||||
struct perf_evlist *evlist;
|
||||
struct machine *host;
|
||||
struct thread *current;
|
||||
u64 base_time;
|
||||
FILE *output;
|
||||
unsigned long nr_events;
|
||||
struct strlist *ev_qualifier;
|
||||
struct {
|
||||
size_t nr;
|
||||
int *entries;
|
||||
} ev_qualifier_ids;
|
||||
struct intlist *tid_list;
|
||||
struct intlist *pid_list;
|
||||
struct {
|
||||
size_t nr;
|
||||
pid_t *entries;
|
||||
} filter_pids;
|
||||
double duration_filter;
|
||||
double runtime_ms;
|
||||
struct {
|
||||
u64 vfs_getname,
|
||||
proc_getname;
|
||||
} stats;
|
||||
bool not_ev_qualifier;
|
||||
bool live;
|
||||
bool full_time;
|
||||
bool sched;
|
||||
bool multiple_threads;
|
||||
bool summary;
|
||||
bool summary_only;
|
||||
bool show_comm;
|
||||
bool show_tool_stats;
|
||||
bool trace_syscalls;
|
||||
bool force;
|
||||
bool vfs_getname;
|
||||
int trace_pgfaults;
|
||||
int open_id;
|
||||
};
|
||||
|
||||
struct tp_field {
|
||||
int offset;
|
||||
|
|
@ -1073,12 +1124,18 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
|
|||
.arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
|
||||
.arg_parm = { [arg] = &strarray__##array, }
|
||||
|
||||
#include "trace/beauty/pid.c"
|
||||
#include "trace/beauty/mode_t.c"
|
||||
#include "trace/beauty/sched_policy.c"
|
||||
#include "trace/beauty/waitid_options.c"
|
||||
|
||||
static struct syscall_fmt {
|
||||
const char *name;
|
||||
const char *alias;
|
||||
size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
|
||||
void *arg_parm[6];
|
||||
bool errmsg;
|
||||
bool errpid;
|
||||
bool timeout;
|
||||
bool hexret;
|
||||
} syscall_fmts[] = {
|
||||
|
|
@ -1096,6 +1153,7 @@ static struct syscall_fmt {
|
|||
{ .name = "chroot", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
|
||||
{ .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
|
||||
{ .name = "clone", .errpid = true, },
|
||||
{ .name = "close", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
|
||||
{ .name = "connect", .errmsg = true, },
|
||||
|
|
@ -1161,6 +1219,9 @@ static struct syscall_fmt {
|
|||
{ .name = "getdents64", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
||||
{ .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
|
||||
{ .name = "getpid", .errpid = true, },
|
||||
{ .name = "getpgid", .errpid = true, },
|
||||
{ .name = "getppid", .errpid = true, },
|
||||
{ .name = "getrandom", .errmsg = true,
|
||||
.arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
|
||||
{ .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
|
||||
|
|
@ -1304,6 +1365,8 @@ static struct syscall_fmt {
|
|||
.arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
|
||||
{ .name = "rt_tgsigqueueinfo", .errmsg = true,
|
||||
.arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
|
||||
{ .name = "sched_setscheduler", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
|
||||
{ .name = "seccomp", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
|
||||
[1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
|
||||
|
|
@ -1317,7 +1380,9 @@ static struct syscall_fmt {
|
|||
{ .name = "sendto", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */
|
||||
[3] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||
{ .name = "set_tid_address", .errpid = true, },
|
||||
{ .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
|
||||
{ .name = "setpgid", .errmsg = true, },
|
||||
{ .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
|
||||
{ .name = "setxattr", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
|
||||
|
|
@ -1360,6 +1425,10 @@ static struct syscall_fmt {
|
|||
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
|
||||
{ .name = "vmsplice", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
||||
{ .name = "wait4", .errpid = true,
|
||||
.arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
|
||||
{ .name = "waitid", .errpid = true,
|
||||
.arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
|
||||
{ .name = "write", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
|
||||
{ .name = "writev", .errmsg = true,
|
||||
|
|
@ -1471,59 +1540,6 @@ fail:
|
|||
|
||||
static const size_t trace__entry_str_size = 2048;
|
||||
|
||||
struct trace {
|
||||
struct perf_tool tool;
|
||||
struct {
|
||||
int machine;
|
||||
int open_id;
|
||||
} audit;
|
||||
struct {
|
||||
int max;
|
||||
struct syscall *table;
|
||||
struct {
|
||||
struct perf_evsel *sys_enter,
|
||||
*sys_exit;
|
||||
} events;
|
||||
} syscalls;
|
||||
struct record_opts opts;
|
||||
struct perf_evlist *evlist;
|
||||
struct machine *host;
|
||||
struct thread *current;
|
||||
u64 base_time;
|
||||
FILE *output;
|
||||
unsigned long nr_events;
|
||||
struct strlist *ev_qualifier;
|
||||
struct {
|
||||
size_t nr;
|
||||
int *entries;
|
||||
} ev_qualifier_ids;
|
||||
struct intlist *tid_list;
|
||||
struct intlist *pid_list;
|
||||
struct {
|
||||
size_t nr;
|
||||
pid_t *entries;
|
||||
} filter_pids;
|
||||
double duration_filter;
|
||||
double runtime_ms;
|
||||
struct {
|
||||
u64 vfs_getname,
|
||||
proc_getname;
|
||||
} stats;
|
||||
bool not_ev_qualifier;
|
||||
bool live;
|
||||
bool full_time;
|
||||
bool sched;
|
||||
bool multiple_threads;
|
||||
bool summary;
|
||||
bool summary_only;
|
||||
bool show_comm;
|
||||
bool show_tool_stats;
|
||||
bool trace_syscalls;
|
||||
bool force;
|
||||
bool vfs_getname;
|
||||
int trace_pgfaults;
|
||||
};
|
||||
|
||||
static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
|
||||
{
|
||||
struct thread_trace *ttrace = thread__priv(thread);
|
||||
|
|
@ -1749,6 +1765,10 @@ static int syscall__set_arg_fmts(struct syscall *sc)
|
|||
sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
|
||||
else if (field->flags & FIELD_IS_POINTER)
|
||||
sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
|
||||
else if (strcmp(field->type, "pid_t") == 0)
|
||||
sc->arg_scnprintf[idx] = SCA_PID;
|
||||
else if (strcmp(field->type, "umode_t") == 0)
|
||||
sc->arg_scnprintf[idx] = SCA_MODE_T;
|
||||
++idx;
|
||||
}
|
||||
|
||||
|
|
@ -1759,7 +1779,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
|
|||
{
|
||||
char tp_name[128];
|
||||
struct syscall *sc;
|
||||
const char *name = audit_syscall_to_name(id, trace->audit.machine);
|
||||
const char *name = syscalltbl__name(trace->sctbl, id);
|
||||
|
||||
if (name == NULL)
|
||||
return -1;
|
||||
|
|
@ -1834,7 +1854,7 @@ static int trace__validate_ev_qualifier(struct trace *trace)
|
|||
|
||||
strlist__for_each(pos, trace->ev_qualifier) {
|
||||
const char *sc = pos->s;
|
||||
int id = audit_name_to_syscall(sc, trace->audit.machine);
|
||||
int id = syscalltbl__id(trace->sctbl, sc);
|
||||
|
||||
if (id < 0) {
|
||||
if (err == 0) {
|
||||
|
|
@ -2116,7 +2136,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
|
|||
|
||||
ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
|
||||
|
||||
if (id == trace->audit.open_id && ret >= 0 && ttrace->filename.pending_open) {
|
||||
if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
|
||||
trace__set_fd_pathname(thread, ret, ttrace->filename.name);
|
||||
ttrace->filename.pending_open = false;
|
||||
++trace->stats.vfs_getname;
|
||||
|
|
@ -2147,7 +2167,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
|
|||
if (sc->fmt == NULL) {
|
||||
signed_print:
|
||||
fprintf(trace->output, ") = %ld", ret);
|
||||
} else if (ret < 0 && sc->fmt->errmsg) {
|
||||
} else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
|
||||
char bf[STRERR_BUFSIZE];
|
||||
const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
|
||||
*e = audit_errno_to_name(-ret);
|
||||
|
|
@ -2157,7 +2177,16 @@ signed_print:
|
|||
fprintf(trace->output, ") = 0 Timeout");
|
||||
else if (sc->fmt->hexret)
|
||||
fprintf(trace->output, ") = %#lx", ret);
|
||||
else
|
||||
else if (sc->fmt->errpid) {
|
||||
struct thread *child = machine__find_thread(trace->host, ret, ret);
|
||||
|
||||
if (child != NULL) {
|
||||
fprintf(trace->output, ") = %ld", ret);
|
||||
if (child->comm_set)
|
||||
fprintf(trace->output, " (%s)", thread__comm_str(child));
|
||||
thread__put(child);
|
||||
}
|
||||
} else
|
||||
goto signed_print;
|
||||
|
||||
fputc('\n', trace->output);
|
||||
|
|
@ -3159,10 +3188,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||
NULL
|
||||
};
|
||||
struct trace trace = {
|
||||
.audit = {
|
||||
.machine = audit_detect_machine(),
|
||||
.open_id = audit_name_to_syscall("open", trace.audit.machine),
|
||||
},
|
||||
.syscalls = {
|
||||
. max = -1,
|
||||
},
|
||||
|
|
@ -3237,8 +3262,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||
signal(SIGFPE, sighandler_dump_stack);
|
||||
|
||||
trace.evlist = perf_evlist__new();
|
||||
trace.sctbl = syscalltbl__new();
|
||||
|
||||
if (trace.evlist == NULL) {
|
||||
if (trace.evlist == NULL || trace.sctbl == NULL) {
|
||||
pr_err("Not enough memory to run!\n");
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
|
|
@ -3276,6 +3302,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||
}
|
||||
}
|
||||
|
||||
trace.open_id = syscalltbl__id(trace.sctbl, "open");
|
||||
|
||||
if (ev_qualifier_str != NULL) {
|
||||
const char *s = ev_qualifier_str;
|
||||
struct strlist_config slist_config = {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ NO_PERF_REGS := 1
|
|||
ifeq ($(ARCH),x86)
|
||||
$(call detected,CONFIG_X86)
|
||||
ifeq (${IS_64_BIT}, 1)
|
||||
CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
|
||||
CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT -DHAVE_SYSCALL_TABLE -I$(OUTPUT)arch/x86/include/generated
|
||||
ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
|
||||
LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
|
||||
$(call detected,CONFIG_X86_64)
|
||||
|
|
@ -268,6 +268,12 @@ else
|
|||
ifneq ($(feature-dwarf), 1)
|
||||
msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
|
||||
NO_DWARF := 1
|
||||
else
|
||||
ifneq ($(feature-dwarf_getlocations), 1)
|
||||
msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157);
|
||||
else
|
||||
CFLAGS += -DHAVE_DWARF_GETLOCATIONS
|
||||
endif # dwarf_getlocations
|
||||
endif # Dwarf support
|
||||
endif # libelf support
|
||||
endif # NO_LIBELF
|
||||
|
|
@ -289,9 +295,6 @@ ifndef NO_LIBELF
|
|||
CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
|
||||
endif
|
||||
|
||||
# include ARCH specific config
|
||||
-include $(src-perf)/arch/$(ARCH)/Makefile
|
||||
|
||||
ifndef NO_DWARF
|
||||
ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
|
||||
msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* From include/linux/stat.h */
|
||||
#ifndef S_IRWXUGO
|
||||
#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
#endif
|
||||
#ifndef S_IALLUGO
|
||||
#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
|
||||
#endif
|
||||
#ifndef S_IRUGO
|
||||
#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
|
||||
#endif
|
||||
#ifndef S_IWUGO
|
||||
#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH)
|
||||
#endif
|
||||
#ifndef S_IXUGO
|
||||
#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
|
||||
#endif
|
||||
|
||||
static size_t syscall_arg__scnprintf_mode_t(char *bf, size_t size, struct syscall_arg *arg)
|
||||
{
|
||||
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); \
|
||||
mode &= ~S_##n; \
|
||||
}
|
||||
|
||||
P_MODE(IALLUGO);
|
||||
P_MODE(IRWXUGO);
|
||||
P_MODE(IRUGO);
|
||||
P_MODE(IWUGO);
|
||||
P_MODE(IXUGO);
|
||||
P_MODE(IFMT);
|
||||
P_MODE(IFSOCK);
|
||||
P_MODE(IFLNK);
|
||||
P_MODE(IFREG);
|
||||
P_MODE(IFBLK);
|
||||
P_MODE(IFDIR);
|
||||
P_MODE(IFCHR);
|
||||
P_MODE(IFIFO);
|
||||
P_MODE(ISUID);
|
||||
P_MODE(ISGID);
|
||||
P_MODE(ISVTX);
|
||||
P_MODE(IRWXU);
|
||||
P_MODE(IRUSR);
|
||||
P_MODE(IWUSR);
|
||||
P_MODE(IXUSR);
|
||||
P_MODE(IRWXG);
|
||||
P_MODE(IRGRP);
|
||||
P_MODE(IWGRP);
|
||||
P_MODE(IXGRP);
|
||||
P_MODE(IRWXO);
|
||||
P_MODE(IROTH);
|
||||
P_MODE(IWOTH);
|
||||
P_MODE(IXOTH);
|
||||
#undef P_MODE
|
||||
|
||||
if (mode)
|
||||
printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", mode);
|
||||
|
||||
return printed;
|
||||
}
|
||||
|
||||
#define SCA_MODE_T syscall_arg__scnprintf_mode_t
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
|
||||
{
|
||||
int pid = arg->val;
|
||||
struct trace *trace = arg->trace;
|
||||
size_t printed = scnprintf(bf, size, "%d", pid);
|
||||
struct thread *thread = machine__find_thread(trace->host, pid, pid);
|
||||
|
||||
if (thread != NULL) {
|
||||
if (thread->comm_set)
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
" (%s)", thread__comm_str(thread));
|
||||
thread__put(thread);
|
||||
}
|
||||
|
||||
return printed;
|
||||
}
|
||||
|
||||
#define SCA_PID syscall_arg__scnprintf_pid
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#include <sched.h>
|
||||
|
||||
/*
|
||||
* Not defined anywhere else, probably, just to make sure we
|
||||
* catch future flags
|
||||
*/
|
||||
#define SCHED_POLICY_MASK 0xff
|
||||
|
||||
#ifndef SCHED_DEADLINE
|
||||
#define SCHED_DEADLINE 6
|
||||
#endif
|
||||
|
||||
static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size,
|
||||
struct syscall_arg *arg)
|
||||
{
|
||||
const char *policies[] = {
|
||||
"NORMAL", "FIFO", "RR", "BATCH", "ISO", "IDLE", "DEADLINE",
|
||||
};
|
||||
size_t printed;
|
||||
int policy = arg->val,
|
||||
flags = policy & ~SCHED_POLICY_MASK;
|
||||
|
||||
policy &= SCHED_POLICY_MASK;
|
||||
if (policy <= SCHED_DEADLINE)
|
||||
printed = scnprintf(bf, size, "%s", 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); \
|
||||
flags &= ~SCHED_##n; \
|
||||
}
|
||||
|
||||
P_POLICY_FLAG(RESET_ON_FORK);
|
||||
#undef P_POLICY_FLAG
|
||||
|
||||
if (flags)
|
||||
printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
|
||||
|
||||
return printed;
|
||||
}
|
||||
|
||||
#define SCA_SCHED_POLICY syscall_arg__scnprintf_sched_policy
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static size_t syscall_arg__scnprintf_waitid_options(char *bf, size_t size,
|
||||
struct syscall_arg *arg)
|
||||
{
|
||||
int printed = 0, options = arg->val;
|
||||
|
||||
#define P_OPTION(n) \
|
||||
if (options & W##n) { \
|
||||
printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
|
||||
options &= ~W##n; \
|
||||
}
|
||||
|
||||
P_OPTION(NOHANG);
|
||||
P_OPTION(UNTRACED);
|
||||
P_OPTION(CONTINUED);
|
||||
#undef P_OPTION
|
||||
|
||||
if (options)
|
||||
printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", options);
|
||||
|
||||
return printed;
|
||||
}
|
||||
|
||||
#define SCA_WAITID_OPTIONS syscall_arg__scnprintf_waitid_options
|
||||
|
|
@ -1607,9 +1607,8 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
|
|||
|
||||
ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
|
||||
dummy_hpp.buf[ret] = '\0';
|
||||
rtrim(dummy_hpp.buf);
|
||||
|
||||
start = ltrim(dummy_hpp.buf);
|
||||
start = trim(dummy_hpp.buf);
|
||||
ret = strlen(start);
|
||||
|
||||
if (start != dummy_hpp.buf)
|
||||
|
|
|
|||
|
|
@ -569,9 +569,8 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
|
|||
first_col = false;
|
||||
|
||||
fmt->header(fmt, hpp, hists_to_evsel(hists));
|
||||
rtrim(hpp->buf);
|
||||
|
||||
header_width += fprintf(fp, "%s", ltrim(hpp->buf));
|
||||
header_width += fprintf(fp, "%s", trim(hpp->buf));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ libperf-y += machine.o
|
|||
libperf-y += map.o
|
||||
libperf-y += pstack.o
|
||||
libperf-y += session.o
|
||||
libperf-$(CONFIG_AUDIT) += syscalltbl.o
|
||||
libperf-y += ordered-events.o
|
||||
libperf-y += comm.o
|
||||
libperf-y += thread.o
|
||||
|
|
@ -147,6 +148,10 @@ CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ET
|
|||
CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
|
||||
CFLAGS_parse-events.o += -Wno-redundant-decls
|
||||
|
||||
$(OUTPUT)util/syscalltbl.o: util/syscalltbl.c arch/x86/entry/syscalls/syscall_64.tbl $(OUTPUT)arch/x86/include/generated/asm/syscalls_64.c FORCE
|
||||
$(call rule_mkdir)
|
||||
$(call if_changed_dep,cc_o_c)
|
||||
|
||||
$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE
|
||||
$(call rule_mkdir)
|
||||
$(call if_changed_dep,cc_o_c)
|
||||
|
|
|
|||
|
|
@ -381,11 +381,11 @@ static int perf_buildid_config(const char *var, const char *value)
|
|||
{
|
||||
/* same dir for all commands */
|
||||
if (!strcmp(var, "buildid.dir")) {
|
||||
const char *dirname = perf_config_dirname(var, value);
|
||||
const char *dir = perf_config_dirname(var, value);
|
||||
|
||||
if (!dirname)
|
||||
if (!dir)
|
||||
return -1;
|
||||
strncpy(buildid_dir, dirname, MAXPATHLEN-1);
|
||||
strncpy(buildid_dir, dir, MAXPATHLEN-1);
|
||||
buildid_dir[MAXPATHLEN-1] = '\0';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -959,6 +959,7 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DWARF_GETLOCATIONS
|
||||
/**
|
||||
* die_get_var_innermost_scope - Get innermost scope range of given variable DIE
|
||||
* @sp_die: a subprogram DIE
|
||||
|
|
@ -1080,3 +1081,11 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
|
|||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
|
||||
Dwarf_Die *vr_die __maybe_unused,
|
||||
struct strbuf *buf __maybe_unused)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -431,6 +431,13 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
|
|||
if (map->dso->rel)
|
||||
return rip - map->pgoff;
|
||||
|
||||
/*
|
||||
* kernel modules also have DSO_TYPE_USER in dso->kernel,
|
||||
* but all kernel modules are ET_REL, so won't get here.
|
||||
*/
|
||||
if (map->dso->kernel == DSO_TYPE_USER)
|
||||
return rip + map->dso->text_offset;
|
||||
|
||||
return map->unmap_ip(map, rip) - map->reloc;
|
||||
}
|
||||
|
||||
|
|
@ -454,6 +461,13 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
|
|||
if (map->dso->rel)
|
||||
return map->unmap_ip(map, ip + map->pgoff);
|
||||
|
||||
/*
|
||||
* kernel modules also have DSO_TYPE_USER in dso->kernel,
|
||||
* but all kernel modules are ET_REL, so won't get here.
|
||||
*/
|
||||
if (map->dso->kernel == DSO_TYPE_USER)
|
||||
return map->unmap_ip(map, ip - map->dso->text_offset);
|
||||
|
||||
return ip + map->reloc;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -283,18 +283,27 @@ static SV *perl_process_callchain(struct perf_sample *sample,
|
|||
if (!elem)
|
||||
goto exit;
|
||||
|
||||
hv_stores(elem, "ip", newSVuv(node->ip));
|
||||
if (!hv_stores(elem, "ip", newSVuv(node->ip))) {
|
||||
hv_undef(elem);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (node->sym) {
|
||||
HV *sym = newHV();
|
||||
if (!sym)
|
||||
if (!sym) {
|
||||
hv_undef(elem);
|
||||
goto exit;
|
||||
hv_stores(sym, "start", newSVuv(node->sym->start));
|
||||
hv_stores(sym, "end", newSVuv(node->sym->end));
|
||||
hv_stores(sym, "binding", newSVuv(node->sym->binding));
|
||||
hv_stores(sym, "name", newSVpvn(node->sym->name,
|
||||
node->sym->namelen));
|
||||
hv_stores(elem, "sym", newRV_noinc((SV*)sym));
|
||||
}
|
||||
if (!hv_stores(sym, "start", newSVuv(node->sym->start)) ||
|
||||
!hv_stores(sym, "end", newSVuv(node->sym->end)) ||
|
||||
!hv_stores(sym, "binding", newSVuv(node->sym->binding)) ||
|
||||
!hv_stores(sym, "name", newSVpvn(node->sym->name,
|
||||
node->sym->namelen)) ||
|
||||
!hv_stores(elem, "sym", newRV_noinc((SV*)sym))) {
|
||||
hv_undef(sym);
|
||||
hv_undef(elem);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (node->map) {
|
||||
|
|
@ -306,7 +315,10 @@ static SV *perl_process_callchain(struct perf_sample *sample,
|
|||
else if (map->dso->name)
|
||||
dsoname = map->dso->name;
|
||||
}
|
||||
hv_stores(elem, "dso", newSVpv(dsoname,0));
|
||||
if (!hv_stores(elem, "dso", newSVpv(dsoname,0))) {
|
||||
hv_undef(elem);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
callchain_cursor_advance(&callchain_cursor);
|
||||
|
|
|
|||
|
|
@ -709,17 +709,10 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
|
|||
if (ss->opdshdr.sh_type != SHT_PROGBITS)
|
||||
ss->opdsec = NULL;
|
||||
|
||||
if (dso->kernel == DSO_TYPE_USER) {
|
||||
GElf_Shdr shdr;
|
||||
ss->adjust_symbols = (ehdr.e_type == ET_EXEC ||
|
||||
ehdr.e_type == ET_REL ||
|
||||
dso__is_vdso(dso) ||
|
||||
elf_section_by_name(elf, &ehdr, &shdr,
|
||||
".gnu.prelink_undo",
|
||||
NULL) != NULL);
|
||||
} else {
|
||||
if (dso->kernel == DSO_TYPE_USER)
|
||||
ss->adjust_symbols = true;
|
||||
else
|
||||
ss->adjust_symbols = elf__needs_adjust_symbols(ehdr);
|
||||
}
|
||||
|
||||
ss->name = strdup(name);
|
||||
if (!ss->name) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* System call table mapper
|
||||
*
|
||||
* (C) 2016 Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include "syscalltbl.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_SYSCALL_TABLE
|
||||
#include <linux/compiler.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#include <asm/syscalls_64.c>
|
||||
const int syscalltbl_native_max_id = SYSCALLTBL_x86_64_MAX_ID;
|
||||
static const char **syscalltbl_native = syscalltbl_x86_64;
|
||||
#endif
|
||||
|
||||
struct syscall {
|
||||
int id;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static int syscallcmpname(const void *vkey, const void *ventry)
|
||||
{
|
||||
const char *key = vkey;
|
||||
const struct syscall *entry = ventry;
|
||||
|
||||
return strcmp(key, entry->name);
|
||||
}
|
||||
|
||||
static int syscallcmp(const void *va, const void *vb)
|
||||
{
|
||||
const struct syscall *a = va, *b = vb;
|
||||
|
||||
return strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
static int syscalltbl__init_native(struct syscalltbl *tbl)
|
||||
{
|
||||
int nr_entries = 0, i, j;
|
||||
struct syscall *entries;
|
||||
|
||||
for (i = 0; i <= syscalltbl_native_max_id; ++i)
|
||||
if (syscalltbl_native[i])
|
||||
++nr_entries;
|
||||
|
||||
entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries);
|
||||
if (tbl->syscalls.entries == NULL)
|
||||
return -1;
|
||||
|
||||
for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) {
|
||||
if (syscalltbl_native[i]) {
|
||||
entries[j].name = syscalltbl_native[i];
|
||||
entries[j].id = i;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp);
|
||||
tbl->syscalls.nr_entries = nr_entries;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct syscalltbl *syscalltbl__new(void)
|
||||
{
|
||||
struct syscalltbl *tbl = malloc(sizeof(*tbl));
|
||||
if (tbl) {
|
||||
if (syscalltbl__init_native(tbl)) {
|
||||
free(tbl);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return tbl;
|
||||
}
|
||||
|
||||
void syscalltbl__delete(struct syscalltbl *tbl)
|
||||
{
|
||||
zfree(&tbl->syscalls.entries);
|
||||
free(tbl);
|
||||
}
|
||||
|
||||
const char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id)
|
||||
{
|
||||
return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL;
|
||||
}
|
||||
|
||||
int syscalltbl__id(struct syscalltbl *tbl, const char *name)
|
||||
{
|
||||
struct syscall *sc = bsearch(name, tbl->syscalls.entries,
|
||||
tbl->syscalls.nr_entries, sizeof(*sc),
|
||||
syscallcmpname);
|
||||
|
||||
return sc ? sc->id : -1;
|
||||
}
|
||||
|
||||
#else /* HAVE_SYSCALL_TABLE */
|
||||
|
||||
#include <libaudit.h>
|
||||
|
||||
struct syscalltbl *syscalltbl__new(void)
|
||||
{
|
||||
struct syscalltbl *tbl = malloc(sizeof(*tbl));
|
||||
if (tbl)
|
||||
tbl->audit_machine = audit_detect_machine();
|
||||
return tbl;
|
||||
}
|
||||
|
||||
void syscalltbl__delete(struct syscalltbl *tbl)
|
||||
{
|
||||
free(tbl);
|
||||
}
|
||||
|
||||
const char *syscalltbl__name(const struct syscalltbl *tbl, int id)
|
||||
{
|
||||
return audit_syscall_to_name(id, tbl->audit_machine);
|
||||
}
|
||||
|
||||
int syscalltbl__id(struct syscalltbl *tbl, const char *name)
|
||||
{
|
||||
return audit_name_to_syscall(name, tbl->audit_machine);
|
||||
}
|
||||
#endif /* HAVE_SYSCALL_TABLE */
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef __PERF_SYSCALLTBL_H
|
||||
#define __PERF_SYSCALLTBL_H
|
||||
|
||||
struct syscalltbl {
|
||||
union {
|
||||
int audit_machine;
|
||||
struct {
|
||||
int nr_entries;
|
||||
void *entries;
|
||||
} syscalls;
|
||||
};
|
||||
};
|
||||
|
||||
struct syscalltbl *syscalltbl__new(void);
|
||||
void syscalltbl__delete(struct syscalltbl *tbl);
|
||||
|
||||
const char *syscalltbl__name(const struct syscalltbl *tbl, int id);
|
||||
int syscalltbl__id(struct syscalltbl *tbl, const char *name);
|
||||
|
||||
#endif /* __PERF_SYSCALLTBL_H */
|
||||
|
|
@ -9,6 +9,9 @@
|
|||
#include "symbol.h"
|
||||
#include <strlist.h>
|
||||
#include <intlist.h>
|
||||
#ifdef HAVE_LIBUNWIND_SUPPORT
|
||||
#include <libunwind.h>
|
||||
#endif
|
||||
|
||||
struct thread_stack;
|
||||
|
||||
|
|
@ -32,6 +35,9 @@ struct thread {
|
|||
|
||||
void *priv;
|
||||
struct thread_stack *ts;
|
||||
#ifdef HAVE_LIBUNWIND_SUPPORT
|
||||
unw_addr_space_t addr_space;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct machine;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "symbol.h"
|
||||
#include "util.h"
|
||||
#include "debug.h"
|
||||
#include "asm/bug.h"
|
||||
|
||||
extern int
|
||||
UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
|
||||
|
|
@ -580,43 +581,33 @@ static unw_accessors_t accessors = {
|
|||
|
||||
int unwind__prepare_access(struct thread *thread)
|
||||
{
|
||||
unw_addr_space_t addr_space;
|
||||
|
||||
if (callchain_param.record_mode != CALLCHAIN_DWARF)
|
||||
return 0;
|
||||
|
||||
addr_space = unw_create_addr_space(&accessors, 0);
|
||||
if (!addr_space) {
|
||||
thread->addr_space = unw_create_addr_space(&accessors, 0);
|
||||
if (!thread->addr_space) {
|
||||
pr_err("unwind: Can't create unwind address space.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL);
|
||||
thread__set_priv(thread, addr_space);
|
||||
|
||||
unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void unwind__flush_access(struct thread *thread)
|
||||
{
|
||||
unw_addr_space_t addr_space;
|
||||
|
||||
if (callchain_param.record_mode != CALLCHAIN_DWARF)
|
||||
return;
|
||||
|
||||
addr_space = thread__priv(thread);
|
||||
unw_flush_cache(addr_space, 0, 0);
|
||||
unw_flush_cache(thread->addr_space, 0, 0);
|
||||
}
|
||||
|
||||
void unwind__finish_access(struct thread *thread)
|
||||
{
|
||||
unw_addr_space_t addr_space;
|
||||
|
||||
if (callchain_param.record_mode != CALLCHAIN_DWARF)
|
||||
return;
|
||||
|
||||
addr_space = thread__priv(thread);
|
||||
unw_destroy_addr_space(addr_space);
|
||||
unw_destroy_addr_space(thread->addr_space);
|
||||
}
|
||||
|
||||
static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
|
||||
|
|
@ -639,7 +630,9 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
|
|||
* unwind itself.
|
||||
*/
|
||||
if (max_stack - 1 > 0) {
|
||||
addr_space = thread__priv(ui->thread);
|
||||
WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL");
|
||||
addr_space = ui->thread->addr_space;
|
||||
|
||||
if (addr_space == NULL)
|
||||
return -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -254,6 +254,11 @@ int hex2u64(const char *ptr, u64 *val);
|
|||
char *ltrim(char *s);
|
||||
char *rtrim(char *s);
|
||||
|
||||
static inline char *trim(char *s)
|
||||
{
|
||||
return ltrim(rtrim(s));
|
||||
}
|
||||
|
||||
void dump_stack(void);
|
||||
void sighandler_dump_stack(int sig);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue