Commit 0a84f007f97ce6fc7c07a481a5b9808b187a0193

Authored by David Daney
Committed by Arnaldo Carvalho de Melo
1 parent d0caf29250

perf tools: Fix broken build by defining _GNU_SOURCE in Makefile

When building on my Debian/mips system, util/util.c fails to build
because commit 1aed2671738785e8f5aea663a6fda91aa7ef59b5 (perf kvm: Do
guest-only counting by default) indirectly includes stdio.h before the
feature selection in util.h is done.  This prevents _GNU_SOURCE in
util.h from enabling the declaration of getline(), from now second
inclusion of stdio.h, and the build is broken.

There is another breakage in util/evsel.c caused by include ordering,
but I didn't fully track down the commit that caused it.

The root cause of all this is an inconsistent definition of _GNU_SOURCE,
so I move the definition into the Makefile so that it is passed to all
invocations of the compiler and used uniformly for all system header
files.  All other #define and #undef of _GNU_SOURCE are removed as they
cause conflicts with the definition passed to the compiler.

All the features.h definitions (_LARGEFILE64_SOURCE _FILE_OFFSET_BITS=64
and _GNU_SOURCE) are needed by the python glue code too, so they are
moved to BASIC_CFLAGS, and the misleading comments about BASIC_CFLAGS
are removed.

This gives me a clean build on x86_64 (fc12) and mips (Debian).

Cc: David Daney <david.daney@cavium.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Joerg Roedel <joerg.roedel@amd.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1326836461-11952-1-git-send-email-ddaney.cavm@gmail.com
Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

Showing 8 changed files with 3 additions and 16 deletions Inline Diff

1 ifeq ("$(origin O)", "command line") 1 ifeq ("$(origin O)", "command line")
2 OUTPUT := $(O)/ 2 OUTPUT := $(O)/
3 endif 3 endif
4 4
5 # The default target of this Makefile is... 5 # The default target of this Makefile is...
6 all: 6 all:
7 7
8 include config/utilities.mak 8 include config/utilities.mak
9 9
10 ifneq ($(OUTPUT),) 10 ifneq ($(OUTPUT),)
11 # check that the output directory actually exists 11 # check that the output directory actually exists
12 OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd) 12 OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd)
13 $(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) 13 $(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
14 endif 14 endif
15 15
16 # Define V to have a more verbose compile. 16 # Define V to have a more verbose compile.
17 # 17 #
18 # Define PYTHON to point to the python binary if the default 18 # Define PYTHON to point to the python binary if the default
19 # `python' is not correct; for example: PYTHON=python2 19 # `python' is not correct; for example: PYTHON=python2
20 # 20 #
21 # Define PYTHON_CONFIG to point to the python-config binary if 21 # Define PYTHON_CONFIG to point to the python-config binary if
22 # the default `$(PYTHON)-config' is not correct. 22 # the default `$(PYTHON)-config' is not correct.
23 # 23 #
24 # Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8 24 # Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
25 # 25 #
26 # Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72. 26 # Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
27 # 27 #
28 # Define LDFLAGS=-static to build a static binary. 28 # Define LDFLAGS=-static to build a static binary.
29 # 29 #
30 # Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds. 30 # Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
31 # 31 #
32 # Define NO_DWARF if you do not want debug-info analysis feature at all. 32 # Define NO_DWARF if you do not want debug-info analysis feature at all.
33 # 33 #
34 # Define WERROR=0 to disable treating any warnings as errors. 34 # Define WERROR=0 to disable treating any warnings as errors.
35 35
36 $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE 36 $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
37 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) 37 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
38 -include $(OUTPUT)PERF-VERSION-FILE 38 -include $(OUTPUT)PERF-VERSION-FILE
39 39
40 uname_M := $(shell uname -m 2>/dev/null || echo not) 40 uname_M := $(shell uname -m 2>/dev/null || echo not)
41 41
42 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ 42 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
43 -e s/arm.*/arm/ -e s/sa110/arm/ \ 43 -e s/arm.*/arm/ -e s/sa110/arm/ \
44 -e s/s390x/s390/ -e s/parisc64/parisc/ \ 44 -e s/s390x/s390/ -e s/parisc64/parisc/ \
45 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ 45 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
46 -e s/sh[234].*/sh/ ) 46 -e s/sh[234].*/sh/ )
47 47
48 CC = $(CROSS_COMPILE)gcc 48 CC = $(CROSS_COMPILE)gcc
49 AR = $(CROSS_COMPILE)ar 49 AR = $(CROSS_COMPILE)ar
50 50
51 # Additional ARCH settings for x86 51 # Additional ARCH settings for x86
52 ifeq ($(ARCH),i386) 52 ifeq ($(ARCH),i386)
53 ARCH := x86 53 ARCH := x86
54 endif 54 endif
55 ifeq ($(ARCH),x86_64) 55 ifeq ($(ARCH),x86_64)
56 ARCH := x86 56 ARCH := x86
57 IS_X86_64 := 0 57 IS_X86_64 := 0
58 ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) 58 ifeq (, $(findstring m32,$(EXTRA_CFLAGS)))
59 IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) 59 IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1)
60 endif 60 endif
61 ifeq (${IS_X86_64}, 1) 61 ifeq (${IS_X86_64}, 1)
62 RAW_ARCH := x86_64 62 RAW_ARCH := x86_64
63 ARCH_CFLAGS := -DARCH_X86_64 63 ARCH_CFLAGS := -DARCH_X86_64
64 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S 64 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S
65 endif 65 endif
66 endif 66 endif
67 67
68 # Treat warnings as errors unless directed not to 68 # Treat warnings as errors unless directed not to
69 ifneq ($(WERROR),0) 69 ifneq ($(WERROR),0)
70 CFLAGS_WERROR := -Werror 70 CFLAGS_WERROR := -Werror
71 endif 71 endif
72 72
73 # 73 #
74 # Include saner warnings here, which can catch bugs: 74 # Include saner warnings here, which can catch bugs:
75 # 75 #
76 76
77 EXTRA_WARNINGS := -Wformat 77 EXTRA_WARNINGS := -Wformat
78 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-security 78 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-security
79 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-y2k 79 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-y2k
80 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wshadow 80 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wshadow
81 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Winit-self 81 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Winit-self
82 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wpacked 82 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wpacked
83 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wredundant-decls 83 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wredundant-decls
84 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-aliasing=3 84 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-aliasing=3
85 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-default 85 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-default
86 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-enum 86 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-enum
87 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wno-system-headers 87 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wno-system-headers
88 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wundef 88 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wundef
89 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wwrite-strings 89 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wwrite-strings
90 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wbad-function-cast 90 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wbad-function-cast
91 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-declarations 91 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-declarations
92 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-prototypes 92 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-prototypes
93 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wnested-externs 93 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wnested-externs
94 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wold-style-definition 94 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wold-style-definition
95 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes 95 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes
96 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement 96 EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement
97 97
98 ifeq ("$(origin DEBUG)", "command line") 98 ifeq ("$(origin DEBUG)", "command line")
99 PERF_DEBUG = $(DEBUG) 99 PERF_DEBUG = $(DEBUG)
100 endif 100 endif
101 ifndef PERF_DEBUG 101 ifndef PERF_DEBUG
102 CFLAGS_OPTIMIZE = -O6 102 CFLAGS_OPTIMIZE = -O6
103 endif 103 endif
104 104
105 CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 105 CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
106 EXTLIBS = -lpthread -lrt -lelf -lm 106 EXTLIBS = -lpthread -lrt -lelf -lm
107 ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 107 ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
108 ALL_LDFLAGS = $(LDFLAGS) 108 ALL_LDFLAGS = $(LDFLAGS)
109 STRIP ?= strip 109 STRIP ?= strip
110 110
111 # Among the variables below, these: 111 # Among the variables below, these:
112 # perfexecdir 112 # perfexecdir
113 # template_dir 113 # template_dir
114 # mandir 114 # mandir
115 # infodir 115 # infodir
116 # htmldir 116 # htmldir
117 # ETC_PERFCONFIG (but not sysconfdir) 117 # ETC_PERFCONFIG (but not sysconfdir)
118 # can be specified as a relative path some/where/else; 118 # can be specified as a relative path some/where/else;
119 # this is interpreted as relative to $(prefix) and "perf" at 119 # this is interpreted as relative to $(prefix) and "perf" at
120 # runtime figures out where they are based on the path to the executable. 120 # runtime figures out where they are based on the path to the executable.
121 # This can help installing the suite in a relocatable way. 121 # This can help installing the suite in a relocatable way.
122 122
123 # Make the path relative to DESTDIR, not to prefix 123 # Make the path relative to DESTDIR, not to prefix
124 ifndef DESTDIR 124 ifndef DESTDIR
125 prefix = $(HOME) 125 prefix = $(HOME)
126 endif 126 endif
127 bindir_relative = bin 127 bindir_relative = bin
128 bindir = $(prefix)/$(bindir_relative) 128 bindir = $(prefix)/$(bindir_relative)
129 mandir = share/man 129 mandir = share/man
130 infodir = share/info 130 infodir = share/info
131 perfexecdir = libexec/perf-core 131 perfexecdir = libexec/perf-core
132 sharedir = $(prefix)/share 132 sharedir = $(prefix)/share
133 template_dir = share/perf-core/templates 133 template_dir = share/perf-core/templates
134 htmldir = share/doc/perf-doc 134 htmldir = share/doc/perf-doc
135 ifeq ($(prefix),/usr) 135 ifeq ($(prefix),/usr)
136 sysconfdir = /etc 136 sysconfdir = /etc
137 ETC_PERFCONFIG = $(sysconfdir)/perfconfig 137 ETC_PERFCONFIG = $(sysconfdir)/perfconfig
138 else 138 else
139 sysconfdir = $(prefix)/etc 139 sysconfdir = $(prefix)/etc
140 ETC_PERFCONFIG = etc/perfconfig 140 ETC_PERFCONFIG = etc/perfconfig
141 endif 141 endif
142 lib = lib 142 lib = lib
143 143
144 export prefix bindir sharedir sysconfdir 144 export prefix bindir sharedir sysconfdir
145 145
146 RM = rm -f 146 RM = rm -f
147 MKDIR = mkdir 147 MKDIR = mkdir
148 FIND = find 148 FIND = find
149 INSTALL = install 149 INSTALL = install
150 150
151 # sparse is architecture-neutral, which means that we need to tell it 151 # sparse is architecture-neutral, which means that we need to tell it
152 # explicitly what architecture to check for. Fix this up for yours.. 152 # explicitly what architecture to check for. Fix this up for yours..
153 SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ 153 SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
154 154
155 -include config/feature-tests.mak 155 -include config/feature-tests.mak
156 156
157 ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y) 157 ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
158 CFLAGS := $(CFLAGS) -fstack-protector-all 158 CFLAGS := $(CFLAGS) -fstack-protector-all
159 endif 159 endif
160 160
161 ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wstack-protector),y) 161 ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wstack-protector),y)
162 CFLAGS := $(CFLAGS) -Wstack-protector 162 CFLAGS := $(CFLAGS) -Wstack-protector
163 endif 163 endif
164 164
165 ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wvolatile-register-var),y) 165 ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wvolatile-register-var),y)
166 CFLAGS := $(CFLAGS) -Wvolatile-register-var 166 CFLAGS := $(CFLAGS) -Wvolatile-register-var
167 endif 167 endif
168 168
169 ### --- END CONFIGURATION SECTION --- 169 ### --- END CONFIGURATION SECTION ---
170 170
171 # Those must not be GNU-specific; they are shared with perl/ which may 171 BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
172 # be built by a different compiler. (Note that this is an artifact now
173 # but it still might be nice to keep that distinction.)
174 BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include
175 BASIC_LDFLAGS = 172 BASIC_LDFLAGS =
176 173
177 # Guard against environment variables 174 # Guard against environment variables
178 BUILTIN_OBJS = 175 BUILTIN_OBJS =
179 LIB_H = 176 LIB_H =
180 LIB_OBJS = 177 LIB_OBJS =
181 PYRF_OBJS = 178 PYRF_OBJS =
182 SCRIPT_SH = 179 SCRIPT_SH =
183 180
184 SCRIPT_SH += perf-archive.sh 181 SCRIPT_SH += perf-archive.sh
185 182
186 grep-libs = $(filter -l%,$(1)) 183 grep-libs = $(filter -l%,$(1))
187 strip-libs = $(filter-out -l%,$(1)) 184 strip-libs = $(filter-out -l%,$(1))
188 185
189 $(OUTPUT)python/perf.so: $(PYRF_OBJS) 186 $(OUTPUT)python/perf.so: $(PYRF_OBJS)
190 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ 187 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
191 --quiet build_ext; \ 188 --quiet build_ext; \
192 mkdir -p $(OUTPUT)python && \ 189 mkdir -p $(OUTPUT)python && \
193 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ 190 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
194 # 191 #
195 # No Perl scripts right now: 192 # No Perl scripts right now:
196 # 193 #
197 194
198 SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) 195 SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
199 196
200 # 197 #
201 # Single 'perf' binary right now: 198 # Single 'perf' binary right now:
202 # 199 #
203 PROGRAMS += $(OUTPUT)perf 200 PROGRAMS += $(OUTPUT)perf
204 201
205 LANG_BINDINGS = 202 LANG_BINDINGS =
206 203
207 # what 'all' will build and 'install' will install, in perfexecdir 204 # what 'all' will build and 'install' will install, in perfexecdir
208 ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) 205 ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
209 206
210 # what 'all' will build but not install in perfexecdir 207 # what 'all' will build but not install in perfexecdir
211 OTHER_PROGRAMS = $(OUTPUT)perf 208 OTHER_PROGRAMS = $(OUTPUT)perf
212 209
213 # Set paths to tools early so that they can be used for version tests. 210 # Set paths to tools early so that they can be used for version tests.
214 ifndef SHELL_PATH 211 ifndef SHELL_PATH
215 SHELL_PATH = /bin/sh 212 SHELL_PATH = /bin/sh
216 endif 213 endif
217 ifndef PERL_PATH 214 ifndef PERL_PATH
218 PERL_PATH = /usr/bin/perl 215 PERL_PATH = /usr/bin/perl
219 endif 216 endif
220 217
221 export PERL_PATH 218 export PERL_PATH
222 219
223 LIB_FILE=$(OUTPUT)libperf.a 220 LIB_FILE=$(OUTPUT)libperf.a
224 221
225 LIB_H += ../../include/linux/perf_event.h 222 LIB_H += ../../include/linux/perf_event.h
226 LIB_H += ../../include/linux/rbtree.h 223 LIB_H += ../../include/linux/rbtree.h
227 LIB_H += ../../include/linux/list.h 224 LIB_H += ../../include/linux/list.h
228 LIB_H += ../../include/linux/const.h 225 LIB_H += ../../include/linux/const.h
229 LIB_H += ../../include/linux/hash.h 226 LIB_H += ../../include/linux/hash.h
230 LIB_H += ../../include/linux/stringify.h 227 LIB_H += ../../include/linux/stringify.h
231 LIB_H += util/include/linux/bitmap.h 228 LIB_H += util/include/linux/bitmap.h
232 LIB_H += util/include/linux/bitops.h 229 LIB_H += util/include/linux/bitops.h
233 LIB_H += util/include/linux/compiler.h 230 LIB_H += util/include/linux/compiler.h
234 LIB_H += util/include/linux/const.h 231 LIB_H += util/include/linux/const.h
235 LIB_H += util/include/linux/ctype.h 232 LIB_H += util/include/linux/ctype.h
236 LIB_H += util/include/linux/kernel.h 233 LIB_H += util/include/linux/kernel.h
237 LIB_H += util/include/linux/list.h 234 LIB_H += util/include/linux/list.h
238 LIB_H += util/include/linux/module.h 235 LIB_H += util/include/linux/module.h
239 LIB_H += util/include/linux/poison.h 236 LIB_H += util/include/linux/poison.h
240 LIB_H += util/include/linux/prefetch.h 237 LIB_H += util/include/linux/prefetch.h
241 LIB_H += util/include/linux/rbtree.h 238 LIB_H += util/include/linux/rbtree.h
242 LIB_H += util/include/linux/string.h 239 LIB_H += util/include/linux/string.h
243 LIB_H += util/include/linux/types.h 240 LIB_H += util/include/linux/types.h
244 LIB_H += util/include/linux/linkage.h 241 LIB_H += util/include/linux/linkage.h
245 LIB_H += util/include/asm/asm-offsets.h 242 LIB_H += util/include/asm/asm-offsets.h
246 LIB_H += util/include/asm/bug.h 243 LIB_H += util/include/asm/bug.h
247 LIB_H += util/include/asm/byteorder.h 244 LIB_H += util/include/asm/byteorder.h
248 LIB_H += util/include/asm/hweight.h 245 LIB_H += util/include/asm/hweight.h
249 LIB_H += util/include/asm/swab.h 246 LIB_H += util/include/asm/swab.h
250 LIB_H += util/include/asm/system.h 247 LIB_H += util/include/asm/system.h
251 LIB_H += util/include/asm/uaccess.h 248 LIB_H += util/include/asm/uaccess.h
252 LIB_H += util/include/dwarf-regs.h 249 LIB_H += util/include/dwarf-regs.h
253 LIB_H += util/include/asm/dwarf2.h 250 LIB_H += util/include/asm/dwarf2.h
254 LIB_H += util/include/asm/cpufeature.h 251 LIB_H += util/include/asm/cpufeature.h
255 LIB_H += perf.h 252 LIB_H += perf.h
256 LIB_H += util/annotate.h 253 LIB_H += util/annotate.h
257 LIB_H += util/cache.h 254 LIB_H += util/cache.h
258 LIB_H += util/callchain.h 255 LIB_H += util/callchain.h
259 LIB_H += util/build-id.h 256 LIB_H += util/build-id.h
260 LIB_H += util/debug.h 257 LIB_H += util/debug.h
261 LIB_H += util/debugfs.h 258 LIB_H += util/debugfs.h
262 LIB_H += util/event.h 259 LIB_H += util/event.h
263 LIB_H += util/evsel.h 260 LIB_H += util/evsel.h
264 LIB_H += util/evlist.h 261 LIB_H += util/evlist.h
265 LIB_H += util/exec_cmd.h 262 LIB_H += util/exec_cmd.h
266 LIB_H += util/types.h 263 LIB_H += util/types.h
267 LIB_H += util/levenshtein.h 264 LIB_H += util/levenshtein.h
268 LIB_H += util/map.h 265 LIB_H += util/map.h
269 LIB_H += util/parse-options.h 266 LIB_H += util/parse-options.h
270 LIB_H += util/parse-events.h 267 LIB_H += util/parse-events.h
271 LIB_H += util/quote.h 268 LIB_H += util/quote.h
272 LIB_H += util/util.h 269 LIB_H += util/util.h
273 LIB_H += util/xyarray.h 270 LIB_H += util/xyarray.h
274 LIB_H += util/header.h 271 LIB_H += util/header.h
275 LIB_H += util/help.h 272 LIB_H += util/help.h
276 LIB_H += util/session.h 273 LIB_H += util/session.h
277 LIB_H += util/strbuf.h 274 LIB_H += util/strbuf.h
278 LIB_H += util/strlist.h 275 LIB_H += util/strlist.h
279 LIB_H += util/strfilter.h 276 LIB_H += util/strfilter.h
280 LIB_H += util/svghelper.h 277 LIB_H += util/svghelper.h
281 LIB_H += util/tool.h 278 LIB_H += util/tool.h
282 LIB_H += util/run-command.h 279 LIB_H += util/run-command.h
283 LIB_H += util/sigchain.h 280 LIB_H += util/sigchain.h
284 LIB_H += util/symbol.h 281 LIB_H += util/symbol.h
285 LIB_H += util/color.h 282 LIB_H += util/color.h
286 LIB_H += util/values.h 283 LIB_H += util/values.h
287 LIB_H += util/sort.h 284 LIB_H += util/sort.h
288 LIB_H += util/hist.h 285 LIB_H += util/hist.h
289 LIB_H += util/thread.h 286 LIB_H += util/thread.h
290 LIB_H += util/thread_map.h 287 LIB_H += util/thread_map.h
291 LIB_H += util/trace-event.h 288 LIB_H += util/trace-event.h
292 LIB_H += util/probe-finder.h 289 LIB_H += util/probe-finder.h
293 LIB_H += util/dwarf-aux.h 290 LIB_H += util/dwarf-aux.h
294 LIB_H += util/probe-event.h 291 LIB_H += util/probe-event.h
295 LIB_H += util/pstack.h 292 LIB_H += util/pstack.h
296 LIB_H += util/cpumap.h 293 LIB_H += util/cpumap.h
297 LIB_H += util/top.h 294 LIB_H += util/top.h
298 LIB_H += $(ARCH_INCLUDE) 295 LIB_H += $(ARCH_INCLUDE)
299 LIB_H += util/cgroup.h 296 LIB_H += util/cgroup.h
300 297
301 LIB_OBJS += $(OUTPUT)util/abspath.o 298 LIB_OBJS += $(OUTPUT)util/abspath.o
302 LIB_OBJS += $(OUTPUT)util/alias.o 299 LIB_OBJS += $(OUTPUT)util/alias.o
303 LIB_OBJS += $(OUTPUT)util/annotate.o 300 LIB_OBJS += $(OUTPUT)util/annotate.o
304 LIB_OBJS += $(OUTPUT)util/build-id.o 301 LIB_OBJS += $(OUTPUT)util/build-id.o
305 LIB_OBJS += $(OUTPUT)util/config.o 302 LIB_OBJS += $(OUTPUT)util/config.o
306 LIB_OBJS += $(OUTPUT)util/ctype.o 303 LIB_OBJS += $(OUTPUT)util/ctype.o
307 LIB_OBJS += $(OUTPUT)util/debugfs.o 304 LIB_OBJS += $(OUTPUT)util/debugfs.o
308 LIB_OBJS += $(OUTPUT)util/environment.o 305 LIB_OBJS += $(OUTPUT)util/environment.o
309 LIB_OBJS += $(OUTPUT)util/event.o 306 LIB_OBJS += $(OUTPUT)util/event.o
310 LIB_OBJS += $(OUTPUT)util/evlist.o 307 LIB_OBJS += $(OUTPUT)util/evlist.o
311 LIB_OBJS += $(OUTPUT)util/evsel.o 308 LIB_OBJS += $(OUTPUT)util/evsel.o
312 LIB_OBJS += $(OUTPUT)util/exec_cmd.o 309 LIB_OBJS += $(OUTPUT)util/exec_cmd.o
313 LIB_OBJS += $(OUTPUT)util/help.o 310 LIB_OBJS += $(OUTPUT)util/help.o
314 LIB_OBJS += $(OUTPUT)util/levenshtein.o 311 LIB_OBJS += $(OUTPUT)util/levenshtein.o
315 LIB_OBJS += $(OUTPUT)util/parse-options.o 312 LIB_OBJS += $(OUTPUT)util/parse-options.o
316 LIB_OBJS += $(OUTPUT)util/parse-events.o 313 LIB_OBJS += $(OUTPUT)util/parse-events.o
317 LIB_OBJS += $(OUTPUT)util/path.o 314 LIB_OBJS += $(OUTPUT)util/path.o
318 LIB_OBJS += $(OUTPUT)util/rbtree.o 315 LIB_OBJS += $(OUTPUT)util/rbtree.o
319 LIB_OBJS += $(OUTPUT)util/bitmap.o 316 LIB_OBJS += $(OUTPUT)util/bitmap.o
320 LIB_OBJS += $(OUTPUT)util/hweight.o 317 LIB_OBJS += $(OUTPUT)util/hweight.o
321 LIB_OBJS += $(OUTPUT)util/run-command.o 318 LIB_OBJS += $(OUTPUT)util/run-command.o
322 LIB_OBJS += $(OUTPUT)util/quote.o 319 LIB_OBJS += $(OUTPUT)util/quote.o
323 LIB_OBJS += $(OUTPUT)util/strbuf.o 320 LIB_OBJS += $(OUTPUT)util/strbuf.o
324 LIB_OBJS += $(OUTPUT)util/string.o 321 LIB_OBJS += $(OUTPUT)util/string.o
325 LIB_OBJS += $(OUTPUT)util/strlist.o 322 LIB_OBJS += $(OUTPUT)util/strlist.o
326 LIB_OBJS += $(OUTPUT)util/strfilter.o 323 LIB_OBJS += $(OUTPUT)util/strfilter.o
327 LIB_OBJS += $(OUTPUT)util/top.o 324 LIB_OBJS += $(OUTPUT)util/top.o
328 LIB_OBJS += $(OUTPUT)util/usage.o 325 LIB_OBJS += $(OUTPUT)util/usage.o
329 LIB_OBJS += $(OUTPUT)util/wrapper.o 326 LIB_OBJS += $(OUTPUT)util/wrapper.o
330 LIB_OBJS += $(OUTPUT)util/sigchain.o 327 LIB_OBJS += $(OUTPUT)util/sigchain.o
331 LIB_OBJS += $(OUTPUT)util/symbol.o 328 LIB_OBJS += $(OUTPUT)util/symbol.o
332 LIB_OBJS += $(OUTPUT)util/color.o 329 LIB_OBJS += $(OUTPUT)util/color.o
333 LIB_OBJS += $(OUTPUT)util/pager.o 330 LIB_OBJS += $(OUTPUT)util/pager.o
334 LIB_OBJS += $(OUTPUT)util/header.o 331 LIB_OBJS += $(OUTPUT)util/header.o
335 LIB_OBJS += $(OUTPUT)util/callchain.o 332 LIB_OBJS += $(OUTPUT)util/callchain.o
336 LIB_OBJS += $(OUTPUT)util/values.o 333 LIB_OBJS += $(OUTPUT)util/values.o
337 LIB_OBJS += $(OUTPUT)util/debug.o 334 LIB_OBJS += $(OUTPUT)util/debug.o
338 LIB_OBJS += $(OUTPUT)util/map.o 335 LIB_OBJS += $(OUTPUT)util/map.o
339 LIB_OBJS += $(OUTPUT)util/pstack.o 336 LIB_OBJS += $(OUTPUT)util/pstack.o
340 LIB_OBJS += $(OUTPUT)util/session.o 337 LIB_OBJS += $(OUTPUT)util/session.o
341 LIB_OBJS += $(OUTPUT)util/thread.o 338 LIB_OBJS += $(OUTPUT)util/thread.o
342 LIB_OBJS += $(OUTPUT)util/thread_map.o 339 LIB_OBJS += $(OUTPUT)util/thread_map.o
343 LIB_OBJS += $(OUTPUT)util/trace-event-parse.o 340 LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
344 LIB_OBJS += $(OUTPUT)util/trace-event-read.o 341 LIB_OBJS += $(OUTPUT)util/trace-event-read.o
345 LIB_OBJS += $(OUTPUT)util/trace-event-info.o 342 LIB_OBJS += $(OUTPUT)util/trace-event-info.o
346 LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o 343 LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
347 LIB_OBJS += $(OUTPUT)util/svghelper.o 344 LIB_OBJS += $(OUTPUT)util/svghelper.o
348 LIB_OBJS += $(OUTPUT)util/sort.o 345 LIB_OBJS += $(OUTPUT)util/sort.o
349 LIB_OBJS += $(OUTPUT)util/hist.o 346 LIB_OBJS += $(OUTPUT)util/hist.o
350 LIB_OBJS += $(OUTPUT)util/probe-event.o 347 LIB_OBJS += $(OUTPUT)util/probe-event.o
351 LIB_OBJS += $(OUTPUT)util/util.o 348 LIB_OBJS += $(OUTPUT)util/util.o
352 LIB_OBJS += $(OUTPUT)util/xyarray.o 349 LIB_OBJS += $(OUTPUT)util/xyarray.o
353 LIB_OBJS += $(OUTPUT)util/cpumap.o 350 LIB_OBJS += $(OUTPUT)util/cpumap.o
354 LIB_OBJS += $(OUTPUT)util/cgroup.o 351 LIB_OBJS += $(OUTPUT)util/cgroup.o
355 352
356 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 353 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
357 354
358 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o 355 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
359 356
360 # Benchmark modules 357 # Benchmark modules
361 BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o 358 BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
362 BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o 359 BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
363 ifeq ($(RAW_ARCH),x86_64) 360 ifeq ($(RAW_ARCH),x86_64)
364 BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o 361 BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
365 endif 362 endif
366 BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 363 BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
367 364
368 BUILTIN_OBJS += $(OUTPUT)builtin-diff.o 365 BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
369 BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o 366 BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
370 BUILTIN_OBJS += $(OUTPUT)builtin-help.o 367 BUILTIN_OBJS += $(OUTPUT)builtin-help.o
371 BUILTIN_OBJS += $(OUTPUT)builtin-sched.o 368 BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
372 BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o 369 BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
373 BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o 370 BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
374 BUILTIN_OBJS += $(OUTPUT)builtin-list.o 371 BUILTIN_OBJS += $(OUTPUT)builtin-list.o
375 BUILTIN_OBJS += $(OUTPUT)builtin-record.o 372 BUILTIN_OBJS += $(OUTPUT)builtin-record.o
376 BUILTIN_OBJS += $(OUTPUT)builtin-report.o 373 BUILTIN_OBJS += $(OUTPUT)builtin-report.o
377 BUILTIN_OBJS += $(OUTPUT)builtin-stat.o 374 BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
378 BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o 375 BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
379 BUILTIN_OBJS += $(OUTPUT)builtin-top.o 376 BUILTIN_OBJS += $(OUTPUT)builtin-top.o
380 BUILTIN_OBJS += $(OUTPUT)builtin-script.o 377 BUILTIN_OBJS += $(OUTPUT)builtin-script.o
381 BUILTIN_OBJS += $(OUTPUT)builtin-probe.o 378 BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
382 BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o 379 BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
383 BUILTIN_OBJS += $(OUTPUT)builtin-lock.o 380 BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
384 BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o 381 BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
385 BUILTIN_OBJS += $(OUTPUT)builtin-test.o 382 BUILTIN_OBJS += $(OUTPUT)builtin-test.o
386 BUILTIN_OBJS += $(OUTPUT)builtin-inject.o 383 BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
387 384
388 PERFLIBS = $(LIB_FILE) 385 PERFLIBS = $(LIB_FILE)
389 386
390 # Files needed for the python binding, perf.so 387 # Files needed for the python binding, perf.so
391 # pyrf is just an internal name needed for all those wrappers. 388 # pyrf is just an internal name needed for all those wrappers.
392 # This has to be in sync with what is in the 'sources' variable in 389 # This has to be in sync with what is in the 'sources' variable in
393 # tools/perf/util/setup.py 390 # tools/perf/util/setup.py
394 391
395 PYRF_OBJS += $(OUTPUT)util/cpumap.o 392 PYRF_OBJS += $(OUTPUT)util/cpumap.o
396 PYRF_OBJS += $(OUTPUT)util/ctype.o 393 PYRF_OBJS += $(OUTPUT)util/ctype.o
397 PYRF_OBJS += $(OUTPUT)util/evlist.o 394 PYRF_OBJS += $(OUTPUT)util/evlist.o
398 PYRF_OBJS += $(OUTPUT)util/evsel.o 395 PYRF_OBJS += $(OUTPUT)util/evsel.o
399 PYRF_OBJS += $(OUTPUT)util/python.o 396 PYRF_OBJS += $(OUTPUT)util/python.o
400 PYRF_OBJS += $(OUTPUT)util/thread_map.o 397 PYRF_OBJS += $(OUTPUT)util/thread_map.o
401 PYRF_OBJS += $(OUTPUT)util/util.o 398 PYRF_OBJS += $(OUTPUT)util/util.o
402 PYRF_OBJS += $(OUTPUT)util/xyarray.o 399 PYRF_OBJS += $(OUTPUT)util/xyarray.o
403 400
404 # 401 #
405 # Platform specific tweaks 402 # Platform specific tweaks
406 # 403 #
407 404
408 # We choose to avoid "if .. else if .. else .. endif endif" 405 # We choose to avoid "if .. else if .. else .. endif endif"
409 # because maintaining the nesting to match is a pain. If 406 # because maintaining the nesting to match is a pain. If
410 # we had "elif" things would have been much nicer... 407 # we had "elif" things would have been much nicer...
411 408
412 -include config.mak.autogen 409 -include config.mak.autogen
413 -include config.mak 410 -include config.mak
414 411
415 ifndef NO_DWARF 412 ifndef NO_DWARF
416 FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS) 413 FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
417 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y) 414 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
418 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); 415 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);
419 NO_DWARF := 1 416 NO_DWARF := 1
420 endif # Dwarf support 417 endif # Dwarf support
421 endif # NO_DWARF 418 endif # NO_DWARF
422 419
423 -include arch/$(ARCH)/Makefile 420 -include arch/$(ARCH)/Makefile
424 421
425 ifneq ($(OUTPUT),) 422 ifneq ($(OUTPUT),)
426 BASIC_CFLAGS += -I$(OUTPUT) 423 BASIC_CFLAGS += -I$(OUTPUT)
427 endif 424 endif
428 425
429 FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) 426 FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
430 ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y) 427 ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
431 FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS) 428 FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS)
432 ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y) 429 ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
433 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); 430 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
434 else 431 else
435 msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel); 432 msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel);
436 endif 433 endif
437 endif 434 endif
438 435
439 ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y) 436 ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
440 BASIC_CFLAGS += -DLIBELF_NO_MMAP 437 BASIC_CFLAGS += -DLIBELF_NO_MMAP
441 endif 438 endif
442 439
443 ifndef NO_DWARF 440 ifndef NO_DWARF
444 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 441 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
445 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 442 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
446 else 443 else
447 BASIC_CFLAGS += -DDWARF_SUPPORT 444 BASIC_CFLAGS += -DDWARF_SUPPORT
448 EXTLIBS += -lelf -ldw 445 EXTLIBS += -lelf -ldw
449 LIB_OBJS += $(OUTPUT)util/probe-finder.o 446 LIB_OBJS += $(OUTPUT)util/probe-finder.o
450 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o 447 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
451 endif # PERF_HAVE_DWARF_REGS 448 endif # PERF_HAVE_DWARF_REGS
452 endif # NO_DWARF 449 endif # NO_DWARF
453 450
454 ifdef NO_NEWT 451 ifdef NO_NEWT
455 BASIC_CFLAGS += -DNO_NEWT_SUPPORT 452 BASIC_CFLAGS += -DNO_NEWT_SUPPORT
456 else 453 else
457 FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt 454 FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt
458 ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT)),y) 455 ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT)),y)
459 msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); 456 msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev);
460 BASIC_CFLAGS += -DNO_NEWT_SUPPORT 457 BASIC_CFLAGS += -DNO_NEWT_SUPPORT
461 else 458 else
462 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h 459 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
463 BASIC_CFLAGS += -I/usr/include/slang 460 BASIC_CFLAGS += -I/usr/include/slang
464 EXTLIBS += -lnewt -lslang 461 EXTLIBS += -lnewt -lslang
465 LIB_OBJS += $(OUTPUT)util/ui/setup.o 462 LIB_OBJS += $(OUTPUT)util/ui/setup.o
466 LIB_OBJS += $(OUTPUT)util/ui/browser.o 463 LIB_OBJS += $(OUTPUT)util/ui/browser.o
467 LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o 464 LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o
468 LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o 465 LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o
469 LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o 466 LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o
470 LIB_OBJS += $(OUTPUT)util/ui/helpline.o 467 LIB_OBJS += $(OUTPUT)util/ui/helpline.o
471 LIB_OBJS += $(OUTPUT)util/ui/progress.o 468 LIB_OBJS += $(OUTPUT)util/ui/progress.o
472 LIB_OBJS += $(OUTPUT)util/ui/util.o 469 LIB_OBJS += $(OUTPUT)util/ui/util.o
473 LIB_H += util/ui/browser.h 470 LIB_H += util/ui/browser.h
474 LIB_H += util/ui/browsers/map.h 471 LIB_H += util/ui/browsers/map.h
475 LIB_H += util/ui/helpline.h 472 LIB_H += util/ui/helpline.h
476 LIB_H += util/ui/keysyms.h 473 LIB_H += util/ui/keysyms.h
477 LIB_H += util/ui/libslang.h 474 LIB_H += util/ui/libslang.h
478 LIB_H += util/ui/progress.h 475 LIB_H += util/ui/progress.h
479 LIB_H += util/ui/util.h 476 LIB_H += util/ui/util.h
480 LIB_H += util/ui/ui.h 477 LIB_H += util/ui/ui.h
481 endif 478 endif
482 endif 479 endif
483 480
484 ifdef NO_LIBPERL 481 ifdef NO_LIBPERL
485 BASIC_CFLAGS += -DNO_LIBPERL 482 BASIC_CFLAGS += -DNO_LIBPERL
486 else 483 else
487 PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null) 484 PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
488 PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS)) 485 PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
489 PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS)) 486 PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
490 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` 487 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
491 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) 488 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
492 489
493 ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED)),y) 490 ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED)),y)
494 BASIC_CFLAGS += -DNO_LIBPERL 491 BASIC_CFLAGS += -DNO_LIBPERL
495 else 492 else
496 ALL_LDFLAGS += $(PERL_EMBED_LDFLAGS) 493 ALL_LDFLAGS += $(PERL_EMBED_LDFLAGS)
497 EXTLIBS += $(PERL_EMBED_LIBADD) 494 EXTLIBS += $(PERL_EMBED_LIBADD)
498 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o 495 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
499 LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o 496 LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
500 endif 497 endif
501 endif 498 endif
502 499
503 disable-python = $(eval $(disable-python_code)) 500 disable-python = $(eval $(disable-python_code))
504 define disable-python_code 501 define disable-python_code
505 BASIC_CFLAGS += -DNO_LIBPYTHON 502 BASIC_CFLAGS += -DNO_LIBPYTHON
506 $(if $(1),$(warning No $(1) was found)) 503 $(if $(1),$(warning No $(1) was found))
507 $(warning Python support won't be built) 504 $(warning Python support won't be built)
508 endef 505 endef
509 506
510 override PYTHON := \ 507 override PYTHON := \
511 $(call get-executable-or-default,PYTHON,python) 508 $(call get-executable-or-default,PYTHON,python)
512 509
513 ifndef PYTHON 510 ifndef PYTHON
514 $(call disable-python,python interpreter) 511 $(call disable-python,python interpreter)
515 python-clean := 512 python-clean :=
516 else 513 else
517 514
518 PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 515 PYTHON_WORD := $(call shell-wordify,$(PYTHON))
519 516
520 # python extension build directories 517 # python extension build directories
521 PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ 518 PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
522 PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/ 519 PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
523 PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/ 520 PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
524 export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP 521 export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
525 522
526 python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 523 python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
527 524
528 ifdef NO_LIBPYTHON 525 ifdef NO_LIBPYTHON
529 $(call disable-python) 526 $(call disable-python)
530 else 527 else
531 528
532 override PYTHON_CONFIG := \ 529 override PYTHON_CONFIG := \
533 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON)-config) 530 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON)-config)
534 531
535 ifndef PYTHON_CONFIG 532 ifndef PYTHON_CONFIG
536 $(call disable-python,python-config tool) 533 $(call disable-python,python-config tool)
537 else 534 else
538 535
539 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) 536 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
540 537
541 PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null) 538 PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
542 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) 539 PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
543 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) 540 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
544 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 541 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
545 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 542 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
546 543
547 ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y) 544 ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y)
548 $(call disable-python,Python.h (for Python 2.x)) 545 $(call disable-python,Python.h (for Python 2.x))
549 else 546 else
550 547
551 ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED)),y) 548 ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED)),y)
552 $(warning Python 3 is not yet supported; please set) 549 $(warning Python 3 is not yet supported; please set)
553 $(warning PYTHON and/or PYTHON_CONFIG appropriately.) 550 $(warning PYTHON and/or PYTHON_CONFIG appropriately.)
554 $(warning If you also have Python 2 installed, then) 551 $(warning If you also have Python 2 installed, then)
555 $(warning try something like:) 552 $(warning try something like:)
556 $(warning $(and ,)) 553 $(warning $(and ,))
557 $(warning $(and ,) make PYTHON=python2) 554 $(warning $(and ,) make PYTHON=python2)
558 $(warning $(and ,)) 555 $(warning $(and ,))
559 $(warning Otherwise, disable Python support entirely:) 556 $(warning Otherwise, disable Python support entirely:)
560 $(warning $(and ,)) 557 $(warning $(and ,))
561 $(warning $(and ,) make NO_LIBPYTHON=1) 558 $(warning $(and ,) make NO_LIBPYTHON=1)
562 $(warning $(and ,)) 559 $(warning $(and ,))
563 $(error $(and ,)) 560 $(error $(and ,))
564 else 561 else
565 ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS) 562 ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
566 EXTLIBS += $(PYTHON_EMBED_LIBADD) 563 EXTLIBS += $(PYTHON_EMBED_LIBADD)
567 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o 564 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
568 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o 565 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
569 LANG_BINDINGS += $(OUTPUT)python/perf.so 566 LANG_BINDINGS += $(OUTPUT)python/perf.so
570 endif 567 endif
571 568
572 endif 569 endif
573 endif 570 endif
574 endif 571 endif
575 endif 572 endif
576 573
577 ifdef NO_DEMANGLE 574 ifdef NO_DEMANGLE
578 BASIC_CFLAGS += -DNO_DEMANGLE 575 BASIC_CFLAGS += -DNO_DEMANGLE
579 else 576 else
580 ifdef HAVE_CPLUS_DEMANGLE 577 ifdef HAVE_CPLUS_DEMANGLE
581 EXTLIBS += -liberty 578 EXTLIBS += -liberty
582 BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE 579 BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE
583 else 580 else
584 FLAGS_BFD=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd 581 FLAGS_BFD=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd
585 has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD)) 582 has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD))
586 ifeq ($(has_bfd),y) 583 ifeq ($(has_bfd),y)
587 EXTLIBS += -lbfd 584 EXTLIBS += -lbfd
588 else 585 else
589 FLAGS_BFD_IBERTY=$(FLAGS_BFD) -liberty 586 FLAGS_BFD_IBERTY=$(FLAGS_BFD) -liberty
590 has_bfd_iberty := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY)) 587 has_bfd_iberty := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY))
591 ifeq ($(has_bfd_iberty),y) 588 ifeq ($(has_bfd_iberty),y)
592 EXTLIBS += -lbfd -liberty 589 EXTLIBS += -lbfd -liberty
593 else 590 else
594 FLAGS_BFD_IBERTY_Z=$(FLAGS_BFD_IBERTY) -lz 591 FLAGS_BFD_IBERTY_Z=$(FLAGS_BFD_IBERTY) -lz
595 has_bfd_iberty_z := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY_Z)) 592 has_bfd_iberty_z := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY_Z))
596 ifeq ($(has_bfd_iberty_z),y) 593 ifeq ($(has_bfd_iberty_z),y)
597 EXTLIBS += -lbfd -liberty -lz 594 EXTLIBS += -lbfd -liberty -lz
598 else 595 else
599 FLAGS_CPLUS_DEMANGLE=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -liberty 596 FLAGS_CPLUS_DEMANGLE=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -liberty
600 has_cplus_demangle := $(call try-cc,$(SOURCE_CPLUS_DEMANGLE),$(FLAGS_CPLUS_DEMANGLE)) 597 has_cplus_demangle := $(call try-cc,$(SOURCE_CPLUS_DEMANGLE),$(FLAGS_CPLUS_DEMANGLE))
601 ifeq ($(has_cplus_demangle),y) 598 ifeq ($(has_cplus_demangle),y)
602 EXTLIBS += -liberty 599 EXTLIBS += -liberty
603 BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE 600 BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE
604 else 601 else
605 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling) 602 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling)
606 BASIC_CFLAGS += -DNO_DEMANGLE 603 BASIC_CFLAGS += -DNO_DEMANGLE
607 endif 604 endif
608 endif 605 endif
609 endif 606 endif
610 endif 607 endif
611 endif 608 endif
612 endif 609 endif
613 610
614 611
615 ifdef NO_STRLCPY 612 ifdef NO_STRLCPY
616 BASIC_CFLAGS += -DNO_STRLCPY 613 BASIC_CFLAGS += -DNO_STRLCPY
617 else 614 else
618 ifneq ($(call try-cc,$(SOURCE_STRLCPY),),y) 615 ifneq ($(call try-cc,$(SOURCE_STRLCPY),),y)
619 BASIC_CFLAGS += -DNO_STRLCPY 616 BASIC_CFLAGS += -DNO_STRLCPY
620 endif 617 endif
621 endif 618 endif
622 619
623 ifneq ($(findstring $(MAKEFLAGS),s),s) 620 ifneq ($(findstring $(MAKEFLAGS),s),s)
624 ifndef V 621 ifndef V
625 QUIET_CC = @echo ' ' CC $@; 622 QUIET_CC = @echo ' ' CC $@;
626 QUIET_AR = @echo ' ' AR $@; 623 QUIET_AR = @echo ' ' AR $@;
627 QUIET_LINK = @echo ' ' LINK $@; 624 QUIET_LINK = @echo ' ' LINK $@;
628 QUIET_MKDIR = @echo ' ' MKDIR $@; 625 QUIET_MKDIR = @echo ' ' MKDIR $@;
629 QUIET_GEN = @echo ' ' GEN $@; 626 QUIET_GEN = @echo ' ' GEN $@;
630 endif 627 endif
631 endif 628 endif
632 629
633 ifdef ASCIIDOC8 630 ifdef ASCIIDOC8
634 export ASCIIDOC8 631 export ASCIIDOC8
635 endif 632 endif
636 633
637 # Shell quote (do not use $(call) to accommodate ancient setups); 634 # Shell quote (do not use $(call) to accommodate ancient setups);
638 635
639 ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG)) 636 ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
640 637
641 DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) 638 DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
642 bindir_SQ = $(subst ','\'',$(bindir)) 639 bindir_SQ = $(subst ','\'',$(bindir))
643 bindir_relative_SQ = $(subst ','\'',$(bindir_relative)) 640 bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
644 mandir_SQ = $(subst ','\'',$(mandir)) 641 mandir_SQ = $(subst ','\'',$(mandir))
645 infodir_SQ = $(subst ','\'',$(infodir)) 642 infodir_SQ = $(subst ','\'',$(infodir))
646 perfexecdir_SQ = $(subst ','\'',$(perfexecdir)) 643 perfexecdir_SQ = $(subst ','\'',$(perfexecdir))
647 template_dir_SQ = $(subst ','\'',$(template_dir)) 644 template_dir_SQ = $(subst ','\'',$(template_dir))
648 htmldir_SQ = $(subst ','\'',$(htmldir)) 645 htmldir_SQ = $(subst ','\'',$(htmldir))
649 prefix_SQ = $(subst ','\'',$(prefix)) 646 prefix_SQ = $(subst ','\'',$(prefix))
650 647
651 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) 648 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
652 649
653 LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group 650 LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
654 651
655 ALL_CFLAGS += $(BASIC_CFLAGS) 652 ALL_CFLAGS += $(BASIC_CFLAGS)
656 ALL_CFLAGS += $(ARCH_CFLAGS) 653 ALL_CFLAGS += $(ARCH_CFLAGS)
657 ALL_LDFLAGS += $(BASIC_LDFLAGS) 654 ALL_LDFLAGS += $(BASIC_LDFLAGS)
658 655
659 export INSTALL SHELL_PATH 656 export INSTALL SHELL_PATH
660 657
661 658
662 ### Build rules 659 ### Build rules
663 660
664 SHELL = $(SHELL_PATH) 661 SHELL = $(SHELL_PATH)
665 662
666 all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) 663 all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
667 664
668 please_set_SHELL_PATH_to_a_more_modern_shell: 665 please_set_SHELL_PATH_to_a_more_modern_shell:
669 @$$(:) 666 @$$(:)
670 667
671 shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell 668 shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
672 669
673 strip: $(PROGRAMS) $(OUTPUT)perf 670 strip: $(PROGRAMS) $(OUTPUT)perf
674 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf 671 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
675 672
676 $(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS 673 $(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
677 $(QUIET_CC)$(CC) -DPERF_VERSION='"$(PERF_VERSION)"' \ 674 $(QUIET_CC)$(CC) -DPERF_VERSION='"$(PERF_VERSION)"' \
678 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ 675 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
679 $(ALL_CFLAGS) -c $(filter %.c,$^) -o $@ 676 $(ALL_CFLAGS) -c $(filter %.c,$^) -o $@
680 677
681 $(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS) 678 $(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
682 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(OUTPUT)perf.o \ 679 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(OUTPUT)perf.o \
683 $(BUILTIN_OBJS) $(LIBS) -o $@ 680 $(BUILTIN_OBJS) $(LIBS) -o $@
684 681
685 $(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS 682 $(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
686 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ 683 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
687 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ 684 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
688 '-DPERF_MAN_PATH="$(mandir_SQ)"' \ 685 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
689 '-DPERF_INFO_PATH="$(infodir_SQ)"' $< 686 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
690 687
691 $(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS 688 $(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
692 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ 689 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
693 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ 690 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
694 '-DPERF_MAN_PATH="$(mandir_SQ)"' \ 691 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
695 '-DPERF_INFO_PATH="$(infodir_SQ)"' $< 692 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
696 693
697 $(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt 694 $(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
698 695
699 $(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt) 696 $(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
700 $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@ 697 $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
701 698
702 $(SCRIPTS) : % : %.sh 699 $(SCRIPTS) : % : %.sh
703 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@' 700 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
704 701
705 # These can record PERF_VERSION 702 # These can record PERF_VERSION
706 $(OUTPUT)perf.o perf.spec \ 703 $(OUTPUT)perf.o perf.spec \
707 $(SCRIPTS) \ 704 $(SCRIPTS) \
708 : $(OUTPUT)PERF-VERSION-FILE 705 : $(OUTPUT)PERF-VERSION-FILE
709 706
710 $(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS 707 $(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
711 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 708 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
712 $(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS 709 $(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
713 $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< 710 $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $<
714 $(OUTPUT)%.o: %.S 711 $(OUTPUT)%.o: %.S
715 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 712 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
716 713
717 $(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS 714 $(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
718 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ 715 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
719 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \ 716 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
720 '-DBINDIR="$(bindir_relative_SQ)"' \ 717 '-DBINDIR="$(bindir_relative_SQ)"' \
721 '-DPREFIX="$(prefix_SQ)"' \ 718 '-DPREFIX="$(prefix_SQ)"' \
722 $< 719 $<
723 720
724 $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS 721 $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
725 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 722 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
726 723
727 $(OUTPUT)util/ui/browser.o: util/ui/browser.c $(OUTPUT)PERF-CFLAGS 724 $(OUTPUT)util/ui/browser.o: util/ui/browser.c $(OUTPUT)PERF-CFLAGS
728 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 725 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
729 726
730 $(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS 727 $(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
731 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 728 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
732 729
733 $(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS 730 $(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
734 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 731 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
735 732
736 $(OUTPUT)util/ui/browsers/map.o: util/ui/browsers/map.c $(OUTPUT)PERF-CFLAGS 733 $(OUTPUT)util/ui/browsers/map.o: util/ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
737 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 734 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
738 735
739 $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 736 $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
740 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 737 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
741 738
742 $(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS 739 $(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
743 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< 740 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
744 741
745 $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS 742 $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
746 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< 743 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
747 744
748 $(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS 745 $(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
749 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< 746 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
750 747
751 $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS 748 $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
752 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< 749 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
753 750
754 $(OUTPUT)perf-%: %.o $(PERFLIBS) 751 $(OUTPUT)perf-%: %.o $(PERFLIBS)
755 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) 752 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
756 753
757 $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) 754 $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
758 $(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) 755 $(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
759 756
760 # we compile into subdirectories. if the target directory is not the source directory, they might not exists. So 757 # we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
761 # we depend the various files onto their directories. 758 # we depend the various files onto their directories.
762 DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h 759 DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
763 $(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS))) 760 $(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
764 # In the second step, we make a rule to actually create these directories 761 # In the second step, we make a rule to actually create these directories
765 $(sort $(dir $(DIRECTORY_DEPS))): 762 $(sort $(dir $(DIRECTORY_DEPS))):
766 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null 763 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
767 764
768 $(LIB_FILE): $(LIB_OBJS) 765 $(LIB_FILE): $(LIB_OBJS)
769 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS) 766 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
770 767
771 help: 768 help:
772 @echo 'Perf make targets:' 769 @echo 'Perf make targets:'
773 @echo ' doc - make *all* documentation (see below)' 770 @echo ' doc - make *all* documentation (see below)'
774 @echo ' man - make manpage documentation (access with man <foo>)' 771 @echo ' man - make manpage documentation (access with man <foo>)'
775 @echo ' html - make html documentation' 772 @echo ' html - make html documentation'
776 @echo ' info - make GNU info documentation (access with info <foo>)' 773 @echo ' info - make GNU info documentation (access with info <foo>)'
777 @echo ' pdf - make pdf documentation' 774 @echo ' pdf - make pdf documentation'
778 @echo ' TAGS - use etags to make tag information for source browsing' 775 @echo ' TAGS - use etags to make tag information for source browsing'
779 @echo ' tags - use ctags to make tag information for source browsing' 776 @echo ' tags - use ctags to make tag information for source browsing'
780 @echo ' cscope - use cscope to make interactive browsing database' 777 @echo ' cscope - use cscope to make interactive browsing database'
781 @echo '' 778 @echo ''
782 @echo 'Perf install targets:' 779 @echo 'Perf install targets:'
783 @echo ' NOTE: documentation build requires asciidoc, xmlto packages to be installed' 780 @echo ' NOTE: documentation build requires asciidoc, xmlto packages to be installed'
784 @echo ' HINT: use "make prefix=<path> <install target>" to install to a particular' 781 @echo ' HINT: use "make prefix=<path> <install target>" to install to a particular'
785 @echo ' path like make prefix=/usr/local install install-doc' 782 @echo ' path like make prefix=/usr/local install install-doc'
786 @echo ' install - install compiled binaries' 783 @echo ' install - install compiled binaries'
787 @echo ' install-doc - install *all* documentation' 784 @echo ' install-doc - install *all* documentation'
788 @echo ' install-man - install manpage documentation' 785 @echo ' install-man - install manpage documentation'
789 @echo ' install-html - install html documentation' 786 @echo ' install-html - install html documentation'
790 @echo ' install-info - install GNU info documentation' 787 @echo ' install-info - install GNU info documentation'
791 @echo ' install-pdf - install pdf documentation' 788 @echo ' install-pdf - install pdf documentation'
792 @echo '' 789 @echo ''
793 @echo ' quick-install-doc - alias for quick-install-man' 790 @echo ' quick-install-doc - alias for quick-install-man'
794 @echo ' quick-install-man - install the documentation quickly' 791 @echo ' quick-install-man - install the documentation quickly'
795 @echo ' quick-install-html - install the html documentation quickly' 792 @echo ' quick-install-html - install the html documentation quickly'
796 @echo '' 793 @echo ''
797 @echo 'Perf maintainer targets:' 794 @echo 'Perf maintainer targets:'
798 @echo ' distclean - alias to clean' 795 @echo ' distclean - alias to clean'
799 @echo ' clean - clean all binary objects and build output' 796 @echo ' clean - clean all binary objects and build output'
800 797
801 doc: 798 doc:
802 $(MAKE) -C Documentation all 799 $(MAKE) -C Documentation all
803 800
804 man: 801 man:
805 $(MAKE) -C Documentation man 802 $(MAKE) -C Documentation man
806 803
807 html: 804 html:
808 $(MAKE) -C Documentation html 805 $(MAKE) -C Documentation html
809 806
810 info: 807 info:
811 $(MAKE) -C Documentation info 808 $(MAKE) -C Documentation info
812 809
813 pdf: 810 pdf:
814 $(MAKE) -C Documentation pdf 811 $(MAKE) -C Documentation pdf
815 812
816 TAGS: 813 TAGS:
817 $(RM) TAGS 814 $(RM) TAGS
818 $(FIND) . -name '*.[hcS]' -print | xargs etags -a 815 $(FIND) . -name '*.[hcS]' -print | xargs etags -a
819 816
820 tags: 817 tags:
821 $(RM) tags 818 $(RM) tags
822 $(FIND) . -name '*.[hcS]' -print | xargs ctags -a 819 $(FIND) . -name '*.[hcS]' -print | xargs ctags -a
823 820
824 cscope: 821 cscope:
825 $(RM) cscope* 822 $(RM) cscope*
826 $(FIND) . -name '*.[hcS]' -print | xargs cscope -b 823 $(FIND) . -name '*.[hcS]' -print | xargs cscope -b
827 824
828 ### Detect prefix changes 825 ### Detect prefix changes
829 TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\ 826 TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\
830 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ) 827 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
831 828
832 $(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS 829 $(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
833 @FLAGS='$(TRACK_CFLAGS)'; \ 830 @FLAGS='$(TRACK_CFLAGS)'; \
834 if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \ 831 if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
835 echo 1>&2 " * new build flags or prefix"; \ 832 echo 1>&2 " * new build flags or prefix"; \
836 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \ 833 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
837 fi 834 fi
838 835
839 ### Testing rules 836 ### Testing rules
840 837
841 # GNU make supports exporting all variables by "export" without parameters. 838 # GNU make supports exporting all variables by "export" without parameters.
842 # However, the environment gets quite big, and some programs have problems 839 # However, the environment gets quite big, and some programs have problems
843 # with that. 840 # with that.
844 841
845 check: $(OUTPUT)common-cmds.h 842 check: $(OUTPUT)common-cmds.h
846 if sparse; \ 843 if sparse; \
847 then \ 844 then \
848 for i in *.c */*.c; \ 845 for i in *.c */*.c; \
849 do \ 846 do \
850 sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; \ 847 sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
851 done; \ 848 done; \
852 else \ 849 else \
853 exit 1; \ 850 exit 1; \
854 fi 851 fi
855 852
856 ### Installation rules 853 ### Installation rules
857 854
858 ifneq ($(filter /%,$(firstword $(perfexecdir))),) 855 ifneq ($(filter /%,$(firstword $(perfexecdir))),)
859 perfexec_instdir = $(perfexecdir) 856 perfexec_instdir = $(perfexecdir)
860 else 857 else
861 perfexec_instdir = $(prefix)/$(perfexecdir) 858 perfexec_instdir = $(prefix)/$(perfexecdir)
862 endif 859 endif
863 perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) 860 perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
864 861
865 install: all 862 install: all
866 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' 863 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
867 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)' 864 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
868 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace' 865 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
869 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin' 866 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
870 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 867 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
871 $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace' 868 $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
872 $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl' 869 $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'
873 $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin' 870 $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
874 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace' 871 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
875 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' 872 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
876 $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace' 873 $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
877 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python' 874 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
878 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' 875 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
879 876
880 install-python_ext: 877 install-python_ext:
881 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' 878 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
882 879
883 install-doc: 880 install-doc:
884 $(MAKE) -C Documentation install 881 $(MAKE) -C Documentation install
885 882
886 install-man: 883 install-man:
887 $(MAKE) -C Documentation install-man 884 $(MAKE) -C Documentation install-man
888 885
889 install-html: 886 install-html:
890 $(MAKE) -C Documentation install-html 887 $(MAKE) -C Documentation install-html
891 888
892 install-info: 889 install-info:
893 $(MAKE) -C Documentation install-info 890 $(MAKE) -C Documentation install-info
894 891
895 install-pdf: 892 install-pdf:
896 $(MAKE) -C Documentation install-pdf 893 $(MAKE) -C Documentation install-pdf
897 894
898 quick-install-doc: 895 quick-install-doc:
899 $(MAKE) -C Documentation quick-install 896 $(MAKE) -C Documentation quick-install
900 897
901 quick-install-man: 898 quick-install-man:
902 $(MAKE) -C Documentation quick-install-man 899 $(MAKE) -C Documentation quick-install-man
903 900
904 quick-install-html: 901 quick-install-html:
905 $(MAKE) -C Documentation quick-install-html 902 $(MAKE) -C Documentation quick-install-html
906 903
907 ### Cleaning rules 904 ### Cleaning rules
908 905
909 clean: 906 clean:
910 $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) 907 $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS)
911 $(RM) $(ALL_PROGRAMS) perf 908 $(RM) $(ALL_PROGRAMS) perf
912 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* 909 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
913 $(MAKE) -C Documentation/ clean 910 $(MAKE) -C Documentation/ clean
914 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS 911 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
915 $(python-clean) 912 $(python-clean)
916 913
917 .PHONY: all install clean strip 914 .PHONY: all install clean strip
918 .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell 915 .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
919 .PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS 916 .PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS
920 917
tools/perf/builtin-probe.c
1 /* 1 /*
2 * builtin-probe.c 2 * builtin-probe.c
3 * 3 *
4 * Builtin probe command: Set up probe events by C expression 4 * Builtin probe command: Set up probe events by C expression
5 * 5 *
6 * Written by Masami Hiramatsu <mhiramat@redhat.com> 6 * Written by Masami Hiramatsu <mhiramat@redhat.com>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version. 11 * (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * 21 *
22 */ 22 */
23 #define _GNU_SOURCE
24 #include <sys/utsname.h> 23 #include <sys/utsname.h>
25 #include <sys/types.h> 24 #include <sys/types.h>
26 #include <sys/stat.h> 25 #include <sys/stat.h>
27 #include <fcntl.h> 26 #include <fcntl.h>
28 #include <errno.h> 27 #include <errno.h>
29 #include <stdio.h> 28 #include <stdio.h>
30 #include <unistd.h> 29 #include <unistd.h>
31 #include <stdlib.h> 30 #include <stdlib.h>
32 #include <string.h> 31 #include <string.h>
33 32
34 #undef _GNU_SOURCE
35 #include "perf.h" 33 #include "perf.h"
36 #include "builtin.h" 34 #include "builtin.h"
37 #include "util/util.h" 35 #include "util/util.h"
38 #include "util/strlist.h" 36 #include "util/strlist.h"
39 #include "util/strfilter.h" 37 #include "util/strfilter.h"
40 #include "util/symbol.h" 38 #include "util/symbol.h"
41 #include "util/debug.h" 39 #include "util/debug.h"
42 #include "util/debugfs.h" 40 #include "util/debugfs.h"
43 #include "util/parse-options.h" 41 #include "util/parse-options.h"
44 #include "util/probe-finder.h" 42 #include "util/probe-finder.h"
45 #include "util/probe-event.h" 43 #include "util/probe-event.h"
46 44
47 #define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" 45 #define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
48 #define DEFAULT_FUNC_FILTER "!_*" 46 #define DEFAULT_FUNC_FILTER "!_*"
49 47
50 /* Session management structure */ 48 /* Session management structure */
51 static struct { 49 static struct {
52 bool list_events; 50 bool list_events;
53 bool force_add; 51 bool force_add;
54 bool show_lines; 52 bool show_lines;
55 bool show_vars; 53 bool show_vars;
56 bool show_ext_vars; 54 bool show_ext_vars;
57 bool show_funcs; 55 bool show_funcs;
58 bool mod_events; 56 bool mod_events;
59 int nevents; 57 int nevents;
60 struct perf_probe_event events[MAX_PROBES]; 58 struct perf_probe_event events[MAX_PROBES];
61 struct strlist *dellist; 59 struct strlist *dellist;
62 struct line_range line_range; 60 struct line_range line_range;
63 const char *target_module; 61 const char *target_module;
64 int max_probe_points; 62 int max_probe_points;
65 struct strfilter *filter; 63 struct strfilter *filter;
66 } params; 64 } params;
67 65
68 /* Parse an event definition. Note that any error must die. */ 66 /* Parse an event definition. Note that any error must die. */
69 static int parse_probe_event(const char *str) 67 static int parse_probe_event(const char *str)
70 { 68 {
71 struct perf_probe_event *pev = &params.events[params.nevents]; 69 struct perf_probe_event *pev = &params.events[params.nevents];
72 int ret; 70 int ret;
73 71
74 pr_debug("probe-definition(%d): %s\n", params.nevents, str); 72 pr_debug("probe-definition(%d): %s\n", params.nevents, str);
75 if (++params.nevents == MAX_PROBES) { 73 if (++params.nevents == MAX_PROBES) {
76 pr_err("Too many probes (> %d) were specified.", MAX_PROBES); 74 pr_err("Too many probes (> %d) were specified.", MAX_PROBES);
77 return -1; 75 return -1;
78 } 76 }
79 77
80 /* Parse a perf-probe command into event */ 78 /* Parse a perf-probe command into event */
81 ret = parse_perf_probe_command(str, pev); 79 ret = parse_perf_probe_command(str, pev);
82 pr_debug("%d arguments\n", pev->nargs); 80 pr_debug("%d arguments\n", pev->nargs);
83 81
84 return ret; 82 return ret;
85 } 83 }
86 84
87 static int parse_probe_event_argv(int argc, const char **argv) 85 static int parse_probe_event_argv(int argc, const char **argv)
88 { 86 {
89 int i, len, ret; 87 int i, len, ret;
90 char *buf; 88 char *buf;
91 89
92 /* Bind up rest arguments */ 90 /* Bind up rest arguments */
93 len = 0; 91 len = 0;
94 for (i = 0; i < argc; i++) 92 for (i = 0; i < argc; i++)
95 len += strlen(argv[i]) + 1; 93 len += strlen(argv[i]) + 1;
96 buf = zalloc(len + 1); 94 buf = zalloc(len + 1);
97 if (buf == NULL) 95 if (buf == NULL)
98 return -ENOMEM; 96 return -ENOMEM;
99 len = 0; 97 len = 0;
100 for (i = 0; i < argc; i++) 98 for (i = 0; i < argc; i++)
101 len += sprintf(&buf[len], "%s ", argv[i]); 99 len += sprintf(&buf[len], "%s ", argv[i]);
102 params.mod_events = true; 100 params.mod_events = true;
103 ret = parse_probe_event(buf); 101 ret = parse_probe_event(buf);
104 free(buf); 102 free(buf);
105 return ret; 103 return ret;
106 } 104 }
107 105
108 static int opt_add_probe_event(const struct option *opt __used, 106 static int opt_add_probe_event(const struct option *opt __used,
109 const char *str, int unset __used) 107 const char *str, int unset __used)
110 { 108 {
111 if (str) { 109 if (str) {
112 params.mod_events = true; 110 params.mod_events = true;
113 return parse_probe_event(str); 111 return parse_probe_event(str);
114 } else 112 } else
115 return 0; 113 return 0;
116 } 114 }
117 115
118 static int opt_del_probe_event(const struct option *opt __used, 116 static int opt_del_probe_event(const struct option *opt __used,
119 const char *str, int unset __used) 117 const char *str, int unset __used)
120 { 118 {
121 if (str) { 119 if (str) {
122 params.mod_events = true; 120 params.mod_events = true;
123 if (!params.dellist) 121 if (!params.dellist)
124 params.dellist = strlist__new(true, NULL); 122 params.dellist = strlist__new(true, NULL);
125 strlist__add(params.dellist, str); 123 strlist__add(params.dellist, str);
126 } 124 }
127 return 0; 125 return 0;
128 } 126 }
129 127
130 #ifdef DWARF_SUPPORT 128 #ifdef DWARF_SUPPORT
131 static int opt_show_lines(const struct option *opt __used, 129 static int opt_show_lines(const struct option *opt __used,
132 const char *str, int unset __used) 130 const char *str, int unset __used)
133 { 131 {
134 int ret = 0; 132 int ret = 0;
135 133
136 if (!str) 134 if (!str)
137 return 0; 135 return 0;
138 136
139 if (params.show_lines) { 137 if (params.show_lines) {
140 pr_warning("Warning: more than one --line options are" 138 pr_warning("Warning: more than one --line options are"
141 " detected. Only the first one is valid.\n"); 139 " detected. Only the first one is valid.\n");
142 return 0; 140 return 0;
143 } 141 }
144 142
145 params.show_lines = true; 143 params.show_lines = true;
146 ret = parse_line_range_desc(str, &params.line_range); 144 ret = parse_line_range_desc(str, &params.line_range);
147 INIT_LIST_HEAD(&params.line_range.line_list); 145 INIT_LIST_HEAD(&params.line_range.line_list);
148 146
149 return ret; 147 return ret;
150 } 148 }
151 149
152 static int opt_show_vars(const struct option *opt __used, 150 static int opt_show_vars(const struct option *opt __used,
153 const char *str, int unset __used) 151 const char *str, int unset __used)
154 { 152 {
155 struct perf_probe_event *pev = &params.events[params.nevents]; 153 struct perf_probe_event *pev = &params.events[params.nevents];
156 int ret; 154 int ret;
157 155
158 if (!str) 156 if (!str)
159 return 0; 157 return 0;
160 158
161 ret = parse_probe_event(str); 159 ret = parse_probe_event(str);
162 if (!ret && pev->nargs != 0) { 160 if (!ret && pev->nargs != 0) {
163 pr_err(" Error: '--vars' doesn't accept arguments.\n"); 161 pr_err(" Error: '--vars' doesn't accept arguments.\n");
164 return -EINVAL; 162 return -EINVAL;
165 } 163 }
166 params.show_vars = true; 164 params.show_vars = true;
167 165
168 return ret; 166 return ret;
169 } 167 }
170 #endif 168 #endif
171 169
172 static int opt_set_filter(const struct option *opt __used, 170 static int opt_set_filter(const struct option *opt __used,
173 const char *str, int unset __used) 171 const char *str, int unset __used)
174 { 172 {
175 const char *err; 173 const char *err;
176 174
177 if (str) { 175 if (str) {
178 pr_debug2("Set filter: %s\n", str); 176 pr_debug2("Set filter: %s\n", str);
179 if (params.filter) 177 if (params.filter)
180 strfilter__delete(params.filter); 178 strfilter__delete(params.filter);
181 params.filter = strfilter__new(str, &err); 179 params.filter = strfilter__new(str, &err);
182 if (!params.filter) { 180 if (!params.filter) {
183 pr_err("Filter parse error at %td.\n", err - str + 1); 181 pr_err("Filter parse error at %td.\n", err - str + 1);
184 pr_err("Source: \"%s\"\n", str); 182 pr_err("Source: \"%s\"\n", str);
185 pr_err(" %*c\n", (int)(err - str + 1), '^'); 183 pr_err(" %*c\n", (int)(err - str + 1), '^');
186 return -EINVAL; 184 return -EINVAL;
187 } 185 }
188 } 186 }
189 187
190 return 0; 188 return 0;
191 } 189 }
192 190
193 static const char * const probe_usage[] = { 191 static const char * const probe_usage[] = {
194 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", 192 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
195 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 193 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
196 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 194 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
197 "perf probe --list", 195 "perf probe --list",
198 #ifdef DWARF_SUPPORT 196 #ifdef DWARF_SUPPORT
199 "perf probe [<options>] --line 'LINEDESC'", 197 "perf probe [<options>] --line 'LINEDESC'",
200 "perf probe [<options>] --vars 'PROBEPOINT'", 198 "perf probe [<options>] --vars 'PROBEPOINT'",
201 #endif 199 #endif
202 NULL 200 NULL
203 }; 201 };
204 202
205 static const struct option options[] = { 203 static const struct option options[] = {
206 OPT_INCR('v', "verbose", &verbose, 204 OPT_INCR('v', "verbose", &verbose,
207 "be more verbose (show parsed arguments, etc)"), 205 "be more verbose (show parsed arguments, etc)"),
208 OPT_BOOLEAN('l', "list", &params.list_events, 206 OPT_BOOLEAN('l', "list", &params.list_events,
209 "list up current probe events"), 207 "list up current probe events"),
210 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 208 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
211 opt_del_probe_event), 209 opt_del_probe_event),
212 OPT_CALLBACK('a', "add", NULL, 210 OPT_CALLBACK('a', "add", NULL,
213 #ifdef DWARF_SUPPORT 211 #ifdef DWARF_SUPPORT
214 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" 212 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
215 " [[NAME=]ARG ...]", 213 " [[NAME=]ARG ...]",
216 #else 214 #else
217 "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]", 215 "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]",
218 #endif 216 #endif
219 "probe point definition, where\n" 217 "probe point definition, where\n"
220 "\t\tGROUP:\tGroup name (optional)\n" 218 "\t\tGROUP:\tGroup name (optional)\n"
221 "\t\tEVENT:\tEvent name\n" 219 "\t\tEVENT:\tEvent name\n"
222 "\t\tFUNC:\tFunction name\n" 220 "\t\tFUNC:\tFunction name\n"
223 "\t\tOFF:\tOffset from function entry (in byte)\n" 221 "\t\tOFF:\tOffset from function entry (in byte)\n"
224 "\t\t%return:\tPut the probe at function return\n" 222 "\t\t%return:\tPut the probe at function return\n"
225 #ifdef DWARF_SUPPORT 223 #ifdef DWARF_SUPPORT
226 "\t\tSRC:\tSource code path\n" 224 "\t\tSRC:\tSource code path\n"
227 "\t\tRL:\tRelative line number from function entry.\n" 225 "\t\tRL:\tRelative line number from function entry.\n"
228 "\t\tAL:\tAbsolute line number in file.\n" 226 "\t\tAL:\tAbsolute line number in file.\n"
229 "\t\tPT:\tLazy expression of line code.\n" 227 "\t\tPT:\tLazy expression of line code.\n"
230 "\t\tARG:\tProbe argument (local variable name or\n" 228 "\t\tARG:\tProbe argument (local variable name or\n"
231 "\t\t\tkprobe-tracer argument format.)\n", 229 "\t\t\tkprobe-tracer argument format.)\n",
232 #else 230 #else
233 "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n", 231 "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
234 #endif 232 #endif
235 opt_add_probe_event), 233 opt_add_probe_event),
236 OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events" 234 OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events"
237 " with existing name"), 235 " with existing name"),
238 #ifdef DWARF_SUPPORT 236 #ifdef DWARF_SUPPORT
239 OPT_CALLBACK('L', "line", NULL, 237 OPT_CALLBACK('L', "line", NULL,
240 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", 238 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
241 "Show source code lines.", opt_show_lines), 239 "Show source code lines.", opt_show_lines),
242 OPT_CALLBACK('V', "vars", NULL, 240 OPT_CALLBACK('V', "vars", NULL,
243 "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT", 241 "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
244 "Show accessible variables on PROBEDEF", opt_show_vars), 242 "Show accessible variables on PROBEDEF", opt_show_vars),
245 OPT_BOOLEAN('\0', "externs", &params.show_ext_vars, 243 OPT_BOOLEAN('\0', "externs", &params.show_ext_vars,
246 "Show external variables too (with --vars only)"), 244 "Show external variables too (with --vars only)"),
247 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 245 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
248 "file", "vmlinux pathname"), 246 "file", "vmlinux pathname"),
249 OPT_STRING('s', "source", &symbol_conf.source_prefix, 247 OPT_STRING('s', "source", &symbol_conf.source_prefix,
250 "directory", "path to kernel source"), 248 "directory", "path to kernel source"),
251 OPT_STRING('m', "module", &params.target_module, 249 OPT_STRING('m', "module", &params.target_module,
252 "modname|path", 250 "modname|path",
253 "target module name (for online) or path (for offline)"), 251 "target module name (for online) or path (for offline)"),
254 #endif 252 #endif
255 OPT__DRY_RUN(&probe_event_dry_run), 253 OPT__DRY_RUN(&probe_event_dry_run),
256 OPT_INTEGER('\0', "max-probes", &params.max_probe_points, 254 OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
257 "Set how many probe points can be found for a probe."), 255 "Set how many probe points can be found for a probe."),
258 OPT_BOOLEAN('F', "funcs", &params.show_funcs, 256 OPT_BOOLEAN('F', "funcs", &params.show_funcs,
259 "Show potential probe-able functions."), 257 "Show potential probe-able functions."),
260 OPT_CALLBACK('\0', "filter", NULL, 258 OPT_CALLBACK('\0', "filter", NULL,
261 "[!]FILTER", "Set a filter (with --vars/funcs only)\n" 259 "[!]FILTER", "Set a filter (with --vars/funcs only)\n"
262 "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n" 260 "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
263 "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)", 261 "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)",
264 opt_set_filter), 262 opt_set_filter),
265 OPT_END() 263 OPT_END()
266 }; 264 };
267 265
268 int cmd_probe(int argc, const char **argv, const char *prefix __used) 266 int cmd_probe(int argc, const char **argv, const char *prefix __used)
269 { 267 {
270 int ret; 268 int ret;
271 269
272 argc = parse_options(argc, argv, options, probe_usage, 270 argc = parse_options(argc, argv, options, probe_usage,
273 PARSE_OPT_STOP_AT_NON_OPTION); 271 PARSE_OPT_STOP_AT_NON_OPTION);
274 if (argc > 0) { 272 if (argc > 0) {
275 if (strcmp(argv[0], "-") == 0) { 273 if (strcmp(argv[0], "-") == 0) {
276 pr_warning(" Error: '-' is not supported.\n"); 274 pr_warning(" Error: '-' is not supported.\n");
277 usage_with_options(probe_usage, options); 275 usage_with_options(probe_usage, options);
278 } 276 }
279 ret = parse_probe_event_argv(argc, argv); 277 ret = parse_probe_event_argv(argc, argv);
280 if (ret < 0) { 278 if (ret < 0) {
281 pr_err(" Error: Parse Error. (%d)\n", ret); 279 pr_err(" Error: Parse Error. (%d)\n", ret);
282 return ret; 280 return ret;
283 } 281 }
284 } 282 }
285 283
286 if (params.max_probe_points == 0) 284 if (params.max_probe_points == 0)
287 params.max_probe_points = MAX_PROBES; 285 params.max_probe_points = MAX_PROBES;
288 286
289 if ((!params.nevents && !params.dellist && !params.list_events && 287 if ((!params.nevents && !params.dellist && !params.list_events &&
290 !params.show_lines && !params.show_funcs)) 288 !params.show_lines && !params.show_funcs))
291 usage_with_options(probe_usage, options); 289 usage_with_options(probe_usage, options);
292 290
293 /* 291 /*
294 * Only consider the user's kernel image path if given. 292 * Only consider the user's kernel image path if given.
295 */ 293 */
296 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 294 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
297 295
298 if (params.list_events) { 296 if (params.list_events) {
299 if (params.mod_events) { 297 if (params.mod_events) {
300 pr_err(" Error: Don't use --list with --add/--del.\n"); 298 pr_err(" Error: Don't use --list with --add/--del.\n");
301 usage_with_options(probe_usage, options); 299 usage_with_options(probe_usage, options);
302 } 300 }
303 if (params.show_lines) { 301 if (params.show_lines) {
304 pr_err(" Error: Don't use --list with --line.\n"); 302 pr_err(" Error: Don't use --list with --line.\n");
305 usage_with_options(probe_usage, options); 303 usage_with_options(probe_usage, options);
306 } 304 }
307 if (params.show_vars) { 305 if (params.show_vars) {
308 pr_err(" Error: Don't use --list with --vars.\n"); 306 pr_err(" Error: Don't use --list with --vars.\n");
309 usage_with_options(probe_usage, options); 307 usage_with_options(probe_usage, options);
310 } 308 }
311 if (params.show_funcs) { 309 if (params.show_funcs) {
312 pr_err(" Error: Don't use --list with --funcs.\n"); 310 pr_err(" Error: Don't use --list with --funcs.\n");
313 usage_with_options(probe_usage, options); 311 usage_with_options(probe_usage, options);
314 } 312 }
315 ret = show_perf_probe_events(); 313 ret = show_perf_probe_events();
316 if (ret < 0) 314 if (ret < 0)
317 pr_err(" Error: Failed to show event list. (%d)\n", 315 pr_err(" Error: Failed to show event list. (%d)\n",
318 ret); 316 ret);
319 return ret; 317 return ret;
320 } 318 }
321 if (params.show_funcs) { 319 if (params.show_funcs) {
322 if (params.nevents != 0 || params.dellist) { 320 if (params.nevents != 0 || params.dellist) {
323 pr_err(" Error: Don't use --funcs with" 321 pr_err(" Error: Don't use --funcs with"
324 " --add/--del.\n"); 322 " --add/--del.\n");
325 usage_with_options(probe_usage, options); 323 usage_with_options(probe_usage, options);
326 } 324 }
327 if (params.show_lines) { 325 if (params.show_lines) {
328 pr_err(" Error: Don't use --funcs with --line.\n"); 326 pr_err(" Error: Don't use --funcs with --line.\n");
329 usage_with_options(probe_usage, options); 327 usage_with_options(probe_usage, options);
330 } 328 }
331 if (params.show_vars) { 329 if (params.show_vars) {
332 pr_err(" Error: Don't use --funcs with --vars.\n"); 330 pr_err(" Error: Don't use --funcs with --vars.\n");
333 usage_with_options(probe_usage, options); 331 usage_with_options(probe_usage, options);
334 } 332 }
335 if (!params.filter) 333 if (!params.filter)
336 params.filter = strfilter__new(DEFAULT_FUNC_FILTER, 334 params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
337 NULL); 335 NULL);
338 ret = show_available_funcs(params.target_module, 336 ret = show_available_funcs(params.target_module,
339 params.filter); 337 params.filter);
340 strfilter__delete(params.filter); 338 strfilter__delete(params.filter);
341 if (ret < 0) 339 if (ret < 0)
342 pr_err(" Error: Failed to show functions." 340 pr_err(" Error: Failed to show functions."
343 " (%d)\n", ret); 341 " (%d)\n", ret);
344 return ret; 342 return ret;
345 } 343 }
346 344
347 #ifdef DWARF_SUPPORT 345 #ifdef DWARF_SUPPORT
348 if (params.show_lines) { 346 if (params.show_lines) {
349 if (params.mod_events) { 347 if (params.mod_events) {
350 pr_err(" Error: Don't use --line with" 348 pr_err(" Error: Don't use --line with"
351 " --add/--del.\n"); 349 " --add/--del.\n");
352 usage_with_options(probe_usage, options); 350 usage_with_options(probe_usage, options);
353 } 351 }
354 if (params.show_vars) { 352 if (params.show_vars) {
355 pr_err(" Error: Don't use --line with --vars.\n"); 353 pr_err(" Error: Don't use --line with --vars.\n");
356 usage_with_options(probe_usage, options); 354 usage_with_options(probe_usage, options);
357 } 355 }
358 356
359 ret = show_line_range(&params.line_range, params.target_module); 357 ret = show_line_range(&params.line_range, params.target_module);
360 if (ret < 0) 358 if (ret < 0)
361 pr_err(" Error: Failed to show lines. (%d)\n", ret); 359 pr_err(" Error: Failed to show lines. (%d)\n", ret);
362 return ret; 360 return ret;
363 } 361 }
364 if (params.show_vars) { 362 if (params.show_vars) {
365 if (params.mod_events) { 363 if (params.mod_events) {
366 pr_err(" Error: Don't use --vars with" 364 pr_err(" Error: Don't use --vars with"
367 " --add/--del.\n"); 365 " --add/--del.\n");
368 usage_with_options(probe_usage, options); 366 usage_with_options(probe_usage, options);
369 } 367 }
370 if (!params.filter) 368 if (!params.filter)
371 params.filter = strfilter__new(DEFAULT_VAR_FILTER, 369 params.filter = strfilter__new(DEFAULT_VAR_FILTER,
372 NULL); 370 NULL);
373 371
374 ret = show_available_vars(params.events, params.nevents, 372 ret = show_available_vars(params.events, params.nevents,
375 params.max_probe_points, 373 params.max_probe_points,
376 params.target_module, 374 params.target_module,
377 params.filter, 375 params.filter,
378 params.show_ext_vars); 376 params.show_ext_vars);
379 strfilter__delete(params.filter); 377 strfilter__delete(params.filter);
380 if (ret < 0) 378 if (ret < 0)
381 pr_err(" Error: Failed to show vars. (%d)\n", ret); 379 pr_err(" Error: Failed to show vars. (%d)\n", ret);
382 return ret; 380 return ret;
383 } 381 }
384 #endif 382 #endif
385 383
386 if (params.dellist) { 384 if (params.dellist) {
387 ret = del_perf_probe_events(params.dellist); 385 ret = del_perf_probe_events(params.dellist);
388 strlist__delete(params.dellist); 386 strlist__delete(params.dellist);
389 if (ret < 0) { 387 if (ret < 0) {
390 pr_err(" Error: Failed to delete events. (%d)\n", ret); 388 pr_err(" Error: Failed to delete events. (%d)\n", ret);
391 return ret; 389 return ret;
392 } 390 }
393 } 391 }
394 392
395 if (params.nevents) { 393 if (params.nevents) {
396 ret = add_perf_probe_events(params.events, params.nevents, 394 ret = add_perf_probe_events(params.events, params.nevents,
397 params.max_probe_points, 395 params.max_probe_points,
398 params.target_module, 396 params.target_module,
399 params.force_add); 397 params.force_add);
400 if (ret < 0) { 398 if (ret < 0) {
401 pr_err(" Error: Failed to add events. (%d)\n", ret); 399 pr_err(" Error: Failed to add events. (%d)\n", ret);
402 return ret; 400 return ret;
403 } 401 }
404 } 402 }
405 return 0; 403 return 0;
406 } 404 }
407 405
tools/perf/util/probe-event.c
1 /* 1 /*
2 * probe-event.c : perf-probe definition to probe_events format converter 2 * probe-event.c : perf-probe definition to probe_events format converter
3 * 3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com> 4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or 8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. 9 * (at your option) any later version.
10 * 10 *
11 * This program is distributed in the hope that it will be useful, 11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License 16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * 19 *
20 */ 20 */
21 21
22 #define _GNU_SOURCE
23 #include <sys/utsname.h> 22 #include <sys/utsname.h>
24 #include <sys/types.h> 23 #include <sys/types.h>
25 #include <sys/stat.h> 24 #include <sys/stat.h>
26 #include <fcntl.h> 25 #include <fcntl.h>
27 #include <errno.h> 26 #include <errno.h>
28 #include <stdio.h> 27 #include <stdio.h>
29 #include <unistd.h> 28 #include <unistd.h>
30 #include <stdlib.h> 29 #include <stdlib.h>
31 #include <string.h> 30 #include <string.h>
32 #include <stdarg.h> 31 #include <stdarg.h>
33 #include <limits.h> 32 #include <limits.h>
34 #include <elf.h> 33 #include <elf.h>
35 34
36 #undef _GNU_SOURCE
37 #include "util.h" 35 #include "util.h"
38 #include "event.h" 36 #include "event.h"
39 #include "string.h" 37 #include "string.h"
40 #include "strlist.h" 38 #include "strlist.h"
41 #include "debug.h" 39 #include "debug.h"
42 #include "cache.h" 40 #include "cache.h"
43 #include "color.h" 41 #include "color.h"
44 #include "symbol.h" 42 #include "symbol.h"
45 #include "thread.h" 43 #include "thread.h"
46 #include "debugfs.h" 44 #include "debugfs.h"
47 #include "trace-event.h" /* For __unused */ 45 #include "trace-event.h" /* For __unused */
48 #include "probe-event.h" 46 #include "probe-event.h"
49 #include "probe-finder.h" 47 #include "probe-finder.h"
50 48
51 #define MAX_CMDLEN 256 49 #define MAX_CMDLEN 256
52 #define MAX_PROBE_ARGS 128 50 #define MAX_PROBE_ARGS 128
53 #define PERFPROBE_GROUP "probe" 51 #define PERFPROBE_GROUP "probe"
54 52
55 bool probe_event_dry_run; /* Dry run flag */ 53 bool probe_event_dry_run; /* Dry run flag */
56 54
57 #define semantic_error(msg ...) pr_err("Semantic error :" msg) 55 #define semantic_error(msg ...) pr_err("Semantic error :" msg)
58 56
59 /* If there is no space to write, returns -E2BIG. */ 57 /* If there is no space to write, returns -E2BIG. */
60 static int e_snprintf(char *str, size_t size, const char *format, ...) 58 static int e_snprintf(char *str, size_t size, const char *format, ...)
61 __attribute__((format(printf, 3, 4))); 59 __attribute__((format(printf, 3, 4)));
62 60
63 static int e_snprintf(char *str, size_t size, const char *format, ...) 61 static int e_snprintf(char *str, size_t size, const char *format, ...)
64 { 62 {
65 int ret; 63 int ret;
66 va_list ap; 64 va_list ap;
67 va_start(ap, format); 65 va_start(ap, format);
68 ret = vsnprintf(str, size, format, ap); 66 ret = vsnprintf(str, size, format, ap);
69 va_end(ap); 67 va_end(ap);
70 if (ret >= (int)size) 68 if (ret >= (int)size)
71 ret = -E2BIG; 69 ret = -E2BIG;
72 return ret; 70 return ret;
73 } 71 }
74 72
75 static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 73 static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
76 static struct machine machine; 74 static struct machine machine;
77 75
78 /* Initialize symbol maps and path of vmlinux/modules */ 76 /* Initialize symbol maps and path of vmlinux/modules */
79 static int init_vmlinux(void) 77 static int init_vmlinux(void)
80 { 78 {
81 int ret; 79 int ret;
82 80
83 symbol_conf.sort_by_name = true; 81 symbol_conf.sort_by_name = true;
84 if (symbol_conf.vmlinux_name == NULL) 82 if (symbol_conf.vmlinux_name == NULL)
85 symbol_conf.try_vmlinux_path = true; 83 symbol_conf.try_vmlinux_path = true;
86 else 84 else
87 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); 85 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
88 ret = symbol__init(); 86 ret = symbol__init();
89 if (ret < 0) { 87 if (ret < 0) {
90 pr_debug("Failed to init symbol map.\n"); 88 pr_debug("Failed to init symbol map.\n");
91 goto out; 89 goto out;
92 } 90 }
93 91
94 ret = machine__init(&machine, "", HOST_KERNEL_ID); 92 ret = machine__init(&machine, "", HOST_KERNEL_ID);
95 if (ret < 0) 93 if (ret < 0)
96 goto out; 94 goto out;
97 95
98 if (machine__create_kernel_maps(&machine) < 0) { 96 if (machine__create_kernel_maps(&machine) < 0) {
99 pr_debug("machine__create_kernel_maps() failed.\n"); 97 pr_debug("machine__create_kernel_maps() failed.\n");
100 goto out; 98 goto out;
101 } 99 }
102 out: 100 out:
103 if (ret < 0) 101 if (ret < 0)
104 pr_warning("Failed to init vmlinux path.\n"); 102 pr_warning("Failed to init vmlinux path.\n");
105 return ret; 103 return ret;
106 } 104 }
107 105
108 static struct symbol *__find_kernel_function_by_name(const char *name, 106 static struct symbol *__find_kernel_function_by_name(const char *name,
109 struct map **mapp) 107 struct map **mapp)
110 { 108 {
111 return machine__find_kernel_function_by_name(&machine, name, mapp, 109 return machine__find_kernel_function_by_name(&machine, name, mapp,
112 NULL); 110 NULL);
113 } 111 }
114 112
115 static struct map *kernel_get_module_map(const char *module) 113 static struct map *kernel_get_module_map(const char *module)
116 { 114 {
117 struct rb_node *nd; 115 struct rb_node *nd;
118 struct map_groups *grp = &machine.kmaps; 116 struct map_groups *grp = &machine.kmaps;
119 117
120 /* A file path -- this is an offline module */ 118 /* A file path -- this is an offline module */
121 if (module && strchr(module, '/')) 119 if (module && strchr(module, '/'))
122 return machine__new_module(&machine, 0, module); 120 return machine__new_module(&machine, 0, module);
123 121
124 if (!module) 122 if (!module)
125 module = "kernel"; 123 module = "kernel";
126 124
127 for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { 125 for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) {
128 struct map *pos = rb_entry(nd, struct map, rb_node); 126 struct map *pos = rb_entry(nd, struct map, rb_node);
129 if (strncmp(pos->dso->short_name + 1, module, 127 if (strncmp(pos->dso->short_name + 1, module,
130 pos->dso->short_name_len - 2) == 0) { 128 pos->dso->short_name_len - 2) == 0) {
131 return pos; 129 return pos;
132 } 130 }
133 } 131 }
134 return NULL; 132 return NULL;
135 } 133 }
136 134
137 static struct dso *kernel_get_module_dso(const char *module) 135 static struct dso *kernel_get_module_dso(const char *module)
138 { 136 {
139 struct dso *dso; 137 struct dso *dso;
140 struct map *map; 138 struct map *map;
141 const char *vmlinux_name; 139 const char *vmlinux_name;
142 140
143 if (module) { 141 if (module) {
144 list_for_each_entry(dso, &machine.kernel_dsos, node) { 142 list_for_each_entry(dso, &machine.kernel_dsos, node) {
145 if (strncmp(dso->short_name + 1, module, 143 if (strncmp(dso->short_name + 1, module,
146 dso->short_name_len - 2) == 0) 144 dso->short_name_len - 2) == 0)
147 goto found; 145 goto found;
148 } 146 }
149 pr_debug("Failed to find module %s.\n", module); 147 pr_debug("Failed to find module %s.\n", module);
150 return NULL; 148 return NULL;
151 } 149 }
152 150
153 map = machine.vmlinux_maps[MAP__FUNCTION]; 151 map = machine.vmlinux_maps[MAP__FUNCTION];
154 dso = map->dso; 152 dso = map->dso;
155 153
156 vmlinux_name = symbol_conf.vmlinux_name; 154 vmlinux_name = symbol_conf.vmlinux_name;
157 if (vmlinux_name) { 155 if (vmlinux_name) {
158 if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0) 156 if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0)
159 return NULL; 157 return NULL;
160 } else { 158 } else {
161 if (dso__load_vmlinux_path(dso, map, NULL) <= 0) { 159 if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
162 pr_debug("Failed to load kernel map.\n"); 160 pr_debug("Failed to load kernel map.\n");
163 return NULL; 161 return NULL;
164 } 162 }
165 } 163 }
166 found: 164 found:
167 return dso; 165 return dso;
168 } 166 }
169 167
170 const char *kernel_get_module_path(const char *module) 168 const char *kernel_get_module_path(const char *module)
171 { 169 {
172 struct dso *dso = kernel_get_module_dso(module); 170 struct dso *dso = kernel_get_module_dso(module);
173 return (dso) ? dso->long_name : NULL; 171 return (dso) ? dso->long_name : NULL;
174 } 172 }
175 173
176 #ifdef DWARF_SUPPORT 174 #ifdef DWARF_SUPPORT
177 /* Open new debuginfo of given module */ 175 /* Open new debuginfo of given module */
178 static struct debuginfo *open_debuginfo(const char *module) 176 static struct debuginfo *open_debuginfo(const char *module)
179 { 177 {
180 const char *path; 178 const char *path;
181 179
182 /* A file path -- this is an offline module */ 180 /* A file path -- this is an offline module */
183 if (module && strchr(module, '/')) 181 if (module && strchr(module, '/'))
184 path = module; 182 path = module;
185 else { 183 else {
186 path = kernel_get_module_path(module); 184 path = kernel_get_module_path(module);
187 185
188 if (!path) { 186 if (!path) {
189 pr_err("Failed to find path of %s module.\n", 187 pr_err("Failed to find path of %s module.\n",
190 module ?: "kernel"); 188 module ?: "kernel");
191 return NULL; 189 return NULL;
192 } 190 }
193 } 191 }
194 return debuginfo__new(path); 192 return debuginfo__new(path);
195 } 193 }
196 194
197 /* 195 /*
198 * Convert trace point to probe point with debuginfo 196 * Convert trace point to probe point with debuginfo
199 * Currently only handles kprobes. 197 * Currently only handles kprobes.
200 */ 198 */
201 static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 199 static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
202 struct perf_probe_point *pp) 200 struct perf_probe_point *pp)
203 { 201 {
204 struct symbol *sym; 202 struct symbol *sym;
205 struct map *map; 203 struct map *map;
206 u64 addr; 204 u64 addr;
207 int ret = -ENOENT; 205 int ret = -ENOENT;
208 struct debuginfo *dinfo; 206 struct debuginfo *dinfo;
209 207
210 sym = __find_kernel_function_by_name(tp->symbol, &map); 208 sym = __find_kernel_function_by_name(tp->symbol, &map);
211 if (sym) { 209 if (sym) {
212 addr = map->unmap_ip(map, sym->start + tp->offset); 210 addr = map->unmap_ip(map, sym->start + tp->offset);
213 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, 211 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
214 tp->offset, addr); 212 tp->offset, addr);
215 213
216 dinfo = debuginfo__new_online_kernel(addr); 214 dinfo = debuginfo__new_online_kernel(addr);
217 if (dinfo) { 215 if (dinfo) {
218 ret = debuginfo__find_probe_point(dinfo, 216 ret = debuginfo__find_probe_point(dinfo,
219 (unsigned long)addr, pp); 217 (unsigned long)addr, pp);
220 debuginfo__delete(dinfo); 218 debuginfo__delete(dinfo);
221 } else { 219 } else {
222 pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n", 220 pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n",
223 addr); 221 addr);
224 ret = -ENOENT; 222 ret = -ENOENT;
225 } 223 }
226 } 224 }
227 if (ret <= 0) { 225 if (ret <= 0) {
228 pr_debug("Failed to find corresponding probes from " 226 pr_debug("Failed to find corresponding probes from "
229 "debuginfo. Use kprobe event information.\n"); 227 "debuginfo. Use kprobe event information.\n");
230 pp->function = strdup(tp->symbol); 228 pp->function = strdup(tp->symbol);
231 if (pp->function == NULL) 229 if (pp->function == NULL)
232 return -ENOMEM; 230 return -ENOMEM;
233 pp->offset = tp->offset; 231 pp->offset = tp->offset;
234 } 232 }
235 pp->retprobe = tp->retprobe; 233 pp->retprobe = tp->retprobe;
236 234
237 return 0; 235 return 0;
238 } 236 }
239 237
240 static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, 238 static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
241 int ntevs, const char *module) 239 int ntevs, const char *module)
242 { 240 {
243 int i, ret = 0; 241 int i, ret = 0;
244 char *tmp; 242 char *tmp;
245 243
246 if (!module) 244 if (!module)
247 return 0; 245 return 0;
248 246
249 tmp = strrchr(module, '/'); 247 tmp = strrchr(module, '/');
250 if (tmp) { 248 if (tmp) {
251 /* This is a module path -- get the module name */ 249 /* This is a module path -- get the module name */
252 module = strdup(tmp + 1); 250 module = strdup(tmp + 1);
253 if (!module) 251 if (!module)
254 return -ENOMEM; 252 return -ENOMEM;
255 tmp = strchr(module, '.'); 253 tmp = strchr(module, '.');
256 if (tmp) 254 if (tmp)
257 *tmp = '\0'; 255 *tmp = '\0';
258 tmp = (char *)module; /* For free() */ 256 tmp = (char *)module; /* For free() */
259 } 257 }
260 258
261 for (i = 0; i < ntevs; i++) { 259 for (i = 0; i < ntevs; i++) {
262 tevs[i].point.module = strdup(module); 260 tevs[i].point.module = strdup(module);
263 if (!tevs[i].point.module) { 261 if (!tevs[i].point.module) {
264 ret = -ENOMEM; 262 ret = -ENOMEM;
265 break; 263 break;
266 } 264 }
267 } 265 }
268 266
269 if (tmp) 267 if (tmp)
270 free(tmp); 268 free(tmp);
271 269
272 return ret; 270 return ret;
273 } 271 }
274 272
275 /* Try to find perf_probe_event with debuginfo */ 273 /* Try to find perf_probe_event with debuginfo */
276 static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 274 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
277 struct probe_trace_event **tevs, 275 struct probe_trace_event **tevs,
278 int max_tevs, const char *module) 276 int max_tevs, const char *module)
279 { 277 {
280 bool need_dwarf = perf_probe_event_need_dwarf(pev); 278 bool need_dwarf = perf_probe_event_need_dwarf(pev);
281 struct debuginfo *dinfo = open_debuginfo(module); 279 struct debuginfo *dinfo = open_debuginfo(module);
282 int ntevs, ret = 0; 280 int ntevs, ret = 0;
283 281
284 if (!dinfo) { 282 if (!dinfo) {
285 if (need_dwarf) { 283 if (need_dwarf) {
286 pr_warning("Failed to open debuginfo file.\n"); 284 pr_warning("Failed to open debuginfo file.\n");
287 return -ENOENT; 285 return -ENOENT;
288 } 286 }
289 pr_debug("Could not open debuginfo. Try to use symbols.\n"); 287 pr_debug("Could not open debuginfo. Try to use symbols.\n");
290 return 0; 288 return 0;
291 } 289 }
292 290
293 /* Searching trace events corresponding to a probe event */ 291 /* Searching trace events corresponding to a probe event */
294 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs); 292 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
295 293
296 debuginfo__delete(dinfo); 294 debuginfo__delete(dinfo);
297 295
298 if (ntevs > 0) { /* Succeeded to find trace events */ 296 if (ntevs > 0) { /* Succeeded to find trace events */
299 pr_debug("find %d probe_trace_events.\n", ntevs); 297 pr_debug("find %d probe_trace_events.\n", ntevs);
300 if (module) 298 if (module)
301 ret = add_module_to_probe_trace_events(*tevs, ntevs, 299 ret = add_module_to_probe_trace_events(*tevs, ntevs,
302 module); 300 module);
303 return ret < 0 ? ret : ntevs; 301 return ret < 0 ? ret : ntevs;
304 } 302 }
305 303
306 if (ntevs == 0) { /* No error but failed to find probe point. */ 304 if (ntevs == 0) { /* No error but failed to find probe point. */
307 pr_warning("Probe point '%s' not found.\n", 305 pr_warning("Probe point '%s' not found.\n",
308 synthesize_perf_probe_point(&pev->point)); 306 synthesize_perf_probe_point(&pev->point));
309 return -ENOENT; 307 return -ENOENT;
310 } 308 }
311 /* Error path : ntevs < 0 */ 309 /* Error path : ntevs < 0 */
312 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 310 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
313 if (ntevs == -EBADF) { 311 if (ntevs == -EBADF) {
314 pr_warning("Warning: No dwarf info found in the vmlinux - " 312 pr_warning("Warning: No dwarf info found in the vmlinux - "
315 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 313 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
316 if (!need_dwarf) { 314 if (!need_dwarf) {
317 pr_debug("Trying to use symbols.\n"); 315 pr_debug("Trying to use symbols.\n");
318 return 0; 316 return 0;
319 } 317 }
320 } 318 }
321 return ntevs; 319 return ntevs;
322 } 320 }
323 321
324 /* 322 /*
325 * Find a src file from a DWARF tag path. Prepend optional source path prefix 323 * Find a src file from a DWARF tag path. Prepend optional source path prefix
326 * and chop off leading directories that do not exist. Result is passed back as 324 * and chop off leading directories that do not exist. Result is passed back as
327 * a newly allocated path on success. 325 * a newly allocated path on success.
328 * Return 0 if file was found and readable, -errno otherwise. 326 * Return 0 if file was found and readable, -errno otherwise.
329 */ 327 */
330 static int get_real_path(const char *raw_path, const char *comp_dir, 328 static int get_real_path(const char *raw_path, const char *comp_dir,
331 char **new_path) 329 char **new_path)
332 { 330 {
333 const char *prefix = symbol_conf.source_prefix; 331 const char *prefix = symbol_conf.source_prefix;
334 332
335 if (!prefix) { 333 if (!prefix) {
336 if (raw_path[0] != '/' && comp_dir) 334 if (raw_path[0] != '/' && comp_dir)
337 /* If not an absolute path, try to use comp_dir */ 335 /* If not an absolute path, try to use comp_dir */
338 prefix = comp_dir; 336 prefix = comp_dir;
339 else { 337 else {
340 if (access(raw_path, R_OK) == 0) { 338 if (access(raw_path, R_OK) == 0) {
341 *new_path = strdup(raw_path); 339 *new_path = strdup(raw_path);
342 return 0; 340 return 0;
343 } else 341 } else
344 return -errno; 342 return -errno;
345 } 343 }
346 } 344 }
347 345
348 *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2)); 346 *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
349 if (!*new_path) 347 if (!*new_path)
350 return -ENOMEM; 348 return -ENOMEM;
351 349
352 for (;;) { 350 for (;;) {
353 sprintf(*new_path, "%s/%s", prefix, raw_path); 351 sprintf(*new_path, "%s/%s", prefix, raw_path);
354 352
355 if (access(*new_path, R_OK) == 0) 353 if (access(*new_path, R_OK) == 0)
356 return 0; 354 return 0;
357 355
358 if (!symbol_conf.source_prefix) 356 if (!symbol_conf.source_prefix)
359 /* In case of searching comp_dir, don't retry */ 357 /* In case of searching comp_dir, don't retry */
360 return -errno; 358 return -errno;
361 359
362 switch (errno) { 360 switch (errno) {
363 case ENAMETOOLONG: 361 case ENAMETOOLONG:
364 case ENOENT: 362 case ENOENT:
365 case EROFS: 363 case EROFS:
366 case EFAULT: 364 case EFAULT:
367 raw_path = strchr(++raw_path, '/'); 365 raw_path = strchr(++raw_path, '/');
368 if (!raw_path) { 366 if (!raw_path) {
369 free(*new_path); 367 free(*new_path);
370 *new_path = NULL; 368 *new_path = NULL;
371 return -ENOENT; 369 return -ENOENT;
372 } 370 }
373 continue; 371 continue;
374 372
375 default: 373 default:
376 free(*new_path); 374 free(*new_path);
377 *new_path = NULL; 375 *new_path = NULL;
378 return -errno; 376 return -errno;
379 } 377 }
380 } 378 }
381 } 379 }
382 380
383 #define LINEBUF_SIZE 256 381 #define LINEBUF_SIZE 256
384 #define NR_ADDITIONAL_LINES 2 382 #define NR_ADDITIONAL_LINES 2
385 383
386 static int __show_one_line(FILE *fp, int l, bool skip, bool show_num) 384 static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
387 { 385 {
388 char buf[LINEBUF_SIZE]; 386 char buf[LINEBUF_SIZE];
389 const char *color = show_num ? "" : PERF_COLOR_BLUE; 387 const char *color = show_num ? "" : PERF_COLOR_BLUE;
390 const char *prefix = NULL; 388 const char *prefix = NULL;
391 389
392 do { 390 do {
393 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 391 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
394 goto error; 392 goto error;
395 if (skip) 393 if (skip)
396 continue; 394 continue;
397 if (!prefix) { 395 if (!prefix) {
398 prefix = show_num ? "%7d " : " "; 396 prefix = show_num ? "%7d " : " ";
399 color_fprintf(stdout, color, prefix, l); 397 color_fprintf(stdout, color, prefix, l);
400 } 398 }
401 color_fprintf(stdout, color, "%s", buf); 399 color_fprintf(stdout, color, "%s", buf);
402 400
403 } while (strchr(buf, '\n') == NULL); 401 } while (strchr(buf, '\n') == NULL);
404 402
405 return 1; 403 return 1;
406 error: 404 error:
407 if (ferror(fp)) { 405 if (ferror(fp)) {
408 pr_warning("File read error: %s\n", strerror(errno)); 406 pr_warning("File read error: %s\n", strerror(errno));
409 return -1; 407 return -1;
410 } 408 }
411 return 0; 409 return 0;
412 } 410 }
413 411
414 static int _show_one_line(FILE *fp, int l, bool skip, bool show_num) 412 static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
415 { 413 {
416 int rv = __show_one_line(fp, l, skip, show_num); 414 int rv = __show_one_line(fp, l, skip, show_num);
417 if (rv == 0) { 415 if (rv == 0) {
418 pr_warning("Source file is shorter than expected.\n"); 416 pr_warning("Source file is shorter than expected.\n");
419 rv = -1; 417 rv = -1;
420 } 418 }
421 return rv; 419 return rv;
422 } 420 }
423 421
424 #define show_one_line_with_num(f,l) _show_one_line(f,l,false,true) 422 #define show_one_line_with_num(f,l) _show_one_line(f,l,false,true)
425 #define show_one_line(f,l) _show_one_line(f,l,false,false) 423 #define show_one_line(f,l) _show_one_line(f,l,false,false)
426 #define skip_one_line(f,l) _show_one_line(f,l,true,false) 424 #define skip_one_line(f,l) _show_one_line(f,l,true,false)
427 #define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false) 425 #define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false)
428 426
429 /* 427 /*
430 * Show line-range always requires debuginfo to find source file and 428 * Show line-range always requires debuginfo to find source file and
431 * line number. 429 * line number.
432 */ 430 */
433 int show_line_range(struct line_range *lr, const char *module) 431 int show_line_range(struct line_range *lr, const char *module)
434 { 432 {
435 int l = 1; 433 int l = 1;
436 struct line_node *ln; 434 struct line_node *ln;
437 struct debuginfo *dinfo; 435 struct debuginfo *dinfo;
438 FILE *fp; 436 FILE *fp;
439 int ret; 437 int ret;
440 char *tmp; 438 char *tmp;
441 439
442 /* Search a line range */ 440 /* Search a line range */
443 ret = init_vmlinux(); 441 ret = init_vmlinux();
444 if (ret < 0) 442 if (ret < 0)
445 return ret; 443 return ret;
446 444
447 dinfo = open_debuginfo(module); 445 dinfo = open_debuginfo(module);
448 if (!dinfo) { 446 if (!dinfo) {
449 pr_warning("Failed to open debuginfo file.\n"); 447 pr_warning("Failed to open debuginfo file.\n");
450 return -ENOENT; 448 return -ENOENT;
451 } 449 }
452 450
453 ret = debuginfo__find_line_range(dinfo, lr); 451 ret = debuginfo__find_line_range(dinfo, lr);
454 debuginfo__delete(dinfo); 452 debuginfo__delete(dinfo);
455 if (ret == 0) { 453 if (ret == 0) {
456 pr_warning("Specified source line is not found.\n"); 454 pr_warning("Specified source line is not found.\n");
457 return -ENOENT; 455 return -ENOENT;
458 } else if (ret < 0) { 456 } else if (ret < 0) {
459 pr_warning("Debuginfo analysis failed. (%d)\n", ret); 457 pr_warning("Debuginfo analysis failed. (%d)\n", ret);
460 return ret; 458 return ret;
461 } 459 }
462 460
463 /* Convert source file path */ 461 /* Convert source file path */
464 tmp = lr->path; 462 tmp = lr->path;
465 ret = get_real_path(tmp, lr->comp_dir, &lr->path); 463 ret = get_real_path(tmp, lr->comp_dir, &lr->path);
466 free(tmp); /* Free old path */ 464 free(tmp); /* Free old path */
467 if (ret < 0) { 465 if (ret < 0) {
468 pr_warning("Failed to find source file. (%d)\n", ret); 466 pr_warning("Failed to find source file. (%d)\n", ret);
469 return ret; 467 return ret;
470 } 468 }
471 469
472 setup_pager(); 470 setup_pager();
473 471
474 if (lr->function) 472 if (lr->function)
475 fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path, 473 fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path,
476 lr->start - lr->offset); 474 lr->start - lr->offset);
477 else 475 else
478 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start); 476 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
479 477
480 fp = fopen(lr->path, "r"); 478 fp = fopen(lr->path, "r");
481 if (fp == NULL) { 479 if (fp == NULL) {
482 pr_warning("Failed to open %s: %s\n", lr->path, 480 pr_warning("Failed to open %s: %s\n", lr->path,
483 strerror(errno)); 481 strerror(errno));
484 return -errno; 482 return -errno;
485 } 483 }
486 /* Skip to starting line number */ 484 /* Skip to starting line number */
487 while (l < lr->start) { 485 while (l < lr->start) {
488 ret = skip_one_line(fp, l++); 486 ret = skip_one_line(fp, l++);
489 if (ret < 0) 487 if (ret < 0)
490 goto end; 488 goto end;
491 } 489 }
492 490
493 list_for_each_entry(ln, &lr->line_list, list) { 491 list_for_each_entry(ln, &lr->line_list, list) {
494 for (; ln->line > l; l++) { 492 for (; ln->line > l; l++) {
495 ret = show_one_line(fp, l - lr->offset); 493 ret = show_one_line(fp, l - lr->offset);
496 if (ret < 0) 494 if (ret < 0)
497 goto end; 495 goto end;
498 } 496 }
499 ret = show_one_line_with_num(fp, l++ - lr->offset); 497 ret = show_one_line_with_num(fp, l++ - lr->offset);
500 if (ret < 0) 498 if (ret < 0)
501 goto end; 499 goto end;
502 } 500 }
503 501
504 if (lr->end == INT_MAX) 502 if (lr->end == INT_MAX)
505 lr->end = l + NR_ADDITIONAL_LINES; 503 lr->end = l + NR_ADDITIONAL_LINES;
506 while (l <= lr->end) { 504 while (l <= lr->end) {
507 ret = show_one_line_or_eof(fp, l++ - lr->offset); 505 ret = show_one_line_or_eof(fp, l++ - lr->offset);
508 if (ret <= 0) 506 if (ret <= 0)
509 break; 507 break;
510 } 508 }
511 end: 509 end:
512 fclose(fp); 510 fclose(fp);
513 return ret; 511 return ret;
514 } 512 }
515 513
516 static int show_available_vars_at(struct debuginfo *dinfo, 514 static int show_available_vars_at(struct debuginfo *dinfo,
517 struct perf_probe_event *pev, 515 struct perf_probe_event *pev,
518 int max_vls, struct strfilter *_filter, 516 int max_vls, struct strfilter *_filter,
519 bool externs) 517 bool externs)
520 { 518 {
521 char *buf; 519 char *buf;
522 int ret, i, nvars; 520 int ret, i, nvars;
523 struct str_node *node; 521 struct str_node *node;
524 struct variable_list *vls = NULL, *vl; 522 struct variable_list *vls = NULL, *vl;
525 const char *var; 523 const char *var;
526 524
527 buf = synthesize_perf_probe_point(&pev->point); 525 buf = synthesize_perf_probe_point(&pev->point);
528 if (!buf) 526 if (!buf)
529 return -EINVAL; 527 return -EINVAL;
530 pr_debug("Searching variables at %s\n", buf); 528 pr_debug("Searching variables at %s\n", buf);
531 529
532 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls, 530 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
533 max_vls, externs); 531 max_vls, externs);
534 if (ret <= 0) { 532 if (ret <= 0) {
535 pr_err("Failed to find variables at %s (%d)\n", buf, ret); 533 pr_err("Failed to find variables at %s (%d)\n", buf, ret);
536 goto end; 534 goto end;
537 } 535 }
538 /* Some variables are found */ 536 /* Some variables are found */
539 fprintf(stdout, "Available variables at %s\n", buf); 537 fprintf(stdout, "Available variables at %s\n", buf);
540 for (i = 0; i < ret; i++) { 538 for (i = 0; i < ret; i++) {
541 vl = &vls[i]; 539 vl = &vls[i];
542 /* 540 /*
543 * A probe point might be converted to 541 * A probe point might be converted to
544 * several trace points. 542 * several trace points.
545 */ 543 */
546 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, 544 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
547 vl->point.offset); 545 vl->point.offset);
548 free(vl->point.symbol); 546 free(vl->point.symbol);
549 nvars = 0; 547 nvars = 0;
550 if (vl->vars) { 548 if (vl->vars) {
551 strlist__for_each(node, vl->vars) { 549 strlist__for_each(node, vl->vars) {
552 var = strchr(node->s, '\t') + 1; 550 var = strchr(node->s, '\t') + 1;
553 if (strfilter__compare(_filter, var)) { 551 if (strfilter__compare(_filter, var)) {
554 fprintf(stdout, "\t\t%s\n", node->s); 552 fprintf(stdout, "\t\t%s\n", node->s);
555 nvars++; 553 nvars++;
556 } 554 }
557 } 555 }
558 strlist__delete(vl->vars); 556 strlist__delete(vl->vars);
559 } 557 }
560 if (nvars == 0) 558 if (nvars == 0)
561 fprintf(stdout, "\t\t(No matched variables)\n"); 559 fprintf(stdout, "\t\t(No matched variables)\n");
562 } 560 }
563 free(vls); 561 free(vls);
564 end: 562 end:
565 free(buf); 563 free(buf);
566 return ret; 564 return ret;
567 } 565 }
568 566
569 /* Show available variables on given probe point */ 567 /* Show available variables on given probe point */
570 int show_available_vars(struct perf_probe_event *pevs, int npevs, 568 int show_available_vars(struct perf_probe_event *pevs, int npevs,
571 int max_vls, const char *module, 569 int max_vls, const char *module,
572 struct strfilter *_filter, bool externs) 570 struct strfilter *_filter, bool externs)
573 { 571 {
574 int i, ret = 0; 572 int i, ret = 0;
575 struct debuginfo *dinfo; 573 struct debuginfo *dinfo;
576 574
577 ret = init_vmlinux(); 575 ret = init_vmlinux();
578 if (ret < 0) 576 if (ret < 0)
579 return ret; 577 return ret;
580 578
581 dinfo = open_debuginfo(module); 579 dinfo = open_debuginfo(module);
582 if (!dinfo) { 580 if (!dinfo) {
583 pr_warning("Failed to open debuginfo file.\n"); 581 pr_warning("Failed to open debuginfo file.\n");
584 return -ENOENT; 582 return -ENOENT;
585 } 583 }
586 584
587 setup_pager(); 585 setup_pager();
588 586
589 for (i = 0; i < npevs && ret >= 0; i++) 587 for (i = 0; i < npevs && ret >= 0; i++)
590 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter, 588 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
591 externs); 589 externs);
592 590
593 debuginfo__delete(dinfo); 591 debuginfo__delete(dinfo);
594 return ret; 592 return ret;
595 } 593 }
596 594
597 #else /* !DWARF_SUPPORT */ 595 #else /* !DWARF_SUPPORT */
598 596
599 static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 597 static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
600 struct perf_probe_point *pp) 598 struct perf_probe_point *pp)
601 { 599 {
602 struct symbol *sym; 600 struct symbol *sym;
603 601
604 sym = __find_kernel_function_by_name(tp->symbol, NULL); 602 sym = __find_kernel_function_by_name(tp->symbol, NULL);
605 if (!sym) { 603 if (!sym) {
606 pr_err("Failed to find symbol %s in kernel.\n", tp->symbol); 604 pr_err("Failed to find symbol %s in kernel.\n", tp->symbol);
607 return -ENOENT; 605 return -ENOENT;
608 } 606 }
609 pp->function = strdup(tp->symbol); 607 pp->function = strdup(tp->symbol);
610 if (pp->function == NULL) 608 if (pp->function == NULL)
611 return -ENOMEM; 609 return -ENOMEM;
612 pp->offset = tp->offset; 610 pp->offset = tp->offset;
613 pp->retprobe = tp->retprobe; 611 pp->retprobe = tp->retprobe;
614 612
615 return 0; 613 return 0;
616 } 614 }
617 615
618 static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 616 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
619 struct probe_trace_event **tevs __unused, 617 struct probe_trace_event **tevs __unused,
620 int max_tevs __unused, const char *mod __unused) 618 int max_tevs __unused, const char *mod __unused)
621 { 619 {
622 if (perf_probe_event_need_dwarf(pev)) { 620 if (perf_probe_event_need_dwarf(pev)) {
623 pr_warning("Debuginfo-analysis is not supported.\n"); 621 pr_warning("Debuginfo-analysis is not supported.\n");
624 return -ENOSYS; 622 return -ENOSYS;
625 } 623 }
626 return 0; 624 return 0;
627 } 625 }
628 626
629 int show_line_range(struct line_range *lr __unused, const char *module __unused) 627 int show_line_range(struct line_range *lr __unused, const char *module __unused)
630 { 628 {
631 pr_warning("Debuginfo-analysis is not supported.\n"); 629 pr_warning("Debuginfo-analysis is not supported.\n");
632 return -ENOSYS; 630 return -ENOSYS;
633 } 631 }
634 632
635 int show_available_vars(struct perf_probe_event *pevs __unused, 633 int show_available_vars(struct perf_probe_event *pevs __unused,
636 int npevs __unused, int max_vls __unused, 634 int npevs __unused, int max_vls __unused,
637 const char *module __unused, 635 const char *module __unused,
638 struct strfilter *filter __unused, 636 struct strfilter *filter __unused,
639 bool externs __unused) 637 bool externs __unused)
640 { 638 {
641 pr_warning("Debuginfo-analysis is not supported.\n"); 639 pr_warning("Debuginfo-analysis is not supported.\n");
642 return -ENOSYS; 640 return -ENOSYS;
643 } 641 }
644 #endif 642 #endif
645 643
646 static int parse_line_num(char **ptr, int *val, const char *what) 644 static int parse_line_num(char **ptr, int *val, const char *what)
647 { 645 {
648 const char *start = *ptr; 646 const char *start = *ptr;
649 647
650 errno = 0; 648 errno = 0;
651 *val = strtol(*ptr, ptr, 0); 649 *val = strtol(*ptr, ptr, 0);
652 if (errno || *ptr == start) { 650 if (errno || *ptr == start) {
653 semantic_error("'%s' is not a valid number.\n", what); 651 semantic_error("'%s' is not a valid number.\n", what);
654 return -EINVAL; 652 return -EINVAL;
655 } 653 }
656 return 0; 654 return 0;
657 } 655 }
658 656
659 /* 657 /*
660 * Stuff 'lr' according to the line range described by 'arg'. 658 * Stuff 'lr' according to the line range described by 'arg'.
661 * The line range syntax is described by: 659 * The line range syntax is described by:
662 * 660 *
663 * SRC[:SLN[+NUM|-ELN]] 661 * SRC[:SLN[+NUM|-ELN]]
664 * FNC[@SRC][:SLN[+NUM|-ELN]] 662 * FNC[@SRC][:SLN[+NUM|-ELN]]
665 */ 663 */
666 int parse_line_range_desc(const char *arg, struct line_range *lr) 664 int parse_line_range_desc(const char *arg, struct line_range *lr)
667 { 665 {
668 char *range, *file, *name = strdup(arg); 666 char *range, *file, *name = strdup(arg);
669 int err; 667 int err;
670 668
671 if (!name) 669 if (!name)
672 return -ENOMEM; 670 return -ENOMEM;
673 671
674 lr->start = 0; 672 lr->start = 0;
675 lr->end = INT_MAX; 673 lr->end = INT_MAX;
676 674
677 range = strchr(name, ':'); 675 range = strchr(name, ':');
678 if (range) { 676 if (range) {
679 *range++ = '\0'; 677 *range++ = '\0';
680 678
681 err = parse_line_num(&range, &lr->start, "start line"); 679 err = parse_line_num(&range, &lr->start, "start line");
682 if (err) 680 if (err)
683 goto err; 681 goto err;
684 682
685 if (*range == '+' || *range == '-') { 683 if (*range == '+' || *range == '-') {
686 const char c = *range++; 684 const char c = *range++;
687 685
688 err = parse_line_num(&range, &lr->end, "end line"); 686 err = parse_line_num(&range, &lr->end, "end line");
689 if (err) 687 if (err)
690 goto err; 688 goto err;
691 689
692 if (c == '+') { 690 if (c == '+') {
693 lr->end += lr->start; 691 lr->end += lr->start;
694 /* 692 /*
695 * Adjust the number of lines here. 693 * Adjust the number of lines here.
696 * If the number of lines == 1, the 694 * If the number of lines == 1, the
697 * the end of line should be equal to 695 * the end of line should be equal to
698 * the start of line. 696 * the start of line.
699 */ 697 */
700 lr->end--; 698 lr->end--;
701 } 699 }
702 } 700 }
703 701
704 pr_debug("Line range is %d to %d\n", lr->start, lr->end); 702 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
705 703
706 err = -EINVAL; 704 err = -EINVAL;
707 if (lr->start > lr->end) { 705 if (lr->start > lr->end) {
708 semantic_error("Start line must be smaller" 706 semantic_error("Start line must be smaller"
709 " than end line.\n"); 707 " than end line.\n");
710 goto err; 708 goto err;
711 } 709 }
712 if (*range != '\0') { 710 if (*range != '\0') {
713 semantic_error("Tailing with invalid str '%s'.\n", range); 711 semantic_error("Tailing with invalid str '%s'.\n", range);
714 goto err; 712 goto err;
715 } 713 }
716 } 714 }
717 715
718 file = strchr(name, '@'); 716 file = strchr(name, '@');
719 if (file) { 717 if (file) {
720 *file = '\0'; 718 *file = '\0';
721 lr->file = strdup(++file); 719 lr->file = strdup(++file);
722 if (lr->file == NULL) { 720 if (lr->file == NULL) {
723 err = -ENOMEM; 721 err = -ENOMEM;
724 goto err; 722 goto err;
725 } 723 }
726 lr->function = name; 724 lr->function = name;
727 } else if (strchr(name, '.')) 725 } else if (strchr(name, '.'))
728 lr->file = name; 726 lr->file = name;
729 else 727 else
730 lr->function = name; 728 lr->function = name;
731 729
732 return 0; 730 return 0;
733 err: 731 err:
734 free(name); 732 free(name);
735 return err; 733 return err;
736 } 734 }
737 735
738 /* Check the name is good for event/group */ 736 /* Check the name is good for event/group */
739 static bool check_event_name(const char *name) 737 static bool check_event_name(const char *name)
740 { 738 {
741 if (!isalpha(*name) && *name != '_') 739 if (!isalpha(*name) && *name != '_')
742 return false; 740 return false;
743 while (*++name != '\0') { 741 while (*++name != '\0') {
744 if (!isalpha(*name) && !isdigit(*name) && *name != '_') 742 if (!isalpha(*name) && !isdigit(*name) && *name != '_')
745 return false; 743 return false;
746 } 744 }
747 return true; 745 return true;
748 } 746 }
749 747
750 /* Parse probepoint definition. */ 748 /* Parse probepoint definition. */
751 static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 749 static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
752 { 750 {
753 struct perf_probe_point *pp = &pev->point; 751 struct perf_probe_point *pp = &pev->point;
754 char *ptr, *tmp; 752 char *ptr, *tmp;
755 char c, nc = 0; 753 char c, nc = 0;
756 /* 754 /*
757 * <Syntax> 755 * <Syntax>
758 * perf probe [EVENT=]SRC[:LN|;PTN] 756 * perf probe [EVENT=]SRC[:LN|;PTN]
759 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 757 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
760 * 758 *
761 * TODO:Group name support 759 * TODO:Group name support
762 */ 760 */
763 761
764 ptr = strpbrk(arg, ";=@+%"); 762 ptr = strpbrk(arg, ";=@+%");
765 if (ptr && *ptr == '=') { /* Event name */ 763 if (ptr && *ptr == '=') { /* Event name */
766 *ptr = '\0'; 764 *ptr = '\0';
767 tmp = ptr + 1; 765 tmp = ptr + 1;
768 if (strchr(arg, ':')) { 766 if (strchr(arg, ':')) {
769 semantic_error("Group name is not supported yet.\n"); 767 semantic_error("Group name is not supported yet.\n");
770 return -ENOTSUP; 768 return -ENOTSUP;
771 } 769 }
772 if (!check_event_name(arg)) { 770 if (!check_event_name(arg)) {
773 semantic_error("%s is bad for event name -it must " 771 semantic_error("%s is bad for event name -it must "
774 "follow C symbol-naming rule.\n", arg); 772 "follow C symbol-naming rule.\n", arg);
775 return -EINVAL; 773 return -EINVAL;
776 } 774 }
777 pev->event = strdup(arg); 775 pev->event = strdup(arg);
778 if (pev->event == NULL) 776 if (pev->event == NULL)
779 return -ENOMEM; 777 return -ENOMEM;
780 pev->group = NULL; 778 pev->group = NULL;
781 arg = tmp; 779 arg = tmp;
782 } 780 }
783 781
784 ptr = strpbrk(arg, ";:+@%"); 782 ptr = strpbrk(arg, ";:+@%");
785 if (ptr) { 783 if (ptr) {
786 nc = *ptr; 784 nc = *ptr;
787 *ptr++ = '\0'; 785 *ptr++ = '\0';
788 } 786 }
789 787
790 tmp = strdup(arg); 788 tmp = strdup(arg);
791 if (tmp == NULL) 789 if (tmp == NULL)
792 return -ENOMEM; 790 return -ENOMEM;
793 791
794 /* Check arg is function or file and copy it */ 792 /* Check arg is function or file and copy it */
795 if (strchr(tmp, '.')) /* File */ 793 if (strchr(tmp, '.')) /* File */
796 pp->file = tmp; 794 pp->file = tmp;
797 else /* Function */ 795 else /* Function */
798 pp->function = tmp; 796 pp->function = tmp;
799 797
800 /* Parse other options */ 798 /* Parse other options */
801 while (ptr) { 799 while (ptr) {
802 arg = ptr; 800 arg = ptr;
803 c = nc; 801 c = nc;
804 if (c == ';') { /* Lazy pattern must be the last part */ 802 if (c == ';') { /* Lazy pattern must be the last part */
805 pp->lazy_line = strdup(arg); 803 pp->lazy_line = strdup(arg);
806 if (pp->lazy_line == NULL) 804 if (pp->lazy_line == NULL)
807 return -ENOMEM; 805 return -ENOMEM;
808 break; 806 break;
809 } 807 }
810 ptr = strpbrk(arg, ";:+@%"); 808 ptr = strpbrk(arg, ";:+@%");
811 if (ptr) { 809 if (ptr) {
812 nc = *ptr; 810 nc = *ptr;
813 *ptr++ = '\0'; 811 *ptr++ = '\0';
814 } 812 }
815 switch (c) { 813 switch (c) {
816 case ':': /* Line number */ 814 case ':': /* Line number */
817 pp->line = strtoul(arg, &tmp, 0); 815 pp->line = strtoul(arg, &tmp, 0);
818 if (*tmp != '\0') { 816 if (*tmp != '\0') {
819 semantic_error("There is non-digit char" 817 semantic_error("There is non-digit char"
820 " in line number.\n"); 818 " in line number.\n");
821 return -EINVAL; 819 return -EINVAL;
822 } 820 }
823 break; 821 break;
824 case '+': /* Byte offset from a symbol */ 822 case '+': /* Byte offset from a symbol */
825 pp->offset = strtoul(arg, &tmp, 0); 823 pp->offset = strtoul(arg, &tmp, 0);
826 if (*tmp != '\0') { 824 if (*tmp != '\0') {
827 semantic_error("There is non-digit character" 825 semantic_error("There is non-digit character"
828 " in offset.\n"); 826 " in offset.\n");
829 return -EINVAL; 827 return -EINVAL;
830 } 828 }
831 break; 829 break;
832 case '@': /* File name */ 830 case '@': /* File name */
833 if (pp->file) { 831 if (pp->file) {
834 semantic_error("SRC@SRC is not allowed.\n"); 832 semantic_error("SRC@SRC is not allowed.\n");
835 return -EINVAL; 833 return -EINVAL;
836 } 834 }
837 pp->file = strdup(arg); 835 pp->file = strdup(arg);
838 if (pp->file == NULL) 836 if (pp->file == NULL)
839 return -ENOMEM; 837 return -ENOMEM;
840 break; 838 break;
841 case '%': /* Probe places */ 839 case '%': /* Probe places */
842 if (strcmp(arg, "return") == 0) { 840 if (strcmp(arg, "return") == 0) {
843 pp->retprobe = 1; 841 pp->retprobe = 1;
844 } else { /* Others not supported yet */ 842 } else { /* Others not supported yet */
845 semantic_error("%%%s is not supported.\n", arg); 843 semantic_error("%%%s is not supported.\n", arg);
846 return -ENOTSUP; 844 return -ENOTSUP;
847 } 845 }
848 break; 846 break;
849 default: /* Buggy case */ 847 default: /* Buggy case */
850 pr_err("This program has a bug at %s:%d.\n", 848 pr_err("This program has a bug at %s:%d.\n",
851 __FILE__, __LINE__); 849 __FILE__, __LINE__);
852 return -ENOTSUP; 850 return -ENOTSUP;
853 break; 851 break;
854 } 852 }
855 } 853 }
856 854
857 /* Exclusion check */ 855 /* Exclusion check */
858 if (pp->lazy_line && pp->line) { 856 if (pp->lazy_line && pp->line) {
859 semantic_error("Lazy pattern can't be used with" 857 semantic_error("Lazy pattern can't be used with"
860 " line number.\n"); 858 " line number.\n");
861 return -EINVAL; 859 return -EINVAL;
862 } 860 }
863 861
864 if (pp->lazy_line && pp->offset) { 862 if (pp->lazy_line && pp->offset) {
865 semantic_error("Lazy pattern can't be used with offset.\n"); 863 semantic_error("Lazy pattern can't be used with offset.\n");
866 return -EINVAL; 864 return -EINVAL;
867 } 865 }
868 866
869 if (pp->line && pp->offset) { 867 if (pp->line && pp->offset) {
870 semantic_error("Offset can't be used with line number.\n"); 868 semantic_error("Offset can't be used with line number.\n");
871 return -EINVAL; 869 return -EINVAL;
872 } 870 }
873 871
874 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 872 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
875 semantic_error("File always requires line number or " 873 semantic_error("File always requires line number or "
876 "lazy pattern.\n"); 874 "lazy pattern.\n");
877 return -EINVAL; 875 return -EINVAL;
878 } 876 }
879 877
880 if (pp->offset && !pp->function) { 878 if (pp->offset && !pp->function) {
881 semantic_error("Offset requires an entry function.\n"); 879 semantic_error("Offset requires an entry function.\n");
882 return -EINVAL; 880 return -EINVAL;
883 } 881 }
884 882
885 if (pp->retprobe && !pp->function) { 883 if (pp->retprobe && !pp->function) {
886 semantic_error("Return probe requires an entry function.\n"); 884 semantic_error("Return probe requires an entry function.\n");
887 return -EINVAL; 885 return -EINVAL;
888 } 886 }
889 887
890 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 888 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
891 semantic_error("Offset/Line/Lazy pattern can't be used with " 889 semantic_error("Offset/Line/Lazy pattern can't be used with "
892 "return probe.\n"); 890 "return probe.\n");
893 return -EINVAL; 891 return -EINVAL;
894 } 892 }
895 893
896 pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n", 894 pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
897 pp->function, pp->file, pp->line, pp->offset, pp->retprobe, 895 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
898 pp->lazy_line); 896 pp->lazy_line);
899 return 0; 897 return 0;
900 } 898 }
901 899
902 /* Parse perf-probe event argument */ 900 /* Parse perf-probe event argument */
903 static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) 901 static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
904 { 902 {
905 char *tmp, *goodname; 903 char *tmp, *goodname;
906 struct perf_probe_arg_field **fieldp; 904 struct perf_probe_arg_field **fieldp;
907 905
908 pr_debug("parsing arg: %s into ", str); 906 pr_debug("parsing arg: %s into ", str);
909 907
910 tmp = strchr(str, '='); 908 tmp = strchr(str, '=');
911 if (tmp) { 909 if (tmp) {
912 arg->name = strndup(str, tmp - str); 910 arg->name = strndup(str, tmp - str);
913 if (arg->name == NULL) 911 if (arg->name == NULL)
914 return -ENOMEM; 912 return -ENOMEM;
915 pr_debug("name:%s ", arg->name); 913 pr_debug("name:%s ", arg->name);
916 str = tmp + 1; 914 str = tmp + 1;
917 } 915 }
918 916
919 tmp = strchr(str, ':'); 917 tmp = strchr(str, ':');
920 if (tmp) { /* Type setting */ 918 if (tmp) { /* Type setting */
921 *tmp = '\0'; 919 *tmp = '\0';
922 arg->type = strdup(tmp + 1); 920 arg->type = strdup(tmp + 1);
923 if (arg->type == NULL) 921 if (arg->type == NULL)
924 return -ENOMEM; 922 return -ENOMEM;
925 pr_debug("type:%s ", arg->type); 923 pr_debug("type:%s ", arg->type);
926 } 924 }
927 925
928 tmp = strpbrk(str, "-.["); 926 tmp = strpbrk(str, "-.[");
929 if (!is_c_varname(str) || !tmp) { 927 if (!is_c_varname(str) || !tmp) {
930 /* A variable, register, symbol or special value */ 928 /* A variable, register, symbol or special value */
931 arg->var = strdup(str); 929 arg->var = strdup(str);
932 if (arg->var == NULL) 930 if (arg->var == NULL)
933 return -ENOMEM; 931 return -ENOMEM;
934 pr_debug("%s\n", arg->var); 932 pr_debug("%s\n", arg->var);
935 return 0; 933 return 0;
936 } 934 }
937 935
938 /* Structure fields or array element */ 936 /* Structure fields or array element */
939 arg->var = strndup(str, tmp - str); 937 arg->var = strndup(str, tmp - str);
940 if (arg->var == NULL) 938 if (arg->var == NULL)
941 return -ENOMEM; 939 return -ENOMEM;
942 goodname = arg->var; 940 goodname = arg->var;
943 pr_debug("%s, ", arg->var); 941 pr_debug("%s, ", arg->var);
944 fieldp = &arg->field; 942 fieldp = &arg->field;
945 943
946 do { 944 do {
947 *fieldp = zalloc(sizeof(struct perf_probe_arg_field)); 945 *fieldp = zalloc(sizeof(struct perf_probe_arg_field));
948 if (*fieldp == NULL) 946 if (*fieldp == NULL)
949 return -ENOMEM; 947 return -ENOMEM;
950 if (*tmp == '[') { /* Array */ 948 if (*tmp == '[') { /* Array */
951 str = tmp; 949 str = tmp;
952 (*fieldp)->index = strtol(str + 1, &tmp, 0); 950 (*fieldp)->index = strtol(str + 1, &tmp, 0);
953 (*fieldp)->ref = true; 951 (*fieldp)->ref = true;
954 if (*tmp != ']' || tmp == str + 1) { 952 if (*tmp != ']' || tmp == str + 1) {
955 semantic_error("Array index must be a" 953 semantic_error("Array index must be a"
956 " number.\n"); 954 " number.\n");
957 return -EINVAL; 955 return -EINVAL;
958 } 956 }
959 tmp++; 957 tmp++;
960 if (*tmp == '\0') 958 if (*tmp == '\0')
961 tmp = NULL; 959 tmp = NULL;
962 } else { /* Structure */ 960 } else { /* Structure */
963 if (*tmp == '.') { 961 if (*tmp == '.') {
964 str = tmp + 1; 962 str = tmp + 1;
965 (*fieldp)->ref = false; 963 (*fieldp)->ref = false;
966 } else if (tmp[1] == '>') { 964 } else if (tmp[1] == '>') {
967 str = tmp + 2; 965 str = tmp + 2;
968 (*fieldp)->ref = true; 966 (*fieldp)->ref = true;
969 } else { 967 } else {
970 semantic_error("Argument parse error: %s\n", 968 semantic_error("Argument parse error: %s\n",
971 str); 969 str);
972 return -EINVAL; 970 return -EINVAL;
973 } 971 }
974 tmp = strpbrk(str, "-.["); 972 tmp = strpbrk(str, "-.[");
975 } 973 }
976 if (tmp) { 974 if (tmp) {
977 (*fieldp)->name = strndup(str, tmp - str); 975 (*fieldp)->name = strndup(str, tmp - str);
978 if ((*fieldp)->name == NULL) 976 if ((*fieldp)->name == NULL)
979 return -ENOMEM; 977 return -ENOMEM;
980 if (*str != '[') 978 if (*str != '[')
981 goodname = (*fieldp)->name; 979 goodname = (*fieldp)->name;
982 pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref); 980 pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
983 fieldp = &(*fieldp)->next; 981 fieldp = &(*fieldp)->next;
984 } 982 }
985 } while (tmp); 983 } while (tmp);
986 (*fieldp)->name = strdup(str); 984 (*fieldp)->name = strdup(str);
987 if ((*fieldp)->name == NULL) 985 if ((*fieldp)->name == NULL)
988 return -ENOMEM; 986 return -ENOMEM;
989 if (*str != '[') 987 if (*str != '[')
990 goodname = (*fieldp)->name; 988 goodname = (*fieldp)->name;
991 pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref); 989 pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
992 990
993 /* If no name is specified, set the last field name (not array index)*/ 991 /* If no name is specified, set the last field name (not array index)*/
994 if (!arg->name) { 992 if (!arg->name) {
995 arg->name = strdup(goodname); 993 arg->name = strdup(goodname);
996 if (arg->name == NULL) 994 if (arg->name == NULL)
997 return -ENOMEM; 995 return -ENOMEM;
998 } 996 }
999 return 0; 997 return 0;
1000 } 998 }
1001 999
1002 /* Parse perf-probe event command */ 1000 /* Parse perf-probe event command */
1003 int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) 1001 int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
1004 { 1002 {
1005 char **argv; 1003 char **argv;
1006 int argc, i, ret = 0; 1004 int argc, i, ret = 0;
1007 1005
1008 argv = argv_split(cmd, &argc); 1006 argv = argv_split(cmd, &argc);
1009 if (!argv) { 1007 if (!argv) {
1010 pr_debug("Failed to split arguments.\n"); 1008 pr_debug("Failed to split arguments.\n");
1011 return -ENOMEM; 1009 return -ENOMEM;
1012 } 1010 }
1013 if (argc - 1 > MAX_PROBE_ARGS) { 1011 if (argc - 1 > MAX_PROBE_ARGS) {
1014 semantic_error("Too many probe arguments (%d).\n", argc - 1); 1012 semantic_error("Too many probe arguments (%d).\n", argc - 1);
1015 ret = -ERANGE; 1013 ret = -ERANGE;
1016 goto out; 1014 goto out;
1017 } 1015 }
1018 /* Parse probe point */ 1016 /* Parse probe point */
1019 ret = parse_perf_probe_point(argv[0], pev); 1017 ret = parse_perf_probe_point(argv[0], pev);
1020 if (ret < 0) 1018 if (ret < 0)
1021 goto out; 1019 goto out;
1022 1020
1023 /* Copy arguments and ensure return probe has no C argument */ 1021 /* Copy arguments and ensure return probe has no C argument */
1024 pev->nargs = argc - 1; 1022 pev->nargs = argc - 1;
1025 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 1023 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
1026 if (pev->args == NULL) { 1024 if (pev->args == NULL) {
1027 ret = -ENOMEM; 1025 ret = -ENOMEM;
1028 goto out; 1026 goto out;
1029 } 1027 }
1030 for (i = 0; i < pev->nargs && ret >= 0; i++) { 1028 for (i = 0; i < pev->nargs && ret >= 0; i++) {
1031 ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]); 1029 ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
1032 if (ret >= 0 && 1030 if (ret >= 0 &&
1033 is_c_varname(pev->args[i].var) && pev->point.retprobe) { 1031 is_c_varname(pev->args[i].var) && pev->point.retprobe) {
1034 semantic_error("You can't specify local variable for" 1032 semantic_error("You can't specify local variable for"
1035 " kretprobe.\n"); 1033 " kretprobe.\n");
1036 ret = -EINVAL; 1034 ret = -EINVAL;
1037 } 1035 }
1038 } 1036 }
1039 out: 1037 out:
1040 argv_free(argv); 1038 argv_free(argv);
1041 1039
1042 return ret; 1040 return ret;
1043 } 1041 }
1044 1042
1045 /* Return true if this perf_probe_event requires debuginfo */ 1043 /* Return true if this perf_probe_event requires debuginfo */
1046 bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) 1044 bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
1047 { 1045 {
1048 int i; 1046 int i;
1049 1047
1050 if (pev->point.file || pev->point.line || pev->point.lazy_line) 1048 if (pev->point.file || pev->point.line || pev->point.lazy_line)
1051 return true; 1049 return true;
1052 1050
1053 for (i = 0; i < pev->nargs; i++) 1051 for (i = 0; i < pev->nargs; i++)
1054 if (is_c_varname(pev->args[i].var)) 1052 if (is_c_varname(pev->args[i].var))
1055 return true; 1053 return true;
1056 1054
1057 return false; 1055 return false;
1058 } 1056 }
1059 1057
1060 /* Parse probe_events event into struct probe_point */ 1058 /* Parse probe_events event into struct probe_point */
1061 static int parse_probe_trace_command(const char *cmd, 1059 static int parse_probe_trace_command(const char *cmd,
1062 struct probe_trace_event *tev) 1060 struct probe_trace_event *tev)
1063 { 1061 {
1064 struct probe_trace_point *tp = &tev->point; 1062 struct probe_trace_point *tp = &tev->point;
1065 char pr; 1063 char pr;
1066 char *p; 1064 char *p;
1067 int ret, i, argc; 1065 int ret, i, argc;
1068 char **argv; 1066 char **argv;
1069 1067
1070 pr_debug("Parsing probe_events: %s\n", cmd); 1068 pr_debug("Parsing probe_events: %s\n", cmd);
1071 argv = argv_split(cmd, &argc); 1069 argv = argv_split(cmd, &argc);
1072 if (!argv) { 1070 if (!argv) {
1073 pr_debug("Failed to split arguments.\n"); 1071 pr_debug("Failed to split arguments.\n");
1074 return -ENOMEM; 1072 return -ENOMEM;
1075 } 1073 }
1076 if (argc < 2) { 1074 if (argc < 2) {
1077 semantic_error("Too few probe arguments.\n"); 1075 semantic_error("Too few probe arguments.\n");
1078 ret = -ERANGE; 1076 ret = -ERANGE;
1079 goto out; 1077 goto out;
1080 } 1078 }
1081 1079
1082 /* Scan event and group name. */ 1080 /* Scan event and group name. */
1083 ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", 1081 ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
1084 &pr, (float *)(void *)&tev->group, 1082 &pr, (float *)(void *)&tev->group,
1085 (float *)(void *)&tev->event); 1083 (float *)(void *)&tev->event);
1086 if (ret != 3) { 1084 if (ret != 3) {
1087 semantic_error("Failed to parse event name: %s\n", argv[0]); 1085 semantic_error("Failed to parse event name: %s\n", argv[0]);
1088 ret = -EINVAL; 1086 ret = -EINVAL;
1089 goto out; 1087 goto out;
1090 } 1088 }
1091 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); 1089 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
1092 1090
1093 tp->retprobe = (pr == 'r'); 1091 tp->retprobe = (pr == 'r');
1094 1092
1095 /* Scan module name(if there), function name and offset */ 1093 /* Scan module name(if there), function name and offset */
1096 p = strchr(argv[1], ':'); 1094 p = strchr(argv[1], ':');
1097 if (p) { 1095 if (p) {
1098 tp->module = strndup(argv[1], p - argv[1]); 1096 tp->module = strndup(argv[1], p - argv[1]);
1099 p++; 1097 p++;
1100 } else 1098 } else
1101 p = argv[1]; 1099 p = argv[1];
1102 ret = sscanf(p, "%a[^+]+%lu", (float *)(void *)&tp->symbol, 1100 ret = sscanf(p, "%a[^+]+%lu", (float *)(void *)&tp->symbol,
1103 &tp->offset); 1101 &tp->offset);
1104 if (ret == 1) 1102 if (ret == 1)
1105 tp->offset = 0; 1103 tp->offset = 0;
1106 1104
1107 tev->nargs = argc - 2; 1105 tev->nargs = argc - 2;
1108 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1106 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1109 if (tev->args == NULL) { 1107 if (tev->args == NULL) {
1110 ret = -ENOMEM; 1108 ret = -ENOMEM;
1111 goto out; 1109 goto out;
1112 } 1110 }
1113 for (i = 0; i < tev->nargs; i++) { 1111 for (i = 0; i < tev->nargs; i++) {
1114 p = strchr(argv[i + 2], '='); 1112 p = strchr(argv[i + 2], '=');
1115 if (p) /* We don't need which register is assigned. */ 1113 if (p) /* We don't need which register is assigned. */
1116 *p++ = '\0'; 1114 *p++ = '\0';
1117 else 1115 else
1118 p = argv[i + 2]; 1116 p = argv[i + 2];
1119 tev->args[i].name = strdup(argv[i + 2]); 1117 tev->args[i].name = strdup(argv[i + 2]);
1120 /* TODO: parse regs and offset */ 1118 /* TODO: parse regs and offset */
1121 tev->args[i].value = strdup(p); 1119 tev->args[i].value = strdup(p);
1122 if (tev->args[i].name == NULL || tev->args[i].value == NULL) { 1120 if (tev->args[i].name == NULL || tev->args[i].value == NULL) {
1123 ret = -ENOMEM; 1121 ret = -ENOMEM;
1124 goto out; 1122 goto out;
1125 } 1123 }
1126 } 1124 }
1127 ret = 0; 1125 ret = 0;
1128 out: 1126 out:
1129 argv_free(argv); 1127 argv_free(argv);
1130 return ret; 1128 return ret;
1131 } 1129 }
1132 1130
1133 /* Compose only probe arg */ 1131 /* Compose only probe arg */
1134 int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) 1132 int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
1135 { 1133 {
1136 struct perf_probe_arg_field *field = pa->field; 1134 struct perf_probe_arg_field *field = pa->field;
1137 int ret; 1135 int ret;
1138 char *tmp = buf; 1136 char *tmp = buf;
1139 1137
1140 if (pa->name && pa->var) 1138 if (pa->name && pa->var)
1141 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var); 1139 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
1142 else 1140 else
1143 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var); 1141 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
1144 if (ret <= 0) 1142 if (ret <= 0)
1145 goto error; 1143 goto error;
1146 tmp += ret; 1144 tmp += ret;
1147 len -= ret; 1145 len -= ret;
1148 1146
1149 while (field) { 1147 while (field) {
1150 if (field->name[0] == '[') 1148 if (field->name[0] == '[')
1151 ret = e_snprintf(tmp, len, "%s", field->name); 1149 ret = e_snprintf(tmp, len, "%s", field->name);
1152 else 1150 else
1153 ret = e_snprintf(tmp, len, "%s%s", 1151 ret = e_snprintf(tmp, len, "%s%s",
1154 field->ref ? "->" : ".", field->name); 1152 field->ref ? "->" : ".", field->name);
1155 if (ret <= 0) 1153 if (ret <= 0)
1156 goto error; 1154 goto error;
1157 tmp += ret; 1155 tmp += ret;
1158 len -= ret; 1156 len -= ret;
1159 field = field->next; 1157 field = field->next;
1160 } 1158 }
1161 1159
1162 if (pa->type) { 1160 if (pa->type) {
1163 ret = e_snprintf(tmp, len, ":%s", pa->type); 1161 ret = e_snprintf(tmp, len, ":%s", pa->type);
1164 if (ret <= 0) 1162 if (ret <= 0)
1165 goto error; 1163 goto error;
1166 tmp += ret; 1164 tmp += ret;
1167 len -= ret; 1165 len -= ret;
1168 } 1166 }
1169 1167
1170 return tmp - buf; 1168 return tmp - buf;
1171 error: 1169 error:
1172 pr_debug("Failed to synthesize perf probe argument: %s\n", 1170 pr_debug("Failed to synthesize perf probe argument: %s\n",
1173 strerror(-ret)); 1171 strerror(-ret));
1174 return ret; 1172 return ret;
1175 } 1173 }
1176 1174
1177 /* Compose only probe point (not argument) */ 1175 /* Compose only probe point (not argument) */
1178 static char *synthesize_perf_probe_point(struct perf_probe_point *pp) 1176 static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1179 { 1177 {
1180 char *buf, *tmp; 1178 char *buf, *tmp;
1181 char offs[32] = "", line[32] = "", file[32] = ""; 1179 char offs[32] = "", line[32] = "", file[32] = "";
1182 int ret, len; 1180 int ret, len;
1183 1181
1184 buf = zalloc(MAX_CMDLEN); 1182 buf = zalloc(MAX_CMDLEN);
1185 if (buf == NULL) { 1183 if (buf == NULL) {
1186 ret = -ENOMEM; 1184 ret = -ENOMEM;
1187 goto error; 1185 goto error;
1188 } 1186 }
1189 if (pp->offset) { 1187 if (pp->offset) {
1190 ret = e_snprintf(offs, 32, "+%lu", pp->offset); 1188 ret = e_snprintf(offs, 32, "+%lu", pp->offset);
1191 if (ret <= 0) 1189 if (ret <= 0)
1192 goto error; 1190 goto error;
1193 } 1191 }
1194 if (pp->line) { 1192 if (pp->line) {
1195 ret = e_snprintf(line, 32, ":%d", pp->line); 1193 ret = e_snprintf(line, 32, ":%d", pp->line);
1196 if (ret <= 0) 1194 if (ret <= 0)
1197 goto error; 1195 goto error;
1198 } 1196 }
1199 if (pp->file) { 1197 if (pp->file) {
1200 tmp = pp->file; 1198 tmp = pp->file;
1201 len = strlen(tmp); 1199 len = strlen(tmp);
1202 if (len > 30) { 1200 if (len > 30) {
1203 tmp = strchr(pp->file + len - 30, '/'); 1201 tmp = strchr(pp->file + len - 30, '/');
1204 tmp = tmp ? tmp + 1 : pp->file + len - 30; 1202 tmp = tmp ? tmp + 1 : pp->file + len - 30;
1205 } 1203 }
1206 ret = e_snprintf(file, 32, "@%s", tmp); 1204 ret = e_snprintf(file, 32, "@%s", tmp);
1207 if (ret <= 0) 1205 if (ret <= 0)
1208 goto error; 1206 goto error;
1209 } 1207 }
1210 1208
1211 if (pp->function) 1209 if (pp->function)
1212 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function, 1210 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
1213 offs, pp->retprobe ? "%return" : "", line, 1211 offs, pp->retprobe ? "%return" : "", line,
1214 file); 1212 file);
1215 else 1213 else
1216 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line); 1214 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
1217 if (ret <= 0) 1215 if (ret <= 0)
1218 goto error; 1216 goto error;
1219 1217
1220 return buf; 1218 return buf;
1221 error: 1219 error:
1222 pr_debug("Failed to synthesize perf probe point: %s\n", 1220 pr_debug("Failed to synthesize perf probe point: %s\n",
1223 strerror(-ret)); 1221 strerror(-ret));
1224 if (buf) 1222 if (buf)
1225 free(buf); 1223 free(buf);
1226 return NULL; 1224 return NULL;
1227 } 1225 }
1228 1226
1229 #if 0 1227 #if 0
1230 char *synthesize_perf_probe_command(struct perf_probe_event *pev) 1228 char *synthesize_perf_probe_command(struct perf_probe_event *pev)
1231 { 1229 {
1232 char *buf; 1230 char *buf;
1233 int i, len, ret; 1231 int i, len, ret;
1234 1232
1235 buf = synthesize_perf_probe_point(&pev->point); 1233 buf = synthesize_perf_probe_point(&pev->point);
1236 if (!buf) 1234 if (!buf)
1237 return NULL; 1235 return NULL;
1238 1236
1239 len = strlen(buf); 1237 len = strlen(buf);
1240 for (i = 0; i < pev->nargs; i++) { 1238 for (i = 0; i < pev->nargs; i++) {
1241 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 1239 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
1242 pev->args[i].name); 1240 pev->args[i].name);
1243 if (ret <= 0) { 1241 if (ret <= 0) {
1244 free(buf); 1242 free(buf);
1245 return NULL; 1243 return NULL;
1246 } 1244 }
1247 len += ret; 1245 len += ret;
1248 } 1246 }
1249 1247
1250 return buf; 1248 return buf;
1251 } 1249 }
1252 #endif 1250 #endif
1253 1251
1254 static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, 1252 static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
1255 char **buf, size_t *buflen, 1253 char **buf, size_t *buflen,
1256 int depth) 1254 int depth)
1257 { 1255 {
1258 int ret; 1256 int ret;
1259 if (ref->next) { 1257 if (ref->next) {
1260 depth = __synthesize_probe_trace_arg_ref(ref->next, buf, 1258 depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
1261 buflen, depth + 1); 1259 buflen, depth + 1);
1262 if (depth < 0) 1260 if (depth < 0)
1263 goto out; 1261 goto out;
1264 } 1262 }
1265 1263
1266 ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset); 1264 ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
1267 if (ret < 0) 1265 if (ret < 0)
1268 depth = ret; 1266 depth = ret;
1269 else { 1267 else {
1270 *buf += ret; 1268 *buf += ret;
1271 *buflen -= ret; 1269 *buflen -= ret;
1272 } 1270 }
1273 out: 1271 out:
1274 return depth; 1272 return depth;
1275 1273
1276 } 1274 }
1277 1275
1278 static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, 1276 static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
1279 char *buf, size_t buflen) 1277 char *buf, size_t buflen)
1280 { 1278 {
1281 struct probe_trace_arg_ref *ref = arg->ref; 1279 struct probe_trace_arg_ref *ref = arg->ref;
1282 int ret, depth = 0; 1280 int ret, depth = 0;
1283 char *tmp = buf; 1281 char *tmp = buf;
1284 1282
1285 /* Argument name or separator */ 1283 /* Argument name or separator */
1286 if (arg->name) 1284 if (arg->name)
1287 ret = e_snprintf(buf, buflen, " %s=", arg->name); 1285 ret = e_snprintf(buf, buflen, " %s=", arg->name);
1288 else 1286 else
1289 ret = e_snprintf(buf, buflen, " "); 1287 ret = e_snprintf(buf, buflen, " ");
1290 if (ret < 0) 1288 if (ret < 0)
1291 return ret; 1289 return ret;
1292 buf += ret; 1290 buf += ret;
1293 buflen -= ret; 1291 buflen -= ret;
1294 1292
1295 /* Special case: @XXX */ 1293 /* Special case: @XXX */
1296 if (arg->value[0] == '@' && arg->ref) 1294 if (arg->value[0] == '@' && arg->ref)
1297 ref = ref->next; 1295 ref = ref->next;
1298 1296
1299 /* Dereferencing arguments */ 1297 /* Dereferencing arguments */
1300 if (ref) { 1298 if (ref) {
1301 depth = __synthesize_probe_trace_arg_ref(ref, &buf, 1299 depth = __synthesize_probe_trace_arg_ref(ref, &buf,
1302 &buflen, 1); 1300 &buflen, 1);
1303 if (depth < 0) 1301 if (depth < 0)
1304 return depth; 1302 return depth;
1305 } 1303 }
1306 1304
1307 /* Print argument value */ 1305 /* Print argument value */
1308 if (arg->value[0] == '@' && arg->ref) 1306 if (arg->value[0] == '@' && arg->ref)
1309 ret = e_snprintf(buf, buflen, "%s%+ld", arg->value, 1307 ret = e_snprintf(buf, buflen, "%s%+ld", arg->value,
1310 arg->ref->offset); 1308 arg->ref->offset);
1311 else 1309 else
1312 ret = e_snprintf(buf, buflen, "%s", arg->value); 1310 ret = e_snprintf(buf, buflen, "%s", arg->value);
1313 if (ret < 0) 1311 if (ret < 0)
1314 return ret; 1312 return ret;
1315 buf += ret; 1313 buf += ret;
1316 buflen -= ret; 1314 buflen -= ret;
1317 1315
1318 /* Closing */ 1316 /* Closing */
1319 while (depth--) { 1317 while (depth--) {
1320 ret = e_snprintf(buf, buflen, ")"); 1318 ret = e_snprintf(buf, buflen, ")");
1321 if (ret < 0) 1319 if (ret < 0)
1322 return ret; 1320 return ret;
1323 buf += ret; 1321 buf += ret;
1324 buflen -= ret; 1322 buflen -= ret;
1325 } 1323 }
1326 /* Print argument type */ 1324 /* Print argument type */
1327 if (arg->type) { 1325 if (arg->type) {
1328 ret = e_snprintf(buf, buflen, ":%s", arg->type); 1326 ret = e_snprintf(buf, buflen, ":%s", arg->type);
1329 if (ret <= 0) 1327 if (ret <= 0)
1330 return ret; 1328 return ret;
1331 buf += ret; 1329 buf += ret;
1332 } 1330 }
1333 1331
1334 return buf - tmp; 1332 return buf - tmp;
1335 } 1333 }
1336 1334
1337 char *synthesize_probe_trace_command(struct probe_trace_event *tev) 1335 char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1338 { 1336 {
1339 struct probe_trace_point *tp = &tev->point; 1337 struct probe_trace_point *tp = &tev->point;
1340 char *buf; 1338 char *buf;
1341 int i, len, ret; 1339 int i, len, ret;
1342 1340
1343 buf = zalloc(MAX_CMDLEN); 1341 buf = zalloc(MAX_CMDLEN);
1344 if (buf == NULL) 1342 if (buf == NULL)
1345 return NULL; 1343 return NULL;
1346 1344
1347 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu", 1345 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu",
1348 tp->retprobe ? 'r' : 'p', 1346 tp->retprobe ? 'r' : 'p',
1349 tev->group, tev->event, 1347 tev->group, tev->event,
1350 tp->module ?: "", tp->module ? ":" : "", 1348 tp->module ?: "", tp->module ? ":" : "",
1351 tp->symbol, tp->offset); 1349 tp->symbol, tp->offset);
1352 if (len <= 0) 1350 if (len <= 0)
1353 goto error; 1351 goto error;
1354 1352
1355 for (i = 0; i < tev->nargs; i++) { 1353 for (i = 0; i < tev->nargs; i++) {
1356 ret = synthesize_probe_trace_arg(&tev->args[i], buf + len, 1354 ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,
1357 MAX_CMDLEN - len); 1355 MAX_CMDLEN - len);
1358 if (ret <= 0) 1356 if (ret <= 0)
1359 goto error; 1357 goto error;
1360 len += ret; 1358 len += ret;
1361 } 1359 }
1362 1360
1363 return buf; 1361 return buf;
1364 error: 1362 error:
1365 free(buf); 1363 free(buf);
1366 return NULL; 1364 return NULL;
1367 } 1365 }
1368 1366
1369 static int convert_to_perf_probe_event(struct probe_trace_event *tev, 1367 static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1370 struct perf_probe_event *pev) 1368 struct perf_probe_event *pev)
1371 { 1369 {
1372 char buf[64] = ""; 1370 char buf[64] = "";
1373 int i, ret; 1371 int i, ret;
1374 1372
1375 /* Convert event/group name */ 1373 /* Convert event/group name */
1376 pev->event = strdup(tev->event); 1374 pev->event = strdup(tev->event);
1377 pev->group = strdup(tev->group); 1375 pev->group = strdup(tev->group);
1378 if (pev->event == NULL || pev->group == NULL) 1376 if (pev->event == NULL || pev->group == NULL)
1379 return -ENOMEM; 1377 return -ENOMEM;
1380 1378
1381 /* Convert trace_point to probe_point */ 1379 /* Convert trace_point to probe_point */
1382 ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point); 1380 ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point);
1383 if (ret < 0) 1381 if (ret < 0)
1384 return ret; 1382 return ret;
1385 1383
1386 /* Convert trace_arg to probe_arg */ 1384 /* Convert trace_arg to probe_arg */
1387 pev->nargs = tev->nargs; 1385 pev->nargs = tev->nargs;
1388 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 1386 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
1389 if (pev->args == NULL) 1387 if (pev->args == NULL)
1390 return -ENOMEM; 1388 return -ENOMEM;
1391 for (i = 0; i < tev->nargs && ret >= 0; i++) { 1389 for (i = 0; i < tev->nargs && ret >= 0; i++) {
1392 if (tev->args[i].name) 1390 if (tev->args[i].name)
1393 pev->args[i].name = strdup(tev->args[i].name); 1391 pev->args[i].name = strdup(tev->args[i].name);
1394 else { 1392 else {
1395 ret = synthesize_probe_trace_arg(&tev->args[i], 1393 ret = synthesize_probe_trace_arg(&tev->args[i],
1396 buf, 64); 1394 buf, 64);
1397 pev->args[i].name = strdup(buf); 1395 pev->args[i].name = strdup(buf);
1398 } 1396 }
1399 if (pev->args[i].name == NULL && ret >= 0) 1397 if (pev->args[i].name == NULL && ret >= 0)
1400 ret = -ENOMEM; 1398 ret = -ENOMEM;
1401 } 1399 }
1402 1400
1403 if (ret < 0) 1401 if (ret < 0)
1404 clear_perf_probe_event(pev); 1402 clear_perf_probe_event(pev);
1405 1403
1406 return ret; 1404 return ret;
1407 } 1405 }
1408 1406
1409 void clear_perf_probe_event(struct perf_probe_event *pev) 1407 void clear_perf_probe_event(struct perf_probe_event *pev)
1410 { 1408 {
1411 struct perf_probe_point *pp = &pev->point; 1409 struct perf_probe_point *pp = &pev->point;
1412 struct perf_probe_arg_field *field, *next; 1410 struct perf_probe_arg_field *field, *next;
1413 int i; 1411 int i;
1414 1412
1415 if (pev->event) 1413 if (pev->event)
1416 free(pev->event); 1414 free(pev->event);
1417 if (pev->group) 1415 if (pev->group)
1418 free(pev->group); 1416 free(pev->group);
1419 if (pp->file) 1417 if (pp->file)
1420 free(pp->file); 1418 free(pp->file);
1421 if (pp->function) 1419 if (pp->function)
1422 free(pp->function); 1420 free(pp->function);
1423 if (pp->lazy_line) 1421 if (pp->lazy_line)
1424 free(pp->lazy_line); 1422 free(pp->lazy_line);
1425 for (i = 0; i < pev->nargs; i++) { 1423 for (i = 0; i < pev->nargs; i++) {
1426 if (pev->args[i].name) 1424 if (pev->args[i].name)
1427 free(pev->args[i].name); 1425 free(pev->args[i].name);
1428 if (pev->args[i].var) 1426 if (pev->args[i].var)
1429 free(pev->args[i].var); 1427 free(pev->args[i].var);
1430 if (pev->args[i].type) 1428 if (pev->args[i].type)
1431 free(pev->args[i].type); 1429 free(pev->args[i].type);
1432 field = pev->args[i].field; 1430 field = pev->args[i].field;
1433 while (field) { 1431 while (field) {
1434 next = field->next; 1432 next = field->next;
1435 if (field->name) 1433 if (field->name)
1436 free(field->name); 1434 free(field->name);
1437 free(field); 1435 free(field);
1438 field = next; 1436 field = next;
1439 } 1437 }
1440 } 1438 }
1441 if (pev->args) 1439 if (pev->args)
1442 free(pev->args); 1440 free(pev->args);
1443 memset(pev, 0, sizeof(*pev)); 1441 memset(pev, 0, sizeof(*pev));
1444 } 1442 }
1445 1443
1446 static void clear_probe_trace_event(struct probe_trace_event *tev) 1444 static void clear_probe_trace_event(struct probe_trace_event *tev)
1447 { 1445 {
1448 struct probe_trace_arg_ref *ref, *next; 1446 struct probe_trace_arg_ref *ref, *next;
1449 int i; 1447 int i;
1450 1448
1451 if (tev->event) 1449 if (tev->event)
1452 free(tev->event); 1450 free(tev->event);
1453 if (tev->group) 1451 if (tev->group)
1454 free(tev->group); 1452 free(tev->group);
1455 if (tev->point.symbol) 1453 if (tev->point.symbol)
1456 free(tev->point.symbol); 1454 free(tev->point.symbol);
1457 if (tev->point.module) 1455 if (tev->point.module)
1458 free(tev->point.module); 1456 free(tev->point.module);
1459 for (i = 0; i < tev->nargs; i++) { 1457 for (i = 0; i < tev->nargs; i++) {
1460 if (tev->args[i].name) 1458 if (tev->args[i].name)
1461 free(tev->args[i].name); 1459 free(tev->args[i].name);
1462 if (tev->args[i].value) 1460 if (tev->args[i].value)
1463 free(tev->args[i].value); 1461 free(tev->args[i].value);
1464 if (tev->args[i].type) 1462 if (tev->args[i].type)
1465 free(tev->args[i].type); 1463 free(tev->args[i].type);
1466 ref = tev->args[i].ref; 1464 ref = tev->args[i].ref;
1467 while (ref) { 1465 while (ref) {
1468 next = ref->next; 1466 next = ref->next;
1469 free(ref); 1467 free(ref);
1470 ref = next; 1468 ref = next;
1471 } 1469 }
1472 } 1470 }
1473 if (tev->args) 1471 if (tev->args)
1474 free(tev->args); 1472 free(tev->args);
1475 memset(tev, 0, sizeof(*tev)); 1473 memset(tev, 0, sizeof(*tev));
1476 } 1474 }
1477 1475
1478 static int open_kprobe_events(bool readwrite) 1476 static int open_kprobe_events(bool readwrite)
1479 { 1477 {
1480 char buf[PATH_MAX]; 1478 char buf[PATH_MAX];
1481 const char *__debugfs; 1479 const char *__debugfs;
1482 int ret; 1480 int ret;
1483 1481
1484 __debugfs = debugfs_find_mountpoint(); 1482 __debugfs = debugfs_find_mountpoint();
1485 if (__debugfs == NULL) { 1483 if (__debugfs == NULL) {
1486 pr_warning("Debugfs is not mounted.\n"); 1484 pr_warning("Debugfs is not mounted.\n");
1487 return -ENOENT; 1485 return -ENOENT;
1488 } 1486 }
1489 1487
1490 ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs); 1488 ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs);
1491 if (ret >= 0) { 1489 if (ret >= 0) {
1492 pr_debug("Opening %s write=%d\n", buf, readwrite); 1490 pr_debug("Opening %s write=%d\n", buf, readwrite);
1493 if (readwrite && !probe_event_dry_run) 1491 if (readwrite && !probe_event_dry_run)
1494 ret = open(buf, O_RDWR, O_APPEND); 1492 ret = open(buf, O_RDWR, O_APPEND);
1495 else 1493 else
1496 ret = open(buf, O_RDONLY, 0); 1494 ret = open(buf, O_RDONLY, 0);
1497 } 1495 }
1498 1496
1499 if (ret < 0) { 1497 if (ret < 0) {
1500 if (errno == ENOENT) 1498 if (errno == ENOENT)
1501 pr_warning("kprobe_events file does not exist - please" 1499 pr_warning("kprobe_events file does not exist - please"
1502 " rebuild kernel with CONFIG_KPROBE_EVENT.\n"); 1500 " rebuild kernel with CONFIG_KPROBE_EVENT.\n");
1503 else 1501 else
1504 pr_warning("Failed to open kprobe_events file: %s\n", 1502 pr_warning("Failed to open kprobe_events file: %s\n",
1505 strerror(errno)); 1503 strerror(errno));
1506 } 1504 }
1507 return ret; 1505 return ret;
1508 } 1506 }
1509 1507
1510 /* Get raw string list of current kprobe_events */ 1508 /* Get raw string list of current kprobe_events */
1511 static struct strlist *get_probe_trace_command_rawlist(int fd) 1509 static struct strlist *get_probe_trace_command_rawlist(int fd)
1512 { 1510 {
1513 int ret, idx; 1511 int ret, idx;
1514 FILE *fp; 1512 FILE *fp;
1515 char buf[MAX_CMDLEN]; 1513 char buf[MAX_CMDLEN];
1516 char *p; 1514 char *p;
1517 struct strlist *sl; 1515 struct strlist *sl;
1518 1516
1519 sl = strlist__new(true, NULL); 1517 sl = strlist__new(true, NULL);
1520 1518
1521 fp = fdopen(dup(fd), "r"); 1519 fp = fdopen(dup(fd), "r");
1522 while (!feof(fp)) { 1520 while (!feof(fp)) {
1523 p = fgets(buf, MAX_CMDLEN, fp); 1521 p = fgets(buf, MAX_CMDLEN, fp);
1524 if (!p) 1522 if (!p)
1525 break; 1523 break;
1526 1524
1527 idx = strlen(p) - 1; 1525 idx = strlen(p) - 1;
1528 if (p[idx] == '\n') 1526 if (p[idx] == '\n')
1529 p[idx] = '\0'; 1527 p[idx] = '\0';
1530 ret = strlist__add(sl, buf); 1528 ret = strlist__add(sl, buf);
1531 if (ret < 0) { 1529 if (ret < 0) {
1532 pr_debug("strlist__add failed: %s\n", strerror(-ret)); 1530 pr_debug("strlist__add failed: %s\n", strerror(-ret));
1533 strlist__delete(sl); 1531 strlist__delete(sl);
1534 return NULL; 1532 return NULL;
1535 } 1533 }
1536 } 1534 }
1537 fclose(fp); 1535 fclose(fp);
1538 1536
1539 return sl; 1537 return sl;
1540 } 1538 }
1541 1539
1542 /* Show an event */ 1540 /* Show an event */
1543 static int show_perf_probe_event(struct perf_probe_event *pev) 1541 static int show_perf_probe_event(struct perf_probe_event *pev)
1544 { 1542 {
1545 int i, ret; 1543 int i, ret;
1546 char buf[128]; 1544 char buf[128];
1547 char *place; 1545 char *place;
1548 1546
1549 /* Synthesize only event probe point */ 1547 /* Synthesize only event probe point */
1550 place = synthesize_perf_probe_point(&pev->point); 1548 place = synthesize_perf_probe_point(&pev->point);
1551 if (!place) 1549 if (!place)
1552 return -EINVAL; 1550 return -EINVAL;
1553 1551
1554 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); 1552 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event);
1555 if (ret < 0) 1553 if (ret < 0)
1556 return ret; 1554 return ret;
1557 1555
1558 printf(" %-20s (on %s", buf, place); 1556 printf(" %-20s (on %s", buf, place);
1559 1557
1560 if (pev->nargs > 0) { 1558 if (pev->nargs > 0) {
1561 printf(" with"); 1559 printf(" with");
1562 for (i = 0; i < pev->nargs; i++) { 1560 for (i = 0; i < pev->nargs; i++) {
1563 ret = synthesize_perf_probe_arg(&pev->args[i], 1561 ret = synthesize_perf_probe_arg(&pev->args[i],
1564 buf, 128); 1562 buf, 128);
1565 if (ret < 0) 1563 if (ret < 0)
1566 break; 1564 break;
1567 printf(" %s", buf); 1565 printf(" %s", buf);
1568 } 1566 }
1569 } 1567 }
1570 printf(")\n"); 1568 printf(")\n");
1571 free(place); 1569 free(place);
1572 return ret; 1570 return ret;
1573 } 1571 }
1574 1572
1575 /* List up current perf-probe events */ 1573 /* List up current perf-probe events */
1576 int show_perf_probe_events(void) 1574 int show_perf_probe_events(void)
1577 { 1575 {
1578 int fd, ret; 1576 int fd, ret;
1579 struct probe_trace_event tev; 1577 struct probe_trace_event tev;
1580 struct perf_probe_event pev; 1578 struct perf_probe_event pev;
1581 struct strlist *rawlist; 1579 struct strlist *rawlist;
1582 struct str_node *ent; 1580 struct str_node *ent;
1583 1581
1584 setup_pager(); 1582 setup_pager();
1585 ret = init_vmlinux(); 1583 ret = init_vmlinux();
1586 if (ret < 0) 1584 if (ret < 0)
1587 return ret; 1585 return ret;
1588 1586
1589 memset(&tev, 0, sizeof(tev)); 1587 memset(&tev, 0, sizeof(tev));
1590 memset(&pev, 0, sizeof(pev)); 1588 memset(&pev, 0, sizeof(pev));
1591 1589
1592 fd = open_kprobe_events(false); 1590 fd = open_kprobe_events(false);
1593 if (fd < 0) 1591 if (fd < 0)
1594 return fd; 1592 return fd;
1595 1593
1596 rawlist = get_probe_trace_command_rawlist(fd); 1594 rawlist = get_probe_trace_command_rawlist(fd);
1597 close(fd); 1595 close(fd);
1598 if (!rawlist) 1596 if (!rawlist)
1599 return -ENOENT; 1597 return -ENOENT;
1600 1598
1601 strlist__for_each(ent, rawlist) { 1599 strlist__for_each(ent, rawlist) {
1602 ret = parse_probe_trace_command(ent->s, &tev); 1600 ret = parse_probe_trace_command(ent->s, &tev);
1603 if (ret >= 0) { 1601 if (ret >= 0) {
1604 ret = convert_to_perf_probe_event(&tev, &pev); 1602 ret = convert_to_perf_probe_event(&tev, &pev);
1605 if (ret >= 0) 1603 if (ret >= 0)
1606 ret = show_perf_probe_event(&pev); 1604 ret = show_perf_probe_event(&pev);
1607 } 1605 }
1608 clear_perf_probe_event(&pev); 1606 clear_perf_probe_event(&pev);
1609 clear_probe_trace_event(&tev); 1607 clear_probe_trace_event(&tev);
1610 if (ret < 0) 1608 if (ret < 0)
1611 break; 1609 break;
1612 } 1610 }
1613 strlist__delete(rawlist); 1611 strlist__delete(rawlist);
1614 1612
1615 return ret; 1613 return ret;
1616 } 1614 }
1617 1615
1618 /* Get current perf-probe event names */ 1616 /* Get current perf-probe event names */
1619 static struct strlist *get_probe_trace_event_names(int fd, bool include_group) 1617 static struct strlist *get_probe_trace_event_names(int fd, bool include_group)
1620 { 1618 {
1621 char buf[128]; 1619 char buf[128];
1622 struct strlist *sl, *rawlist; 1620 struct strlist *sl, *rawlist;
1623 struct str_node *ent; 1621 struct str_node *ent;
1624 struct probe_trace_event tev; 1622 struct probe_trace_event tev;
1625 int ret = 0; 1623 int ret = 0;
1626 1624
1627 memset(&tev, 0, sizeof(tev)); 1625 memset(&tev, 0, sizeof(tev));
1628 rawlist = get_probe_trace_command_rawlist(fd); 1626 rawlist = get_probe_trace_command_rawlist(fd);
1629 sl = strlist__new(true, NULL); 1627 sl = strlist__new(true, NULL);
1630 strlist__for_each(ent, rawlist) { 1628 strlist__for_each(ent, rawlist) {
1631 ret = parse_probe_trace_command(ent->s, &tev); 1629 ret = parse_probe_trace_command(ent->s, &tev);
1632 if (ret < 0) 1630 if (ret < 0)
1633 break; 1631 break;
1634 if (include_group) { 1632 if (include_group) {
1635 ret = e_snprintf(buf, 128, "%s:%s", tev.group, 1633 ret = e_snprintf(buf, 128, "%s:%s", tev.group,
1636 tev.event); 1634 tev.event);
1637 if (ret >= 0) 1635 if (ret >= 0)
1638 ret = strlist__add(sl, buf); 1636 ret = strlist__add(sl, buf);
1639 } else 1637 } else
1640 ret = strlist__add(sl, tev.event); 1638 ret = strlist__add(sl, tev.event);
1641 clear_probe_trace_event(&tev); 1639 clear_probe_trace_event(&tev);
1642 if (ret < 0) 1640 if (ret < 0)
1643 break; 1641 break;
1644 } 1642 }
1645 strlist__delete(rawlist); 1643 strlist__delete(rawlist);
1646 1644
1647 if (ret < 0) { 1645 if (ret < 0) {
1648 strlist__delete(sl); 1646 strlist__delete(sl);
1649 return NULL; 1647 return NULL;
1650 } 1648 }
1651 return sl; 1649 return sl;
1652 } 1650 }
1653 1651
1654 static int write_probe_trace_event(int fd, struct probe_trace_event *tev) 1652 static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
1655 { 1653 {
1656 int ret = 0; 1654 int ret = 0;
1657 char *buf = synthesize_probe_trace_command(tev); 1655 char *buf = synthesize_probe_trace_command(tev);
1658 1656
1659 if (!buf) { 1657 if (!buf) {
1660 pr_debug("Failed to synthesize probe trace event.\n"); 1658 pr_debug("Failed to synthesize probe trace event.\n");
1661 return -EINVAL; 1659 return -EINVAL;
1662 } 1660 }
1663 1661
1664 pr_debug("Writing event: %s\n", buf); 1662 pr_debug("Writing event: %s\n", buf);
1665 if (!probe_event_dry_run) { 1663 if (!probe_event_dry_run) {
1666 ret = write(fd, buf, strlen(buf)); 1664 ret = write(fd, buf, strlen(buf));
1667 if (ret <= 0) 1665 if (ret <= 0)
1668 pr_warning("Failed to write event: %s\n", 1666 pr_warning("Failed to write event: %s\n",
1669 strerror(errno)); 1667 strerror(errno));
1670 } 1668 }
1671 free(buf); 1669 free(buf);
1672 return ret; 1670 return ret;
1673 } 1671 }
1674 1672
1675 static int get_new_event_name(char *buf, size_t len, const char *base, 1673 static int get_new_event_name(char *buf, size_t len, const char *base,
1676 struct strlist *namelist, bool allow_suffix) 1674 struct strlist *namelist, bool allow_suffix)
1677 { 1675 {
1678 int i, ret; 1676 int i, ret;
1679 1677
1680 /* Try no suffix */ 1678 /* Try no suffix */
1681 ret = e_snprintf(buf, len, "%s", base); 1679 ret = e_snprintf(buf, len, "%s", base);
1682 if (ret < 0) { 1680 if (ret < 0) {
1683 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 1681 pr_debug("snprintf() failed: %s\n", strerror(-ret));
1684 return ret; 1682 return ret;
1685 } 1683 }
1686 if (!strlist__has_entry(namelist, buf)) 1684 if (!strlist__has_entry(namelist, buf))
1687 return 0; 1685 return 0;
1688 1686
1689 if (!allow_suffix) { 1687 if (!allow_suffix) {
1690 pr_warning("Error: event \"%s\" already exists. " 1688 pr_warning("Error: event \"%s\" already exists. "
1691 "(Use -f to force duplicates.)\n", base); 1689 "(Use -f to force duplicates.)\n", base);
1692 return -EEXIST; 1690 return -EEXIST;
1693 } 1691 }
1694 1692
1695 /* Try to add suffix */ 1693 /* Try to add suffix */
1696 for (i = 1; i < MAX_EVENT_INDEX; i++) { 1694 for (i = 1; i < MAX_EVENT_INDEX; i++) {
1697 ret = e_snprintf(buf, len, "%s_%d", base, i); 1695 ret = e_snprintf(buf, len, "%s_%d", base, i);
1698 if (ret < 0) { 1696 if (ret < 0) {
1699 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 1697 pr_debug("snprintf() failed: %s\n", strerror(-ret));
1700 return ret; 1698 return ret;
1701 } 1699 }
1702 if (!strlist__has_entry(namelist, buf)) 1700 if (!strlist__has_entry(namelist, buf))
1703 break; 1701 break;
1704 } 1702 }
1705 if (i == MAX_EVENT_INDEX) { 1703 if (i == MAX_EVENT_INDEX) {
1706 pr_warning("Too many events are on the same function.\n"); 1704 pr_warning("Too many events are on the same function.\n");
1707 ret = -ERANGE; 1705 ret = -ERANGE;
1708 } 1706 }
1709 1707
1710 return ret; 1708 return ret;
1711 } 1709 }
1712 1710
1713 static int __add_probe_trace_events(struct perf_probe_event *pev, 1711 static int __add_probe_trace_events(struct perf_probe_event *pev,
1714 struct probe_trace_event *tevs, 1712 struct probe_trace_event *tevs,
1715 int ntevs, bool allow_suffix) 1713 int ntevs, bool allow_suffix)
1716 { 1714 {
1717 int i, fd, ret; 1715 int i, fd, ret;
1718 struct probe_trace_event *tev = NULL; 1716 struct probe_trace_event *tev = NULL;
1719 char buf[64]; 1717 char buf[64];
1720 const char *event, *group; 1718 const char *event, *group;
1721 struct strlist *namelist; 1719 struct strlist *namelist;
1722 1720
1723 fd = open_kprobe_events(true); 1721 fd = open_kprobe_events(true);
1724 if (fd < 0) 1722 if (fd < 0)
1725 return fd; 1723 return fd;
1726 /* Get current event names */ 1724 /* Get current event names */
1727 namelist = get_probe_trace_event_names(fd, false); 1725 namelist = get_probe_trace_event_names(fd, false);
1728 if (!namelist) { 1726 if (!namelist) {
1729 pr_debug("Failed to get current event list.\n"); 1727 pr_debug("Failed to get current event list.\n");
1730 return -EIO; 1728 return -EIO;
1731 } 1729 }
1732 1730
1733 ret = 0; 1731 ret = 0;
1734 printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":"); 1732 printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":");
1735 for (i = 0; i < ntevs; i++) { 1733 for (i = 0; i < ntevs; i++) {
1736 tev = &tevs[i]; 1734 tev = &tevs[i];
1737 if (pev->event) 1735 if (pev->event)
1738 event = pev->event; 1736 event = pev->event;
1739 else 1737 else
1740 if (pev->point.function) 1738 if (pev->point.function)
1741 event = pev->point.function; 1739 event = pev->point.function;
1742 else 1740 else
1743 event = tev->point.symbol; 1741 event = tev->point.symbol;
1744 if (pev->group) 1742 if (pev->group)
1745 group = pev->group; 1743 group = pev->group;
1746 else 1744 else
1747 group = PERFPROBE_GROUP; 1745 group = PERFPROBE_GROUP;
1748 1746
1749 /* Get an unused new event name */ 1747 /* Get an unused new event name */
1750 ret = get_new_event_name(buf, 64, event, 1748 ret = get_new_event_name(buf, 64, event,
1751 namelist, allow_suffix); 1749 namelist, allow_suffix);
1752 if (ret < 0) 1750 if (ret < 0)
1753 break; 1751 break;
1754 event = buf; 1752 event = buf;
1755 1753
1756 tev->event = strdup(event); 1754 tev->event = strdup(event);
1757 tev->group = strdup(group); 1755 tev->group = strdup(group);
1758 if (tev->event == NULL || tev->group == NULL) { 1756 if (tev->event == NULL || tev->group == NULL) {
1759 ret = -ENOMEM; 1757 ret = -ENOMEM;
1760 break; 1758 break;
1761 } 1759 }
1762 ret = write_probe_trace_event(fd, tev); 1760 ret = write_probe_trace_event(fd, tev);
1763 if (ret < 0) 1761 if (ret < 0)
1764 break; 1762 break;
1765 /* Add added event name to namelist */ 1763 /* Add added event name to namelist */
1766 strlist__add(namelist, event); 1764 strlist__add(namelist, event);
1767 1765
1768 /* Trick here - save current event/group */ 1766 /* Trick here - save current event/group */
1769 event = pev->event; 1767 event = pev->event;
1770 group = pev->group; 1768 group = pev->group;
1771 pev->event = tev->event; 1769 pev->event = tev->event;
1772 pev->group = tev->group; 1770 pev->group = tev->group;
1773 show_perf_probe_event(pev); 1771 show_perf_probe_event(pev);
1774 /* Trick here - restore current event/group */ 1772 /* Trick here - restore current event/group */
1775 pev->event = (char *)event; 1773 pev->event = (char *)event;
1776 pev->group = (char *)group; 1774 pev->group = (char *)group;
1777 1775
1778 /* 1776 /*
1779 * Probes after the first probe which comes from same 1777 * Probes after the first probe which comes from same
1780 * user input are always allowed to add suffix, because 1778 * user input are always allowed to add suffix, because
1781 * there might be several addresses corresponding to 1779 * there might be several addresses corresponding to
1782 * one code line. 1780 * one code line.
1783 */ 1781 */
1784 allow_suffix = true; 1782 allow_suffix = true;
1785 } 1783 }
1786 1784
1787 if (ret >= 0) { 1785 if (ret >= 0) {
1788 /* Show how to use the event. */ 1786 /* Show how to use the event. */
1789 printf("\nYou can now use it on all perf tools, such as:\n\n"); 1787 printf("\nYou can now use it on all perf tools, such as:\n\n");
1790 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 1788 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
1791 tev->event); 1789 tev->event);
1792 } 1790 }
1793 1791
1794 strlist__delete(namelist); 1792 strlist__delete(namelist);
1795 close(fd); 1793 close(fd);
1796 return ret; 1794 return ret;
1797 } 1795 }
1798 1796
1799 static int convert_to_probe_trace_events(struct perf_probe_event *pev, 1797 static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1800 struct probe_trace_event **tevs, 1798 struct probe_trace_event **tevs,
1801 int max_tevs, const char *module) 1799 int max_tevs, const char *module)
1802 { 1800 {
1803 struct symbol *sym; 1801 struct symbol *sym;
1804 int ret = 0, i; 1802 int ret = 0, i;
1805 struct probe_trace_event *tev; 1803 struct probe_trace_event *tev;
1806 1804
1807 /* Convert perf_probe_event with debuginfo */ 1805 /* Convert perf_probe_event with debuginfo */
1808 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module); 1806 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module);
1809 if (ret != 0) 1807 if (ret != 0)
1810 return ret; /* Found in debuginfo or got an error */ 1808 return ret; /* Found in debuginfo or got an error */
1811 1809
1812 /* Allocate trace event buffer */ 1810 /* Allocate trace event buffer */
1813 tev = *tevs = zalloc(sizeof(struct probe_trace_event)); 1811 tev = *tevs = zalloc(sizeof(struct probe_trace_event));
1814 if (tev == NULL) 1812 if (tev == NULL)
1815 return -ENOMEM; 1813 return -ENOMEM;
1816 1814
1817 /* Copy parameters */ 1815 /* Copy parameters */
1818 tev->point.symbol = strdup(pev->point.function); 1816 tev->point.symbol = strdup(pev->point.function);
1819 if (tev->point.symbol == NULL) { 1817 if (tev->point.symbol == NULL) {
1820 ret = -ENOMEM; 1818 ret = -ENOMEM;
1821 goto error; 1819 goto error;
1822 } 1820 }
1823 1821
1824 if (module) { 1822 if (module) {
1825 tev->point.module = strdup(module); 1823 tev->point.module = strdup(module);
1826 if (tev->point.module == NULL) { 1824 if (tev->point.module == NULL) {
1827 ret = -ENOMEM; 1825 ret = -ENOMEM;
1828 goto error; 1826 goto error;
1829 } 1827 }
1830 } 1828 }
1831 1829
1832 tev->point.offset = pev->point.offset; 1830 tev->point.offset = pev->point.offset;
1833 tev->point.retprobe = pev->point.retprobe; 1831 tev->point.retprobe = pev->point.retprobe;
1834 tev->nargs = pev->nargs; 1832 tev->nargs = pev->nargs;
1835 if (tev->nargs) { 1833 if (tev->nargs) {
1836 tev->args = zalloc(sizeof(struct probe_trace_arg) 1834 tev->args = zalloc(sizeof(struct probe_trace_arg)
1837 * tev->nargs); 1835 * tev->nargs);
1838 if (tev->args == NULL) { 1836 if (tev->args == NULL) {
1839 ret = -ENOMEM; 1837 ret = -ENOMEM;
1840 goto error; 1838 goto error;
1841 } 1839 }
1842 for (i = 0; i < tev->nargs; i++) { 1840 for (i = 0; i < tev->nargs; i++) {
1843 if (pev->args[i].name) { 1841 if (pev->args[i].name) {
1844 tev->args[i].name = strdup(pev->args[i].name); 1842 tev->args[i].name = strdup(pev->args[i].name);
1845 if (tev->args[i].name == NULL) { 1843 if (tev->args[i].name == NULL) {
1846 ret = -ENOMEM; 1844 ret = -ENOMEM;
1847 goto error; 1845 goto error;
1848 } 1846 }
1849 } 1847 }
1850 tev->args[i].value = strdup(pev->args[i].var); 1848 tev->args[i].value = strdup(pev->args[i].var);
1851 if (tev->args[i].value == NULL) { 1849 if (tev->args[i].value == NULL) {
1852 ret = -ENOMEM; 1850 ret = -ENOMEM;
1853 goto error; 1851 goto error;
1854 } 1852 }
1855 if (pev->args[i].type) { 1853 if (pev->args[i].type) {
1856 tev->args[i].type = strdup(pev->args[i].type); 1854 tev->args[i].type = strdup(pev->args[i].type);
1857 if (tev->args[i].type == NULL) { 1855 if (tev->args[i].type == NULL) {
1858 ret = -ENOMEM; 1856 ret = -ENOMEM;
1859 goto error; 1857 goto error;
1860 } 1858 }
1861 } 1859 }
1862 } 1860 }
1863 } 1861 }
1864 1862
1865 /* Currently just checking function name from symbol map */ 1863 /* Currently just checking function name from symbol map */
1866 sym = __find_kernel_function_by_name(tev->point.symbol, NULL); 1864 sym = __find_kernel_function_by_name(tev->point.symbol, NULL);
1867 if (!sym) { 1865 if (!sym) {
1868 pr_warning("Kernel symbol \'%s\' not found.\n", 1866 pr_warning("Kernel symbol \'%s\' not found.\n",
1869 tev->point.symbol); 1867 tev->point.symbol);
1870 ret = -ENOENT; 1868 ret = -ENOENT;
1871 goto error; 1869 goto error;
1872 } 1870 }
1873 1871
1874 return 1; 1872 return 1;
1875 error: 1873 error:
1876 clear_probe_trace_event(tev); 1874 clear_probe_trace_event(tev);
1877 free(tev); 1875 free(tev);
1878 *tevs = NULL; 1876 *tevs = NULL;
1879 return ret; 1877 return ret;
1880 } 1878 }
1881 1879
1882 struct __event_package { 1880 struct __event_package {
1883 struct perf_probe_event *pev; 1881 struct perf_probe_event *pev;
1884 struct probe_trace_event *tevs; 1882 struct probe_trace_event *tevs;
1885 int ntevs; 1883 int ntevs;
1886 }; 1884 };
1887 1885
1888 int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 1886 int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1889 int max_tevs, const char *module, bool force_add) 1887 int max_tevs, const char *module, bool force_add)
1890 { 1888 {
1891 int i, j, ret; 1889 int i, j, ret;
1892 struct __event_package *pkgs; 1890 struct __event_package *pkgs;
1893 1891
1894 pkgs = zalloc(sizeof(struct __event_package) * npevs); 1892 pkgs = zalloc(sizeof(struct __event_package) * npevs);
1895 if (pkgs == NULL) 1893 if (pkgs == NULL)
1896 return -ENOMEM; 1894 return -ENOMEM;
1897 1895
1898 /* Init vmlinux path */ 1896 /* Init vmlinux path */
1899 ret = init_vmlinux(); 1897 ret = init_vmlinux();
1900 if (ret < 0) { 1898 if (ret < 0) {
1901 free(pkgs); 1899 free(pkgs);
1902 return ret; 1900 return ret;
1903 } 1901 }
1904 1902
1905 /* Loop 1: convert all events */ 1903 /* Loop 1: convert all events */
1906 for (i = 0; i < npevs; i++) { 1904 for (i = 0; i < npevs; i++) {
1907 pkgs[i].pev = &pevs[i]; 1905 pkgs[i].pev = &pevs[i];
1908 /* Convert with or without debuginfo */ 1906 /* Convert with or without debuginfo */
1909 ret = convert_to_probe_trace_events(pkgs[i].pev, 1907 ret = convert_to_probe_trace_events(pkgs[i].pev,
1910 &pkgs[i].tevs, 1908 &pkgs[i].tevs,
1911 max_tevs, 1909 max_tevs,
1912 module); 1910 module);
1913 if (ret < 0) 1911 if (ret < 0)
1914 goto end; 1912 goto end;
1915 pkgs[i].ntevs = ret; 1913 pkgs[i].ntevs = ret;
1916 } 1914 }
1917 1915
1918 /* Loop 2: add all events */ 1916 /* Loop 2: add all events */
1919 for (i = 0; i < npevs; i++) { 1917 for (i = 0; i < npevs; i++) {
1920 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 1918 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
1921 pkgs[i].ntevs, force_add); 1919 pkgs[i].ntevs, force_add);
1922 if (ret < 0) 1920 if (ret < 0)
1923 break; 1921 break;
1924 } 1922 }
1925 end: 1923 end:
1926 /* Loop 3: cleanup and free trace events */ 1924 /* Loop 3: cleanup and free trace events */
1927 for (i = 0; i < npevs; i++) { 1925 for (i = 0; i < npevs; i++) {
1928 for (j = 0; j < pkgs[i].ntevs; j++) 1926 for (j = 0; j < pkgs[i].ntevs; j++)
1929 clear_probe_trace_event(&pkgs[i].tevs[j]); 1927 clear_probe_trace_event(&pkgs[i].tevs[j]);
1930 free(pkgs[i].tevs); 1928 free(pkgs[i].tevs);
1931 } 1929 }
1932 free(pkgs); 1930 free(pkgs);
1933 1931
1934 return ret; 1932 return ret;
1935 } 1933 }
1936 1934
1937 static int __del_trace_probe_event(int fd, struct str_node *ent) 1935 static int __del_trace_probe_event(int fd, struct str_node *ent)
1938 { 1936 {
1939 char *p; 1937 char *p;
1940 char buf[128]; 1938 char buf[128];
1941 int ret; 1939 int ret;
1942 1940
1943 /* Convert from perf-probe event to trace-probe event */ 1941 /* Convert from perf-probe event to trace-probe event */
1944 ret = e_snprintf(buf, 128, "-:%s", ent->s); 1942 ret = e_snprintf(buf, 128, "-:%s", ent->s);
1945 if (ret < 0) 1943 if (ret < 0)
1946 goto error; 1944 goto error;
1947 1945
1948 p = strchr(buf + 2, ':'); 1946 p = strchr(buf + 2, ':');
1949 if (!p) { 1947 if (!p) {
1950 pr_debug("Internal error: %s should have ':' but not.\n", 1948 pr_debug("Internal error: %s should have ':' but not.\n",
1951 ent->s); 1949 ent->s);
1952 ret = -ENOTSUP; 1950 ret = -ENOTSUP;
1953 goto error; 1951 goto error;
1954 } 1952 }
1955 *p = '/'; 1953 *p = '/';
1956 1954
1957 pr_debug("Writing event: %s\n", buf); 1955 pr_debug("Writing event: %s\n", buf);
1958 ret = write(fd, buf, strlen(buf)); 1956 ret = write(fd, buf, strlen(buf));
1959 if (ret < 0) { 1957 if (ret < 0) {
1960 ret = -errno; 1958 ret = -errno;
1961 goto error; 1959 goto error;
1962 } 1960 }
1963 1961
1964 printf("Remove event: %s\n", ent->s); 1962 printf("Remove event: %s\n", ent->s);
1965 return 0; 1963 return 0;
1966 error: 1964 error:
1967 pr_warning("Failed to delete event: %s\n", strerror(-ret)); 1965 pr_warning("Failed to delete event: %s\n", strerror(-ret));
1968 return ret; 1966 return ret;
1969 } 1967 }
1970 1968
1971 static int del_trace_probe_event(int fd, const char *group, 1969 static int del_trace_probe_event(int fd, const char *group,
1972 const char *event, struct strlist *namelist) 1970 const char *event, struct strlist *namelist)
1973 { 1971 {
1974 char buf[128]; 1972 char buf[128];
1975 struct str_node *ent, *n; 1973 struct str_node *ent, *n;
1976 int found = 0, ret = 0; 1974 int found = 0, ret = 0;
1977 1975
1978 ret = e_snprintf(buf, 128, "%s:%s", group, event); 1976 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1979 if (ret < 0) { 1977 if (ret < 0) {
1980 pr_err("Failed to copy event.\n"); 1978 pr_err("Failed to copy event.\n");
1981 return ret; 1979 return ret;
1982 } 1980 }
1983 1981
1984 if (strpbrk(buf, "*?")) { /* Glob-exp */ 1982 if (strpbrk(buf, "*?")) { /* Glob-exp */
1985 strlist__for_each_safe(ent, n, namelist) 1983 strlist__for_each_safe(ent, n, namelist)
1986 if (strglobmatch(ent->s, buf)) { 1984 if (strglobmatch(ent->s, buf)) {
1987 found++; 1985 found++;
1988 ret = __del_trace_probe_event(fd, ent); 1986 ret = __del_trace_probe_event(fd, ent);
1989 if (ret < 0) 1987 if (ret < 0)
1990 break; 1988 break;
1991 strlist__remove(namelist, ent); 1989 strlist__remove(namelist, ent);
1992 } 1990 }
1993 } else { 1991 } else {
1994 ent = strlist__find(namelist, buf); 1992 ent = strlist__find(namelist, buf);
1995 if (ent) { 1993 if (ent) {
1996 found++; 1994 found++;
1997 ret = __del_trace_probe_event(fd, ent); 1995 ret = __del_trace_probe_event(fd, ent);
1998 if (ret >= 0) 1996 if (ret >= 0)
1999 strlist__remove(namelist, ent); 1997 strlist__remove(namelist, ent);
2000 } 1998 }
2001 } 1999 }
2002 if (found == 0 && ret >= 0) 2000 if (found == 0 && ret >= 0)
2003 pr_info("Info: Event \"%s\" does not exist.\n", buf); 2001 pr_info("Info: Event \"%s\" does not exist.\n", buf);
2004 2002
2005 return ret; 2003 return ret;
2006 } 2004 }
2007 2005
2008 int del_perf_probe_events(struct strlist *dellist) 2006 int del_perf_probe_events(struct strlist *dellist)
2009 { 2007 {
2010 int fd, ret = 0; 2008 int fd, ret = 0;
2011 const char *group, *event; 2009 const char *group, *event;
2012 char *p, *str; 2010 char *p, *str;
2013 struct str_node *ent; 2011 struct str_node *ent;
2014 struct strlist *namelist; 2012 struct strlist *namelist;
2015 2013
2016 fd = open_kprobe_events(true); 2014 fd = open_kprobe_events(true);
2017 if (fd < 0) 2015 if (fd < 0)
2018 return fd; 2016 return fd;
2019 2017
2020 /* Get current event names */ 2018 /* Get current event names */
2021 namelist = get_probe_trace_event_names(fd, true); 2019 namelist = get_probe_trace_event_names(fd, true);
2022 if (namelist == NULL) 2020 if (namelist == NULL)
2023 return -EINVAL; 2021 return -EINVAL;
2024 2022
2025 strlist__for_each(ent, dellist) { 2023 strlist__for_each(ent, dellist) {
2026 str = strdup(ent->s); 2024 str = strdup(ent->s);
2027 if (str == NULL) { 2025 if (str == NULL) {
2028 ret = -ENOMEM; 2026 ret = -ENOMEM;
2029 break; 2027 break;
2030 } 2028 }
2031 pr_debug("Parsing: %s\n", str); 2029 pr_debug("Parsing: %s\n", str);
2032 p = strchr(str, ':'); 2030 p = strchr(str, ':');
2033 if (p) { 2031 if (p) {
2034 group = str; 2032 group = str;
2035 *p = '\0'; 2033 *p = '\0';
2036 event = p + 1; 2034 event = p + 1;
2037 } else { 2035 } else {
2038 group = "*"; 2036 group = "*";
2039 event = str; 2037 event = str;
2040 } 2038 }
2041 pr_debug("Group: %s, Event: %s\n", group, event); 2039 pr_debug("Group: %s, Event: %s\n", group, event);
2042 ret = del_trace_probe_event(fd, group, event, namelist); 2040 ret = del_trace_probe_event(fd, group, event, namelist);
2043 free(str); 2041 free(str);
2044 if (ret < 0) 2042 if (ret < 0)
2045 break; 2043 break;
2046 } 2044 }
2047 strlist__delete(namelist); 2045 strlist__delete(namelist);
2048 close(fd); 2046 close(fd);
2049 2047
2050 return ret; 2048 return ret;
2051 } 2049 }
2052 /* TODO: don't use a global variable for filter ... */ 2050 /* TODO: don't use a global variable for filter ... */
2053 static struct strfilter *available_func_filter; 2051 static struct strfilter *available_func_filter;
2054 2052
2055 /* 2053 /*
2056 * If a symbol corresponds to a function with global binding and 2054 * If a symbol corresponds to a function with global binding and
2057 * matches filter return 0. For all others return 1. 2055 * matches filter return 0. For all others return 1.
2058 */ 2056 */
2059 static int filter_available_functions(struct map *map __unused, 2057 static int filter_available_functions(struct map *map __unused,
2060 struct symbol *sym) 2058 struct symbol *sym)
2061 { 2059 {
2062 if (sym->binding == STB_GLOBAL && 2060 if (sym->binding == STB_GLOBAL &&
2063 strfilter__compare(available_func_filter, sym->name)) 2061 strfilter__compare(available_func_filter, sym->name))
2064 return 0; 2062 return 0;
2065 return 1; 2063 return 1;
2066 } 2064 }
2067 2065
2068 int show_available_funcs(const char *module, struct strfilter *_filter) 2066 int show_available_funcs(const char *module, struct strfilter *_filter)
2069 { 2067 {
2070 struct map *map; 2068 struct map *map;
2071 int ret; 2069 int ret;
2072 2070
2073 setup_pager(); 2071 setup_pager();
2074 2072
2075 ret = init_vmlinux(); 2073 ret = init_vmlinux();
2076 if (ret < 0) 2074 if (ret < 0)
2077 return ret; 2075 return ret;
2078 2076
2079 map = kernel_get_module_map(module); 2077 map = kernel_get_module_map(module);
2080 if (!map) { 2078 if (!map) {
2081 pr_err("Failed to find %s map.\n", (module) ? : "kernel"); 2079 pr_err("Failed to find %s map.\n", (module) ? : "kernel");
2082 return -EINVAL; 2080 return -EINVAL;
2083 } 2081 }
2084 available_func_filter = _filter; 2082 available_func_filter = _filter;
2085 if (map__load(map, filter_available_functions)) { 2083 if (map__load(map, filter_available_functions)) {
2086 pr_err("Failed to load map.\n"); 2084 pr_err("Failed to load map.\n");
2087 return -EINVAL; 2085 return -EINVAL;
2088 } 2086 }
2089 if (!dso__sorted_by_name(map->dso, map->type)) 2087 if (!dso__sorted_by_name(map->dso, map->type))
2090 dso__sort_by_name(map->dso, map->type); 2088 dso__sort_by_name(map->dso, map->type);
2091 2089
2092 dso__fprintf_symbols_by_name(map->dso, map->type, stdout); 2090 dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2093 return 0; 2091 return 0;
2094 } 2092 }
2095 2093
tools/perf/util/symbol.c
1 #define _GNU_SOURCE
2 #include <ctype.h> 1 #include <ctype.h>
3 #include <dirent.h> 2 #include <dirent.h>
4 #include <errno.h> 3 #include <errno.h>
5 #include <libgen.h> 4 #include <libgen.h>
6 #include <stdlib.h> 5 #include <stdlib.h>
7 #include <stdio.h> 6 #include <stdio.h>
8 #include <string.h> 7 #include <string.h>
9 #include <sys/types.h> 8 #include <sys/types.h>
10 #include <sys/stat.h> 9 #include <sys/stat.h>
11 #include <sys/param.h> 10 #include <sys/param.h>
12 #include <fcntl.h> 11 #include <fcntl.h>
13 #include <unistd.h> 12 #include <unistd.h>
14 #include <inttypes.h> 13 #include <inttypes.h>
15 #include "build-id.h" 14 #include "build-id.h"
16 #include "debug.h" 15 #include "debug.h"
17 #include "symbol.h" 16 #include "symbol.h"
18 #include "strlist.h" 17 #include "strlist.h"
19 18
20 #include <libelf.h> 19 #include <libelf.h>
21 #include <gelf.h> 20 #include <gelf.h>
22 #include <elf.h> 21 #include <elf.h>
23 #include <limits.h> 22 #include <limits.h>
24 #include <sys/utsname.h> 23 #include <sys/utsname.h>
25 24
26 #ifndef KSYM_NAME_LEN 25 #ifndef KSYM_NAME_LEN
27 #define KSYM_NAME_LEN 256 26 #define KSYM_NAME_LEN 256
28 #endif 27 #endif
29 28
30 #ifndef NT_GNU_BUILD_ID 29 #ifndef NT_GNU_BUILD_ID
31 #define NT_GNU_BUILD_ID 3 30 #define NT_GNU_BUILD_ID 3
32 #endif 31 #endif
33 32
34 static bool dso__build_id_equal(const struct dso *dso, u8 *build_id); 33 static bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
35 static int elf_read_build_id(Elf *elf, void *bf, size_t size); 34 static int elf_read_build_id(Elf *elf, void *bf, size_t size);
36 static void dsos__add(struct list_head *head, struct dso *dso); 35 static void dsos__add(struct list_head *head, struct dso *dso);
37 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 36 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
38 static int dso__load_kernel_sym(struct dso *dso, struct map *map, 37 static int dso__load_kernel_sym(struct dso *dso, struct map *map,
39 symbol_filter_t filter); 38 symbol_filter_t filter);
40 static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 39 static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
41 symbol_filter_t filter); 40 symbol_filter_t filter);
42 static int vmlinux_path__nr_entries; 41 static int vmlinux_path__nr_entries;
43 static char **vmlinux_path; 42 static char **vmlinux_path;
44 43
45 struct symbol_conf symbol_conf = { 44 struct symbol_conf symbol_conf = {
46 .exclude_other = true, 45 .exclude_other = true,
47 .use_modules = true, 46 .use_modules = true,
48 .try_vmlinux_path = true, 47 .try_vmlinux_path = true,
49 .annotate_src = true, 48 .annotate_src = true,
50 .symfs = "", 49 .symfs = "",
51 }; 50 };
52 51
53 int dso__name_len(const struct dso *dso) 52 int dso__name_len(const struct dso *dso)
54 { 53 {
55 if (verbose) 54 if (verbose)
56 return dso->long_name_len; 55 return dso->long_name_len;
57 56
58 return dso->short_name_len; 57 return dso->short_name_len;
59 } 58 }
60 59
61 bool dso__loaded(const struct dso *dso, enum map_type type) 60 bool dso__loaded(const struct dso *dso, enum map_type type)
62 { 61 {
63 return dso->loaded & (1 << type); 62 return dso->loaded & (1 << type);
64 } 63 }
65 64
66 bool dso__sorted_by_name(const struct dso *dso, enum map_type type) 65 bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
67 { 66 {
68 return dso->sorted_by_name & (1 << type); 67 return dso->sorted_by_name & (1 << type);
69 } 68 }
70 69
71 static void dso__set_sorted_by_name(struct dso *dso, enum map_type type) 70 static void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
72 { 71 {
73 dso->sorted_by_name |= (1 << type); 72 dso->sorted_by_name |= (1 << type);
74 } 73 }
75 74
76 bool symbol_type__is_a(char symbol_type, enum map_type map_type) 75 bool symbol_type__is_a(char symbol_type, enum map_type map_type)
77 { 76 {
78 symbol_type = toupper(symbol_type); 77 symbol_type = toupper(symbol_type);
79 78
80 switch (map_type) { 79 switch (map_type) {
81 case MAP__FUNCTION: 80 case MAP__FUNCTION:
82 return symbol_type == 'T' || symbol_type == 'W'; 81 return symbol_type == 'T' || symbol_type == 'W';
83 case MAP__VARIABLE: 82 case MAP__VARIABLE:
84 return symbol_type == 'D'; 83 return symbol_type == 'D';
85 default: 84 default:
86 return false; 85 return false;
87 } 86 }
88 } 87 }
89 88
90 static int prefix_underscores_count(const char *str) 89 static int prefix_underscores_count(const char *str)
91 { 90 {
92 const char *tail = str; 91 const char *tail = str;
93 92
94 while (*tail == '_') 93 while (*tail == '_')
95 tail++; 94 tail++;
96 95
97 return tail - str; 96 return tail - str;
98 } 97 }
99 98
100 #define SYMBOL_A 0 99 #define SYMBOL_A 0
101 #define SYMBOL_B 1 100 #define SYMBOL_B 1
102 101
103 static int choose_best_symbol(struct symbol *syma, struct symbol *symb) 102 static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
104 { 103 {
105 s64 a; 104 s64 a;
106 s64 b; 105 s64 b;
107 106
108 /* Prefer a symbol with non zero length */ 107 /* Prefer a symbol with non zero length */
109 a = syma->end - syma->start; 108 a = syma->end - syma->start;
110 b = symb->end - symb->start; 109 b = symb->end - symb->start;
111 if ((b == 0) && (a > 0)) 110 if ((b == 0) && (a > 0))
112 return SYMBOL_A; 111 return SYMBOL_A;
113 else if ((a == 0) && (b > 0)) 112 else if ((a == 0) && (b > 0))
114 return SYMBOL_B; 113 return SYMBOL_B;
115 114
116 /* Prefer a non weak symbol over a weak one */ 115 /* Prefer a non weak symbol over a weak one */
117 a = syma->binding == STB_WEAK; 116 a = syma->binding == STB_WEAK;
118 b = symb->binding == STB_WEAK; 117 b = symb->binding == STB_WEAK;
119 if (b && !a) 118 if (b && !a)
120 return SYMBOL_A; 119 return SYMBOL_A;
121 if (a && !b) 120 if (a && !b)
122 return SYMBOL_B; 121 return SYMBOL_B;
123 122
124 /* Prefer a global symbol over a non global one */ 123 /* Prefer a global symbol over a non global one */
125 a = syma->binding == STB_GLOBAL; 124 a = syma->binding == STB_GLOBAL;
126 b = symb->binding == STB_GLOBAL; 125 b = symb->binding == STB_GLOBAL;
127 if (a && !b) 126 if (a && !b)
128 return SYMBOL_A; 127 return SYMBOL_A;
129 if (b && !a) 128 if (b && !a)
130 return SYMBOL_B; 129 return SYMBOL_B;
131 130
132 /* Prefer a symbol with less underscores */ 131 /* Prefer a symbol with less underscores */
133 a = prefix_underscores_count(syma->name); 132 a = prefix_underscores_count(syma->name);
134 b = prefix_underscores_count(symb->name); 133 b = prefix_underscores_count(symb->name);
135 if (b > a) 134 if (b > a)
136 return SYMBOL_A; 135 return SYMBOL_A;
137 else if (a > b) 136 else if (a > b)
138 return SYMBOL_B; 137 return SYMBOL_B;
139 138
140 /* If all else fails, choose the symbol with the longest name */ 139 /* If all else fails, choose the symbol with the longest name */
141 if (strlen(syma->name) >= strlen(symb->name)) 140 if (strlen(syma->name) >= strlen(symb->name))
142 return SYMBOL_A; 141 return SYMBOL_A;
143 else 142 else
144 return SYMBOL_B; 143 return SYMBOL_B;
145 } 144 }
146 145
147 static void symbols__fixup_duplicate(struct rb_root *symbols) 146 static void symbols__fixup_duplicate(struct rb_root *symbols)
148 { 147 {
149 struct rb_node *nd; 148 struct rb_node *nd;
150 struct symbol *curr, *next; 149 struct symbol *curr, *next;
151 150
152 nd = rb_first(symbols); 151 nd = rb_first(symbols);
153 152
154 while (nd) { 153 while (nd) {
155 curr = rb_entry(nd, struct symbol, rb_node); 154 curr = rb_entry(nd, struct symbol, rb_node);
156 again: 155 again:
157 nd = rb_next(&curr->rb_node); 156 nd = rb_next(&curr->rb_node);
158 next = rb_entry(nd, struct symbol, rb_node); 157 next = rb_entry(nd, struct symbol, rb_node);
159 158
160 if (!nd) 159 if (!nd)
161 break; 160 break;
162 161
163 if (curr->start != next->start) 162 if (curr->start != next->start)
164 continue; 163 continue;
165 164
166 if (choose_best_symbol(curr, next) == SYMBOL_A) { 165 if (choose_best_symbol(curr, next) == SYMBOL_A) {
167 rb_erase(&next->rb_node, symbols); 166 rb_erase(&next->rb_node, symbols);
168 goto again; 167 goto again;
169 } else { 168 } else {
170 nd = rb_next(&curr->rb_node); 169 nd = rb_next(&curr->rb_node);
171 rb_erase(&curr->rb_node, symbols); 170 rb_erase(&curr->rb_node, symbols);
172 } 171 }
173 } 172 }
174 } 173 }
175 174
176 static void symbols__fixup_end(struct rb_root *symbols) 175 static void symbols__fixup_end(struct rb_root *symbols)
177 { 176 {
178 struct rb_node *nd, *prevnd = rb_first(symbols); 177 struct rb_node *nd, *prevnd = rb_first(symbols);
179 struct symbol *curr, *prev; 178 struct symbol *curr, *prev;
180 179
181 if (prevnd == NULL) 180 if (prevnd == NULL)
182 return; 181 return;
183 182
184 curr = rb_entry(prevnd, struct symbol, rb_node); 183 curr = rb_entry(prevnd, struct symbol, rb_node);
185 184
186 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 185 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
187 prev = curr; 186 prev = curr;
188 curr = rb_entry(nd, struct symbol, rb_node); 187 curr = rb_entry(nd, struct symbol, rb_node);
189 188
190 if (prev->end == prev->start && prev->end != curr->start) 189 if (prev->end == prev->start && prev->end != curr->start)
191 prev->end = curr->start - 1; 190 prev->end = curr->start - 1;
192 } 191 }
193 192
194 /* Last entry */ 193 /* Last entry */
195 if (curr->end == curr->start) 194 if (curr->end == curr->start)
196 curr->end = roundup(curr->start, 4096); 195 curr->end = roundup(curr->start, 4096);
197 } 196 }
198 197
199 static void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) 198 static void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
200 { 199 {
201 struct map *prev, *curr; 200 struct map *prev, *curr;
202 struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]); 201 struct rb_node *nd, *prevnd = rb_first(&mg->maps[type]);
203 202
204 if (prevnd == NULL) 203 if (prevnd == NULL)
205 return; 204 return;
206 205
207 curr = rb_entry(prevnd, struct map, rb_node); 206 curr = rb_entry(prevnd, struct map, rb_node);
208 207
209 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 208 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
210 prev = curr; 209 prev = curr;
211 curr = rb_entry(nd, struct map, rb_node); 210 curr = rb_entry(nd, struct map, rb_node);
212 prev->end = curr->start - 1; 211 prev->end = curr->start - 1;
213 } 212 }
214 213
215 /* 214 /*
216 * We still haven't the actual symbols, so guess the 215 * We still haven't the actual symbols, so guess the
217 * last map final address. 216 * last map final address.
218 */ 217 */
219 curr->end = ~0ULL; 218 curr->end = ~0ULL;
220 } 219 }
221 220
222 static void map_groups__fixup_end(struct map_groups *mg) 221 static void map_groups__fixup_end(struct map_groups *mg)
223 { 222 {
224 int i; 223 int i;
225 for (i = 0; i < MAP__NR_TYPES; ++i) 224 for (i = 0; i < MAP__NR_TYPES; ++i)
226 __map_groups__fixup_end(mg, i); 225 __map_groups__fixup_end(mg, i);
227 } 226 }
228 227
229 static struct symbol *symbol__new(u64 start, u64 len, u8 binding, 228 static struct symbol *symbol__new(u64 start, u64 len, u8 binding,
230 const char *name) 229 const char *name)
231 { 230 {
232 size_t namelen = strlen(name) + 1; 231 size_t namelen = strlen(name) + 1;
233 struct symbol *sym = calloc(1, (symbol_conf.priv_size + 232 struct symbol *sym = calloc(1, (symbol_conf.priv_size +
234 sizeof(*sym) + namelen)); 233 sizeof(*sym) + namelen));
235 if (sym == NULL) 234 if (sym == NULL)
236 return NULL; 235 return NULL;
237 236
238 if (symbol_conf.priv_size) 237 if (symbol_conf.priv_size)
239 sym = ((void *)sym) + symbol_conf.priv_size; 238 sym = ((void *)sym) + symbol_conf.priv_size;
240 239
241 sym->start = start; 240 sym->start = start;
242 sym->end = len ? start + len - 1 : start; 241 sym->end = len ? start + len - 1 : start;
243 sym->binding = binding; 242 sym->binding = binding;
244 sym->namelen = namelen - 1; 243 sym->namelen = namelen - 1;
245 244
246 pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", 245 pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n",
247 __func__, name, start, sym->end); 246 __func__, name, start, sym->end);
248 memcpy(sym->name, name, namelen); 247 memcpy(sym->name, name, namelen);
249 248
250 return sym; 249 return sym;
251 } 250 }
252 251
253 void symbol__delete(struct symbol *sym) 252 void symbol__delete(struct symbol *sym)
254 { 253 {
255 free(((void *)sym) - symbol_conf.priv_size); 254 free(((void *)sym) - symbol_conf.priv_size);
256 } 255 }
257 256
258 static size_t symbol__fprintf(struct symbol *sym, FILE *fp) 257 static size_t symbol__fprintf(struct symbol *sym, FILE *fp)
259 { 258 {
260 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n", 259 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n",
261 sym->start, sym->end, 260 sym->start, sym->end,
262 sym->binding == STB_GLOBAL ? 'g' : 261 sym->binding == STB_GLOBAL ? 'g' :
263 sym->binding == STB_LOCAL ? 'l' : 'w', 262 sym->binding == STB_LOCAL ? 'l' : 'w',
264 sym->name); 263 sym->name);
265 } 264 }
266 265
267 void dso__set_long_name(struct dso *dso, char *name) 266 void dso__set_long_name(struct dso *dso, char *name)
268 { 267 {
269 if (name == NULL) 268 if (name == NULL)
270 return; 269 return;
271 dso->long_name = name; 270 dso->long_name = name;
272 dso->long_name_len = strlen(name); 271 dso->long_name_len = strlen(name);
273 } 272 }
274 273
275 static void dso__set_short_name(struct dso *dso, const char *name) 274 static void dso__set_short_name(struct dso *dso, const char *name)
276 { 275 {
277 if (name == NULL) 276 if (name == NULL)
278 return; 277 return;
279 dso->short_name = name; 278 dso->short_name = name;
280 dso->short_name_len = strlen(name); 279 dso->short_name_len = strlen(name);
281 } 280 }
282 281
283 static void dso__set_basename(struct dso *dso) 282 static void dso__set_basename(struct dso *dso)
284 { 283 {
285 dso__set_short_name(dso, basename(dso->long_name)); 284 dso__set_short_name(dso, basename(dso->long_name));
286 } 285 }
287 286
288 struct dso *dso__new(const char *name) 287 struct dso *dso__new(const char *name)
289 { 288 {
290 struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1); 289 struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
291 290
292 if (dso != NULL) { 291 if (dso != NULL) {
293 int i; 292 int i;
294 strcpy(dso->name, name); 293 strcpy(dso->name, name);
295 dso__set_long_name(dso, dso->name); 294 dso__set_long_name(dso, dso->name);
296 dso__set_short_name(dso, dso->name); 295 dso__set_short_name(dso, dso->name);
297 for (i = 0; i < MAP__NR_TYPES; ++i) 296 for (i = 0; i < MAP__NR_TYPES; ++i)
298 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; 297 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
299 dso->symtab_type = SYMTAB__NOT_FOUND; 298 dso->symtab_type = SYMTAB__NOT_FOUND;
300 dso->loaded = 0; 299 dso->loaded = 0;
301 dso->sorted_by_name = 0; 300 dso->sorted_by_name = 0;
302 dso->has_build_id = 0; 301 dso->has_build_id = 0;
303 dso->kernel = DSO_TYPE_USER; 302 dso->kernel = DSO_TYPE_USER;
304 INIT_LIST_HEAD(&dso->node); 303 INIT_LIST_HEAD(&dso->node);
305 } 304 }
306 305
307 return dso; 306 return dso;
308 } 307 }
309 308
310 static void symbols__delete(struct rb_root *symbols) 309 static void symbols__delete(struct rb_root *symbols)
311 { 310 {
312 struct symbol *pos; 311 struct symbol *pos;
313 struct rb_node *next = rb_first(symbols); 312 struct rb_node *next = rb_first(symbols);
314 313
315 while (next) { 314 while (next) {
316 pos = rb_entry(next, struct symbol, rb_node); 315 pos = rb_entry(next, struct symbol, rb_node);
317 next = rb_next(&pos->rb_node); 316 next = rb_next(&pos->rb_node);
318 rb_erase(&pos->rb_node, symbols); 317 rb_erase(&pos->rb_node, symbols);
319 symbol__delete(pos); 318 symbol__delete(pos);
320 } 319 }
321 } 320 }
322 321
323 void dso__delete(struct dso *dso) 322 void dso__delete(struct dso *dso)
324 { 323 {
325 int i; 324 int i;
326 for (i = 0; i < MAP__NR_TYPES; ++i) 325 for (i = 0; i < MAP__NR_TYPES; ++i)
327 symbols__delete(&dso->symbols[i]); 326 symbols__delete(&dso->symbols[i]);
328 if (dso->sname_alloc) 327 if (dso->sname_alloc)
329 free((char *)dso->short_name); 328 free((char *)dso->short_name);
330 if (dso->lname_alloc) 329 if (dso->lname_alloc)
331 free(dso->long_name); 330 free(dso->long_name);
332 free(dso); 331 free(dso);
333 } 332 }
334 333
335 void dso__set_build_id(struct dso *dso, void *build_id) 334 void dso__set_build_id(struct dso *dso, void *build_id)
336 { 335 {
337 memcpy(dso->build_id, build_id, sizeof(dso->build_id)); 336 memcpy(dso->build_id, build_id, sizeof(dso->build_id));
338 dso->has_build_id = 1; 337 dso->has_build_id = 1;
339 } 338 }
340 339
341 static void symbols__insert(struct rb_root *symbols, struct symbol *sym) 340 static void symbols__insert(struct rb_root *symbols, struct symbol *sym)
342 { 341 {
343 struct rb_node **p = &symbols->rb_node; 342 struct rb_node **p = &symbols->rb_node;
344 struct rb_node *parent = NULL; 343 struct rb_node *parent = NULL;
345 const u64 ip = sym->start; 344 const u64 ip = sym->start;
346 struct symbol *s; 345 struct symbol *s;
347 346
348 while (*p != NULL) { 347 while (*p != NULL) {
349 parent = *p; 348 parent = *p;
350 s = rb_entry(parent, struct symbol, rb_node); 349 s = rb_entry(parent, struct symbol, rb_node);
351 if (ip < s->start) 350 if (ip < s->start)
352 p = &(*p)->rb_left; 351 p = &(*p)->rb_left;
353 else 352 else
354 p = &(*p)->rb_right; 353 p = &(*p)->rb_right;
355 } 354 }
356 rb_link_node(&sym->rb_node, parent, p); 355 rb_link_node(&sym->rb_node, parent, p);
357 rb_insert_color(&sym->rb_node, symbols); 356 rb_insert_color(&sym->rb_node, symbols);
358 } 357 }
359 358
360 static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) 359 static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
361 { 360 {
362 struct rb_node *n; 361 struct rb_node *n;
363 362
364 if (symbols == NULL) 363 if (symbols == NULL)
365 return NULL; 364 return NULL;
366 365
367 n = symbols->rb_node; 366 n = symbols->rb_node;
368 367
369 while (n) { 368 while (n) {
370 struct symbol *s = rb_entry(n, struct symbol, rb_node); 369 struct symbol *s = rb_entry(n, struct symbol, rb_node);
371 370
372 if (ip < s->start) 371 if (ip < s->start)
373 n = n->rb_left; 372 n = n->rb_left;
374 else if (ip > s->end) 373 else if (ip > s->end)
375 n = n->rb_right; 374 n = n->rb_right;
376 else 375 else
377 return s; 376 return s;
378 } 377 }
379 378
380 return NULL; 379 return NULL;
381 } 380 }
382 381
383 struct symbol_name_rb_node { 382 struct symbol_name_rb_node {
384 struct rb_node rb_node; 383 struct rb_node rb_node;
385 struct symbol sym; 384 struct symbol sym;
386 }; 385 };
387 386
388 static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym) 387 static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym)
389 { 388 {
390 struct rb_node **p = &symbols->rb_node; 389 struct rb_node **p = &symbols->rb_node;
391 struct rb_node *parent = NULL; 390 struct rb_node *parent = NULL;
392 struct symbol_name_rb_node *symn, *s; 391 struct symbol_name_rb_node *symn, *s;
393 392
394 symn = container_of(sym, struct symbol_name_rb_node, sym); 393 symn = container_of(sym, struct symbol_name_rb_node, sym);
395 394
396 while (*p != NULL) { 395 while (*p != NULL) {
397 parent = *p; 396 parent = *p;
398 s = rb_entry(parent, struct symbol_name_rb_node, rb_node); 397 s = rb_entry(parent, struct symbol_name_rb_node, rb_node);
399 if (strcmp(sym->name, s->sym.name) < 0) 398 if (strcmp(sym->name, s->sym.name) < 0)
400 p = &(*p)->rb_left; 399 p = &(*p)->rb_left;
401 else 400 else
402 p = &(*p)->rb_right; 401 p = &(*p)->rb_right;
403 } 402 }
404 rb_link_node(&symn->rb_node, parent, p); 403 rb_link_node(&symn->rb_node, parent, p);
405 rb_insert_color(&symn->rb_node, symbols); 404 rb_insert_color(&symn->rb_node, symbols);
406 } 405 }
407 406
408 static void symbols__sort_by_name(struct rb_root *symbols, 407 static void symbols__sort_by_name(struct rb_root *symbols,
409 struct rb_root *source) 408 struct rb_root *source)
410 { 409 {
411 struct rb_node *nd; 410 struct rb_node *nd;
412 411
413 for (nd = rb_first(source); nd; nd = rb_next(nd)) { 412 for (nd = rb_first(source); nd; nd = rb_next(nd)) {
414 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 413 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
415 symbols__insert_by_name(symbols, pos); 414 symbols__insert_by_name(symbols, pos);
416 } 415 }
417 } 416 }
418 417
419 static struct symbol *symbols__find_by_name(struct rb_root *symbols, 418 static struct symbol *symbols__find_by_name(struct rb_root *symbols,
420 const char *name) 419 const char *name)
421 { 420 {
422 struct rb_node *n; 421 struct rb_node *n;
423 422
424 if (symbols == NULL) 423 if (symbols == NULL)
425 return NULL; 424 return NULL;
426 425
427 n = symbols->rb_node; 426 n = symbols->rb_node;
428 427
429 while (n) { 428 while (n) {
430 struct symbol_name_rb_node *s; 429 struct symbol_name_rb_node *s;
431 int cmp; 430 int cmp;
432 431
433 s = rb_entry(n, struct symbol_name_rb_node, rb_node); 432 s = rb_entry(n, struct symbol_name_rb_node, rb_node);
434 cmp = strcmp(name, s->sym.name); 433 cmp = strcmp(name, s->sym.name);
435 434
436 if (cmp < 0) 435 if (cmp < 0)
437 n = n->rb_left; 436 n = n->rb_left;
438 else if (cmp > 0) 437 else if (cmp > 0)
439 n = n->rb_right; 438 n = n->rb_right;
440 else 439 else
441 return &s->sym; 440 return &s->sym;
442 } 441 }
443 442
444 return NULL; 443 return NULL;
445 } 444 }
446 445
447 struct symbol *dso__find_symbol(struct dso *dso, 446 struct symbol *dso__find_symbol(struct dso *dso,
448 enum map_type type, u64 addr) 447 enum map_type type, u64 addr)
449 { 448 {
450 return symbols__find(&dso->symbols[type], addr); 449 return symbols__find(&dso->symbols[type], addr);
451 } 450 }
452 451
453 struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 452 struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
454 const char *name) 453 const char *name)
455 { 454 {
456 return symbols__find_by_name(&dso->symbol_names[type], name); 455 return symbols__find_by_name(&dso->symbol_names[type], name);
457 } 456 }
458 457
459 void dso__sort_by_name(struct dso *dso, enum map_type type) 458 void dso__sort_by_name(struct dso *dso, enum map_type type)
460 { 459 {
461 dso__set_sorted_by_name(dso, type); 460 dso__set_sorted_by_name(dso, type);
462 return symbols__sort_by_name(&dso->symbol_names[type], 461 return symbols__sort_by_name(&dso->symbol_names[type],
463 &dso->symbols[type]); 462 &dso->symbols[type]);
464 } 463 }
465 464
466 int build_id__sprintf(const u8 *build_id, int len, char *bf) 465 int build_id__sprintf(const u8 *build_id, int len, char *bf)
467 { 466 {
468 char *bid = bf; 467 char *bid = bf;
469 const u8 *raw = build_id; 468 const u8 *raw = build_id;
470 int i; 469 int i;
471 470
472 for (i = 0; i < len; ++i) { 471 for (i = 0; i < len; ++i) {
473 sprintf(bid, "%02x", *raw); 472 sprintf(bid, "%02x", *raw);
474 ++raw; 473 ++raw;
475 bid += 2; 474 bid += 2;
476 } 475 }
477 476
478 return raw - build_id; 477 return raw - build_id;
479 } 478 }
480 479
481 size_t dso__fprintf_buildid(struct dso *dso, FILE *fp) 480 size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
482 { 481 {
483 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 482 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
484 483
485 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 484 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
486 return fprintf(fp, "%s", sbuild_id); 485 return fprintf(fp, "%s", sbuild_id);
487 } 486 }
488 487
489 size_t dso__fprintf_symbols_by_name(struct dso *dso, 488 size_t dso__fprintf_symbols_by_name(struct dso *dso,
490 enum map_type type, FILE *fp) 489 enum map_type type, FILE *fp)
491 { 490 {
492 size_t ret = 0; 491 size_t ret = 0;
493 struct rb_node *nd; 492 struct rb_node *nd;
494 struct symbol_name_rb_node *pos; 493 struct symbol_name_rb_node *pos;
495 494
496 for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) { 495 for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) {
497 pos = rb_entry(nd, struct symbol_name_rb_node, rb_node); 496 pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
498 fprintf(fp, "%s\n", pos->sym.name); 497 fprintf(fp, "%s\n", pos->sym.name);
499 } 498 }
500 499
501 return ret; 500 return ret;
502 } 501 }
503 502
504 size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp) 503 size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
505 { 504 {
506 struct rb_node *nd; 505 struct rb_node *nd;
507 size_t ret = fprintf(fp, "dso: %s (", dso->short_name); 506 size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
508 507
509 if (dso->short_name != dso->long_name) 508 if (dso->short_name != dso->long_name)
510 ret += fprintf(fp, "%s, ", dso->long_name); 509 ret += fprintf(fp, "%s, ", dso->long_name);
511 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type], 510 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
512 dso->loaded ? "" : "NOT "); 511 dso->loaded ? "" : "NOT ");
513 ret += dso__fprintf_buildid(dso, fp); 512 ret += dso__fprintf_buildid(dso, fp);
514 ret += fprintf(fp, ")\n"); 513 ret += fprintf(fp, ")\n");
515 for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) { 514 for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
516 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 515 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
517 ret += symbol__fprintf(pos, fp); 516 ret += symbol__fprintf(pos, fp);
518 } 517 }
519 518
520 return ret; 519 return ret;
521 } 520 }
522 521
523 int kallsyms__parse(const char *filename, void *arg, 522 int kallsyms__parse(const char *filename, void *arg,
524 int (*process_symbol)(void *arg, const char *name, 523 int (*process_symbol)(void *arg, const char *name,
525 char type, u64 start, u64 end)) 524 char type, u64 start, u64 end))
526 { 525 {
527 char *line = NULL; 526 char *line = NULL;
528 size_t n; 527 size_t n;
529 int err = -1; 528 int err = -1;
530 FILE *file = fopen(filename, "r"); 529 FILE *file = fopen(filename, "r");
531 530
532 if (file == NULL) 531 if (file == NULL)
533 goto out_failure; 532 goto out_failure;
534 533
535 err = 0; 534 err = 0;
536 535
537 while (!feof(file)) { 536 while (!feof(file)) {
538 u64 start; 537 u64 start;
539 int line_len, len; 538 int line_len, len;
540 char symbol_type; 539 char symbol_type;
541 char *symbol_name; 540 char *symbol_name;
542 541
543 line_len = getline(&line, &n, file); 542 line_len = getline(&line, &n, file);
544 if (line_len < 0 || !line) 543 if (line_len < 0 || !line)
545 break; 544 break;
546 545
547 line[--line_len] = '\0'; /* \n */ 546 line[--line_len] = '\0'; /* \n */
548 547
549 len = hex2u64(line, &start); 548 len = hex2u64(line, &start);
550 549
551 len++; 550 len++;
552 if (len + 2 >= line_len) 551 if (len + 2 >= line_len)
553 continue; 552 continue;
554 553
555 symbol_type = line[len]; 554 symbol_type = line[len];
556 len += 2; 555 len += 2;
557 symbol_name = line + len; 556 symbol_name = line + len;
558 len = line_len - len; 557 len = line_len - len;
559 558
560 if (len >= KSYM_NAME_LEN) { 559 if (len >= KSYM_NAME_LEN) {
561 err = -1; 560 err = -1;
562 break; 561 break;
563 } 562 }
564 563
565 /* 564 /*
566 * module symbols are not sorted so we add all 565 * module symbols are not sorted so we add all
567 * symbols with zero length and rely on 566 * symbols with zero length and rely on
568 * symbols__fixup_end() to fix it up. 567 * symbols__fixup_end() to fix it up.
569 */ 568 */
570 err = process_symbol(arg, symbol_name, 569 err = process_symbol(arg, symbol_name,
571 symbol_type, start, start); 570 symbol_type, start, start);
572 if (err) 571 if (err)
573 break; 572 break;
574 } 573 }
575 574
576 free(line); 575 free(line);
577 fclose(file); 576 fclose(file);
578 return err; 577 return err;
579 578
580 out_failure: 579 out_failure:
581 return -1; 580 return -1;
582 } 581 }
583 582
584 struct process_kallsyms_args { 583 struct process_kallsyms_args {
585 struct map *map; 584 struct map *map;
586 struct dso *dso; 585 struct dso *dso;
587 }; 586 };
588 587
589 static u8 kallsyms2elf_type(char type) 588 static u8 kallsyms2elf_type(char type)
590 { 589 {
591 if (type == 'W') 590 if (type == 'W')
592 return STB_WEAK; 591 return STB_WEAK;
593 592
594 return isupper(type) ? STB_GLOBAL : STB_LOCAL; 593 return isupper(type) ? STB_GLOBAL : STB_LOCAL;
595 } 594 }
596 595
597 static int map__process_kallsym_symbol(void *arg, const char *name, 596 static int map__process_kallsym_symbol(void *arg, const char *name,
598 char type, u64 start, u64 end) 597 char type, u64 start, u64 end)
599 { 598 {
600 struct symbol *sym; 599 struct symbol *sym;
601 struct process_kallsyms_args *a = arg; 600 struct process_kallsyms_args *a = arg;
602 struct rb_root *root = &a->dso->symbols[a->map->type]; 601 struct rb_root *root = &a->dso->symbols[a->map->type];
603 602
604 if (!symbol_type__is_a(type, a->map->type)) 603 if (!symbol_type__is_a(type, a->map->type))
605 return 0; 604 return 0;
606 605
607 sym = symbol__new(start, end - start + 1, 606 sym = symbol__new(start, end - start + 1,
608 kallsyms2elf_type(type), name); 607 kallsyms2elf_type(type), name);
609 if (sym == NULL) 608 if (sym == NULL)
610 return -ENOMEM; 609 return -ENOMEM;
611 /* 610 /*
612 * We will pass the symbols to the filter later, in 611 * We will pass the symbols to the filter later, in
613 * map__split_kallsyms, when we have split the maps per module 612 * map__split_kallsyms, when we have split the maps per module
614 */ 613 */
615 symbols__insert(root, sym); 614 symbols__insert(root, sym);
616 615
617 return 0; 616 return 0;
618 } 617 }
619 618
620 /* 619 /*
621 * Loads the function entries in /proc/kallsyms into kernel_map->dso, 620 * Loads the function entries in /proc/kallsyms into kernel_map->dso,
622 * so that we can in the next step set the symbol ->end address and then 621 * so that we can in the next step set the symbol ->end address and then
623 * call kernel_maps__split_kallsyms. 622 * call kernel_maps__split_kallsyms.
624 */ 623 */
625 static int dso__load_all_kallsyms(struct dso *dso, const char *filename, 624 static int dso__load_all_kallsyms(struct dso *dso, const char *filename,
626 struct map *map) 625 struct map *map)
627 { 626 {
628 struct process_kallsyms_args args = { .map = map, .dso = dso, }; 627 struct process_kallsyms_args args = { .map = map, .dso = dso, };
629 return kallsyms__parse(filename, &args, map__process_kallsym_symbol); 628 return kallsyms__parse(filename, &args, map__process_kallsym_symbol);
630 } 629 }
631 630
632 /* 631 /*
633 * Split the symbols into maps, making sure there are no overlaps, i.e. the 632 * Split the symbols into maps, making sure there are no overlaps, i.e. the
634 * kernel range is broken in several maps, named [kernel].N, as we don't have 633 * kernel range is broken in several maps, named [kernel].N, as we don't have
635 * the original ELF section names vmlinux have. 634 * the original ELF section names vmlinux have.
636 */ 635 */
637 static int dso__split_kallsyms(struct dso *dso, struct map *map, 636 static int dso__split_kallsyms(struct dso *dso, struct map *map,
638 symbol_filter_t filter) 637 symbol_filter_t filter)
639 { 638 {
640 struct map_groups *kmaps = map__kmap(map)->kmaps; 639 struct map_groups *kmaps = map__kmap(map)->kmaps;
641 struct machine *machine = kmaps->machine; 640 struct machine *machine = kmaps->machine;
642 struct map *curr_map = map; 641 struct map *curr_map = map;
643 struct symbol *pos; 642 struct symbol *pos;
644 int count = 0, moved = 0; 643 int count = 0, moved = 0;
645 struct rb_root *root = &dso->symbols[map->type]; 644 struct rb_root *root = &dso->symbols[map->type];
646 struct rb_node *next = rb_first(root); 645 struct rb_node *next = rb_first(root);
647 int kernel_range = 0; 646 int kernel_range = 0;
648 647
649 while (next) { 648 while (next) {
650 char *module; 649 char *module;
651 650
652 pos = rb_entry(next, struct symbol, rb_node); 651 pos = rb_entry(next, struct symbol, rb_node);
653 next = rb_next(&pos->rb_node); 652 next = rb_next(&pos->rb_node);
654 653
655 module = strchr(pos->name, '\t'); 654 module = strchr(pos->name, '\t');
656 if (module) { 655 if (module) {
657 if (!symbol_conf.use_modules) 656 if (!symbol_conf.use_modules)
658 goto discard_symbol; 657 goto discard_symbol;
659 658
660 *module++ = '\0'; 659 *module++ = '\0';
661 660
662 if (strcmp(curr_map->dso->short_name, module)) { 661 if (strcmp(curr_map->dso->short_name, module)) {
663 if (curr_map != map && 662 if (curr_map != map &&
664 dso->kernel == DSO_TYPE_GUEST_KERNEL && 663 dso->kernel == DSO_TYPE_GUEST_KERNEL &&
665 machine__is_default_guest(machine)) { 664 machine__is_default_guest(machine)) {
666 /* 665 /*
667 * We assume all symbols of a module are 666 * We assume all symbols of a module are
668 * continuous in * kallsyms, so curr_map 667 * continuous in * kallsyms, so curr_map
669 * points to a module and all its 668 * points to a module and all its
670 * symbols are in its kmap. Mark it as 669 * symbols are in its kmap. Mark it as
671 * loaded. 670 * loaded.
672 */ 671 */
673 dso__set_loaded(curr_map->dso, 672 dso__set_loaded(curr_map->dso,
674 curr_map->type); 673 curr_map->type);
675 } 674 }
676 675
677 curr_map = map_groups__find_by_name(kmaps, 676 curr_map = map_groups__find_by_name(kmaps,
678 map->type, module); 677 map->type, module);
679 if (curr_map == NULL) { 678 if (curr_map == NULL) {
680 pr_debug("%s/proc/{kallsyms,modules} " 679 pr_debug("%s/proc/{kallsyms,modules} "
681 "inconsistency while looking " 680 "inconsistency while looking "
682 "for \"%s\" module!\n", 681 "for \"%s\" module!\n",
683 machine->root_dir, module); 682 machine->root_dir, module);
684 curr_map = map; 683 curr_map = map;
685 goto discard_symbol; 684 goto discard_symbol;
686 } 685 }
687 686
688 if (curr_map->dso->loaded && 687 if (curr_map->dso->loaded &&
689 !machine__is_default_guest(machine)) 688 !machine__is_default_guest(machine))
690 goto discard_symbol; 689 goto discard_symbol;
691 } 690 }
692 /* 691 /*
693 * So that we look just like we get from .ko files, 692 * So that we look just like we get from .ko files,
694 * i.e. not prelinked, relative to map->start. 693 * i.e. not prelinked, relative to map->start.
695 */ 694 */
696 pos->start = curr_map->map_ip(curr_map, pos->start); 695 pos->start = curr_map->map_ip(curr_map, pos->start);
697 pos->end = curr_map->map_ip(curr_map, pos->end); 696 pos->end = curr_map->map_ip(curr_map, pos->end);
698 } else if (curr_map != map) { 697 } else if (curr_map != map) {
699 char dso_name[PATH_MAX]; 698 char dso_name[PATH_MAX];
700 struct dso *ndso; 699 struct dso *ndso;
701 700
702 if (count == 0) { 701 if (count == 0) {
703 curr_map = map; 702 curr_map = map;
704 goto filter_symbol; 703 goto filter_symbol;
705 } 704 }
706 705
707 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 706 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
708 snprintf(dso_name, sizeof(dso_name), 707 snprintf(dso_name, sizeof(dso_name),
709 "[guest.kernel].%d", 708 "[guest.kernel].%d",
710 kernel_range++); 709 kernel_range++);
711 else 710 else
712 snprintf(dso_name, sizeof(dso_name), 711 snprintf(dso_name, sizeof(dso_name),
713 "[kernel].%d", 712 "[kernel].%d",
714 kernel_range++); 713 kernel_range++);
715 714
716 ndso = dso__new(dso_name); 715 ndso = dso__new(dso_name);
717 if (ndso == NULL) 716 if (ndso == NULL)
718 return -1; 717 return -1;
719 718
720 ndso->kernel = dso->kernel; 719 ndso->kernel = dso->kernel;
721 720
722 curr_map = map__new2(pos->start, ndso, map->type); 721 curr_map = map__new2(pos->start, ndso, map->type);
723 if (curr_map == NULL) { 722 if (curr_map == NULL) {
724 dso__delete(ndso); 723 dso__delete(ndso);
725 return -1; 724 return -1;
726 } 725 }
727 726
728 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; 727 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
729 map_groups__insert(kmaps, curr_map); 728 map_groups__insert(kmaps, curr_map);
730 ++kernel_range; 729 ++kernel_range;
731 } 730 }
732 filter_symbol: 731 filter_symbol:
733 if (filter && filter(curr_map, pos)) { 732 if (filter && filter(curr_map, pos)) {
734 discard_symbol: rb_erase(&pos->rb_node, root); 733 discard_symbol: rb_erase(&pos->rb_node, root);
735 symbol__delete(pos); 734 symbol__delete(pos);
736 } else { 735 } else {
737 if (curr_map != map) { 736 if (curr_map != map) {
738 rb_erase(&pos->rb_node, root); 737 rb_erase(&pos->rb_node, root);
739 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); 738 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
740 ++moved; 739 ++moved;
741 } else 740 } else
742 ++count; 741 ++count;
743 } 742 }
744 } 743 }
745 744
746 if (curr_map != map && 745 if (curr_map != map &&
747 dso->kernel == DSO_TYPE_GUEST_KERNEL && 746 dso->kernel == DSO_TYPE_GUEST_KERNEL &&
748 machine__is_default_guest(kmaps->machine)) { 747 machine__is_default_guest(kmaps->machine)) {
749 dso__set_loaded(curr_map->dso, curr_map->type); 748 dso__set_loaded(curr_map->dso, curr_map->type);
750 } 749 }
751 750
752 return count + moved; 751 return count + moved;
753 } 752 }
754 753
755 static bool symbol__restricted_filename(const char *filename, 754 static bool symbol__restricted_filename(const char *filename,
756 const char *restricted_filename) 755 const char *restricted_filename)
757 { 756 {
758 bool restricted = false; 757 bool restricted = false;
759 758
760 if (symbol_conf.kptr_restrict) { 759 if (symbol_conf.kptr_restrict) {
761 char *r = realpath(filename, NULL); 760 char *r = realpath(filename, NULL);
762 761
763 if (r != NULL) { 762 if (r != NULL) {
764 restricted = strcmp(r, restricted_filename) == 0; 763 restricted = strcmp(r, restricted_filename) == 0;
765 free(r); 764 free(r);
766 return restricted; 765 return restricted;
767 } 766 }
768 } 767 }
769 768
770 return restricted; 769 return restricted;
771 } 770 }
772 771
773 int dso__load_kallsyms(struct dso *dso, const char *filename, 772 int dso__load_kallsyms(struct dso *dso, const char *filename,
774 struct map *map, symbol_filter_t filter) 773 struct map *map, symbol_filter_t filter)
775 { 774 {
776 if (symbol__restricted_filename(filename, "/proc/kallsyms")) 775 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
777 return -1; 776 return -1;
778 777
779 if (dso__load_all_kallsyms(dso, filename, map) < 0) 778 if (dso__load_all_kallsyms(dso, filename, map) < 0)
780 return -1; 779 return -1;
781 780
782 symbols__fixup_duplicate(&dso->symbols[map->type]); 781 symbols__fixup_duplicate(&dso->symbols[map->type]);
783 symbols__fixup_end(&dso->symbols[map->type]); 782 symbols__fixup_end(&dso->symbols[map->type]);
784 783
785 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 784 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
786 dso->symtab_type = SYMTAB__GUEST_KALLSYMS; 785 dso->symtab_type = SYMTAB__GUEST_KALLSYMS;
787 else 786 else
788 dso->symtab_type = SYMTAB__KALLSYMS; 787 dso->symtab_type = SYMTAB__KALLSYMS;
789 788
790 return dso__split_kallsyms(dso, map, filter); 789 return dso__split_kallsyms(dso, map, filter);
791 } 790 }
792 791
793 static int dso__load_perf_map(struct dso *dso, struct map *map, 792 static int dso__load_perf_map(struct dso *dso, struct map *map,
794 symbol_filter_t filter) 793 symbol_filter_t filter)
795 { 794 {
796 char *line = NULL; 795 char *line = NULL;
797 size_t n; 796 size_t n;
798 FILE *file; 797 FILE *file;
799 int nr_syms = 0; 798 int nr_syms = 0;
800 799
801 file = fopen(dso->long_name, "r"); 800 file = fopen(dso->long_name, "r");
802 if (file == NULL) 801 if (file == NULL)
803 goto out_failure; 802 goto out_failure;
804 803
805 while (!feof(file)) { 804 while (!feof(file)) {
806 u64 start, size; 805 u64 start, size;
807 struct symbol *sym; 806 struct symbol *sym;
808 int line_len, len; 807 int line_len, len;
809 808
810 line_len = getline(&line, &n, file); 809 line_len = getline(&line, &n, file);
811 if (line_len < 0) 810 if (line_len < 0)
812 break; 811 break;
813 812
814 if (!line) 813 if (!line)
815 goto out_failure; 814 goto out_failure;
816 815
817 line[--line_len] = '\0'; /* \n */ 816 line[--line_len] = '\0'; /* \n */
818 817
819 len = hex2u64(line, &start); 818 len = hex2u64(line, &start);
820 819
821 len++; 820 len++;
822 if (len + 2 >= line_len) 821 if (len + 2 >= line_len)
823 continue; 822 continue;
824 823
825 len += hex2u64(line + len, &size); 824 len += hex2u64(line + len, &size);
826 825
827 len++; 826 len++;
828 if (len + 2 >= line_len) 827 if (len + 2 >= line_len)
829 continue; 828 continue;
830 829
831 sym = symbol__new(start, size, STB_GLOBAL, line + len); 830 sym = symbol__new(start, size, STB_GLOBAL, line + len);
832 831
833 if (sym == NULL) 832 if (sym == NULL)
834 goto out_delete_line; 833 goto out_delete_line;
835 834
836 if (filter && filter(map, sym)) 835 if (filter && filter(map, sym))
837 symbol__delete(sym); 836 symbol__delete(sym);
838 else { 837 else {
839 symbols__insert(&dso->symbols[map->type], sym); 838 symbols__insert(&dso->symbols[map->type], sym);
840 nr_syms++; 839 nr_syms++;
841 } 840 }
842 } 841 }
843 842
844 free(line); 843 free(line);
845 fclose(file); 844 fclose(file);
846 845
847 return nr_syms; 846 return nr_syms;
848 847
849 out_delete_line: 848 out_delete_line:
850 free(line); 849 free(line);
851 out_failure: 850 out_failure:
852 return -1; 851 return -1;
853 } 852 }
854 853
855 /** 854 /**
856 * elf_symtab__for_each_symbol - iterate thru all the symbols 855 * elf_symtab__for_each_symbol - iterate thru all the symbols
857 * 856 *
858 * @syms: struct elf_symtab instance to iterate 857 * @syms: struct elf_symtab instance to iterate
859 * @idx: uint32_t idx 858 * @idx: uint32_t idx
860 * @sym: GElf_Sym iterator 859 * @sym: GElf_Sym iterator
861 */ 860 */
862 #define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \ 861 #define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \
863 for (idx = 0, gelf_getsym(syms, idx, &sym);\ 862 for (idx = 0, gelf_getsym(syms, idx, &sym);\
864 idx < nr_syms; \ 863 idx < nr_syms; \
865 idx++, gelf_getsym(syms, idx, &sym)) 864 idx++, gelf_getsym(syms, idx, &sym))
866 865
867 static inline uint8_t elf_sym__type(const GElf_Sym *sym) 866 static inline uint8_t elf_sym__type(const GElf_Sym *sym)
868 { 867 {
869 return GELF_ST_TYPE(sym->st_info); 868 return GELF_ST_TYPE(sym->st_info);
870 } 869 }
871 870
872 static inline int elf_sym__is_function(const GElf_Sym *sym) 871 static inline int elf_sym__is_function(const GElf_Sym *sym)
873 { 872 {
874 return elf_sym__type(sym) == STT_FUNC && 873 return elf_sym__type(sym) == STT_FUNC &&
875 sym->st_name != 0 && 874 sym->st_name != 0 &&
876 sym->st_shndx != SHN_UNDEF; 875 sym->st_shndx != SHN_UNDEF;
877 } 876 }
878 877
879 static inline bool elf_sym__is_object(const GElf_Sym *sym) 878 static inline bool elf_sym__is_object(const GElf_Sym *sym)
880 { 879 {
881 return elf_sym__type(sym) == STT_OBJECT && 880 return elf_sym__type(sym) == STT_OBJECT &&
882 sym->st_name != 0 && 881 sym->st_name != 0 &&
883 sym->st_shndx != SHN_UNDEF; 882 sym->st_shndx != SHN_UNDEF;
884 } 883 }
885 884
886 static inline int elf_sym__is_label(const GElf_Sym *sym) 885 static inline int elf_sym__is_label(const GElf_Sym *sym)
887 { 886 {
888 return elf_sym__type(sym) == STT_NOTYPE && 887 return elf_sym__type(sym) == STT_NOTYPE &&
889 sym->st_name != 0 && 888 sym->st_name != 0 &&
890 sym->st_shndx != SHN_UNDEF && 889 sym->st_shndx != SHN_UNDEF &&
891 sym->st_shndx != SHN_ABS; 890 sym->st_shndx != SHN_ABS;
892 } 891 }
893 892
894 static inline const char *elf_sec__name(const GElf_Shdr *shdr, 893 static inline const char *elf_sec__name(const GElf_Shdr *shdr,
895 const Elf_Data *secstrs) 894 const Elf_Data *secstrs)
896 { 895 {
897 return secstrs->d_buf + shdr->sh_name; 896 return secstrs->d_buf + shdr->sh_name;
898 } 897 }
899 898
900 static inline int elf_sec__is_text(const GElf_Shdr *shdr, 899 static inline int elf_sec__is_text(const GElf_Shdr *shdr,
901 const Elf_Data *secstrs) 900 const Elf_Data *secstrs)
902 { 901 {
903 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL; 902 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
904 } 903 }
905 904
906 static inline bool elf_sec__is_data(const GElf_Shdr *shdr, 905 static inline bool elf_sec__is_data(const GElf_Shdr *shdr,
907 const Elf_Data *secstrs) 906 const Elf_Data *secstrs)
908 { 907 {
909 return strstr(elf_sec__name(shdr, secstrs), "data") != NULL; 908 return strstr(elf_sec__name(shdr, secstrs), "data") != NULL;
910 } 909 }
911 910
912 static inline const char *elf_sym__name(const GElf_Sym *sym, 911 static inline const char *elf_sym__name(const GElf_Sym *sym,
913 const Elf_Data *symstrs) 912 const Elf_Data *symstrs)
914 { 913 {
915 return symstrs->d_buf + sym->st_name; 914 return symstrs->d_buf + sym->st_name;
916 } 915 }
917 916
918 static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, 917 static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
919 GElf_Shdr *shp, const char *name, 918 GElf_Shdr *shp, const char *name,
920 size_t *idx) 919 size_t *idx)
921 { 920 {
922 Elf_Scn *sec = NULL; 921 Elf_Scn *sec = NULL;
923 size_t cnt = 1; 922 size_t cnt = 1;
924 923
925 while ((sec = elf_nextscn(elf, sec)) != NULL) { 924 while ((sec = elf_nextscn(elf, sec)) != NULL) {
926 char *str; 925 char *str;
927 926
928 gelf_getshdr(sec, shp); 927 gelf_getshdr(sec, shp);
929 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); 928 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
930 if (!strcmp(name, str)) { 929 if (!strcmp(name, str)) {
931 if (idx) 930 if (idx)
932 *idx = cnt; 931 *idx = cnt;
933 break; 932 break;
934 } 933 }
935 ++cnt; 934 ++cnt;
936 } 935 }
937 936
938 return sec; 937 return sec;
939 } 938 }
940 939
941 #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \ 940 #define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
942 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \ 941 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
943 idx < nr_entries; \ 942 idx < nr_entries; \
944 ++idx, pos = gelf_getrel(reldata, idx, &pos_mem)) 943 ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
945 944
946 #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \ 945 #define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
947 for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \ 946 for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
948 idx < nr_entries; \ 947 idx < nr_entries; \
949 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) 948 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
950 949
951 /* 950 /*
952 * We need to check if we have a .dynsym, so that we can handle the 951 * We need to check if we have a .dynsym, so that we can handle the
953 * .plt, synthesizing its symbols, that aren't on the symtabs (be it 952 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
954 * .dynsym or .symtab). 953 * .dynsym or .symtab).
955 * And always look at the original dso, not at debuginfo packages, that 954 * And always look at the original dso, not at debuginfo packages, that
956 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). 955 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
957 */ 956 */
958 static int dso__synthesize_plt_symbols(struct dso *dso, struct map *map, 957 static int dso__synthesize_plt_symbols(struct dso *dso, struct map *map,
959 symbol_filter_t filter) 958 symbol_filter_t filter)
960 { 959 {
961 uint32_t nr_rel_entries, idx; 960 uint32_t nr_rel_entries, idx;
962 GElf_Sym sym; 961 GElf_Sym sym;
963 u64 plt_offset; 962 u64 plt_offset;
964 GElf_Shdr shdr_plt; 963 GElf_Shdr shdr_plt;
965 struct symbol *f; 964 struct symbol *f;
966 GElf_Shdr shdr_rel_plt, shdr_dynsym; 965 GElf_Shdr shdr_rel_plt, shdr_dynsym;
967 Elf_Data *reldata, *syms, *symstrs; 966 Elf_Data *reldata, *syms, *symstrs;
968 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym; 967 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
969 size_t dynsym_idx; 968 size_t dynsym_idx;
970 GElf_Ehdr ehdr; 969 GElf_Ehdr ehdr;
971 char sympltname[1024]; 970 char sympltname[1024];
972 Elf *elf; 971 Elf *elf;
973 int nr = 0, symidx, fd, err = 0; 972 int nr = 0, symidx, fd, err = 0;
974 char name[PATH_MAX]; 973 char name[PATH_MAX];
975 974
976 snprintf(name, sizeof(name), "%s%s", 975 snprintf(name, sizeof(name), "%s%s",
977 symbol_conf.symfs, dso->long_name); 976 symbol_conf.symfs, dso->long_name);
978 fd = open(name, O_RDONLY); 977 fd = open(name, O_RDONLY);
979 if (fd < 0) 978 if (fd < 0)
980 goto out; 979 goto out;
981 980
982 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 981 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
983 if (elf == NULL) 982 if (elf == NULL)
984 goto out_close; 983 goto out_close;
985 984
986 if (gelf_getehdr(elf, &ehdr) == NULL) 985 if (gelf_getehdr(elf, &ehdr) == NULL)
987 goto out_elf_end; 986 goto out_elf_end;
988 987
989 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym, 988 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
990 ".dynsym", &dynsym_idx); 989 ".dynsym", &dynsym_idx);
991 if (scn_dynsym == NULL) 990 if (scn_dynsym == NULL)
992 goto out_elf_end; 991 goto out_elf_end;
993 992
994 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, 993 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
995 ".rela.plt", NULL); 994 ".rela.plt", NULL);
996 if (scn_plt_rel == NULL) { 995 if (scn_plt_rel == NULL) {
997 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, 996 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
998 ".rel.plt", NULL); 997 ".rel.plt", NULL);
999 if (scn_plt_rel == NULL) 998 if (scn_plt_rel == NULL)
1000 goto out_elf_end; 999 goto out_elf_end;
1001 } 1000 }
1002 1001
1003 err = -1; 1002 err = -1;
1004 1003
1005 if (shdr_rel_plt.sh_link != dynsym_idx) 1004 if (shdr_rel_plt.sh_link != dynsym_idx)
1006 goto out_elf_end; 1005 goto out_elf_end;
1007 1006
1008 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL) 1007 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
1009 goto out_elf_end; 1008 goto out_elf_end;
1010 1009
1011 /* 1010 /*
1012 * Fetch the relocation section to find the idxes to the GOT 1011 * Fetch the relocation section to find the idxes to the GOT
1013 * and the symbols in the .dynsym they refer to. 1012 * and the symbols in the .dynsym they refer to.
1014 */ 1013 */
1015 reldata = elf_getdata(scn_plt_rel, NULL); 1014 reldata = elf_getdata(scn_plt_rel, NULL);
1016 if (reldata == NULL) 1015 if (reldata == NULL)
1017 goto out_elf_end; 1016 goto out_elf_end;
1018 1017
1019 syms = elf_getdata(scn_dynsym, NULL); 1018 syms = elf_getdata(scn_dynsym, NULL);
1020 if (syms == NULL) 1019 if (syms == NULL)
1021 goto out_elf_end; 1020 goto out_elf_end;
1022 1021
1023 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link); 1022 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
1024 if (scn_symstrs == NULL) 1023 if (scn_symstrs == NULL)
1025 goto out_elf_end; 1024 goto out_elf_end;
1026 1025
1027 symstrs = elf_getdata(scn_symstrs, NULL); 1026 symstrs = elf_getdata(scn_symstrs, NULL);
1028 if (symstrs == NULL) 1027 if (symstrs == NULL)
1029 goto out_elf_end; 1028 goto out_elf_end;
1030 1029
1031 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 1030 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
1032 plt_offset = shdr_plt.sh_offset; 1031 plt_offset = shdr_plt.sh_offset;
1033 1032
1034 if (shdr_rel_plt.sh_type == SHT_RELA) { 1033 if (shdr_rel_plt.sh_type == SHT_RELA) {
1035 GElf_Rela pos_mem, *pos; 1034 GElf_Rela pos_mem, *pos;
1036 1035
1037 elf_section__for_each_rela(reldata, pos, pos_mem, idx, 1036 elf_section__for_each_rela(reldata, pos, pos_mem, idx,
1038 nr_rel_entries) { 1037 nr_rel_entries) {
1039 symidx = GELF_R_SYM(pos->r_info); 1038 symidx = GELF_R_SYM(pos->r_info);
1040 plt_offset += shdr_plt.sh_entsize; 1039 plt_offset += shdr_plt.sh_entsize;
1041 gelf_getsym(syms, symidx, &sym); 1040 gelf_getsym(syms, symidx, &sym);
1042 snprintf(sympltname, sizeof(sympltname), 1041 snprintf(sympltname, sizeof(sympltname),
1043 "%s@plt", elf_sym__name(&sym, symstrs)); 1042 "%s@plt", elf_sym__name(&sym, symstrs));
1044 1043
1045 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 1044 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
1046 STB_GLOBAL, sympltname); 1045 STB_GLOBAL, sympltname);
1047 if (!f) 1046 if (!f)
1048 goto out_elf_end; 1047 goto out_elf_end;
1049 1048
1050 if (filter && filter(map, f)) 1049 if (filter && filter(map, f))
1051 symbol__delete(f); 1050 symbol__delete(f);
1052 else { 1051 else {
1053 symbols__insert(&dso->symbols[map->type], f); 1052 symbols__insert(&dso->symbols[map->type], f);
1054 ++nr; 1053 ++nr;
1055 } 1054 }
1056 } 1055 }
1057 } else if (shdr_rel_plt.sh_type == SHT_REL) { 1056 } else if (shdr_rel_plt.sh_type == SHT_REL) {
1058 GElf_Rel pos_mem, *pos; 1057 GElf_Rel pos_mem, *pos;
1059 elf_section__for_each_rel(reldata, pos, pos_mem, idx, 1058 elf_section__for_each_rel(reldata, pos, pos_mem, idx,
1060 nr_rel_entries) { 1059 nr_rel_entries) {
1061 symidx = GELF_R_SYM(pos->r_info); 1060 symidx = GELF_R_SYM(pos->r_info);
1062 plt_offset += shdr_plt.sh_entsize; 1061 plt_offset += shdr_plt.sh_entsize;
1063 gelf_getsym(syms, symidx, &sym); 1062 gelf_getsym(syms, symidx, &sym);
1064 snprintf(sympltname, sizeof(sympltname), 1063 snprintf(sympltname, sizeof(sympltname),
1065 "%s@plt", elf_sym__name(&sym, symstrs)); 1064 "%s@plt", elf_sym__name(&sym, symstrs));
1066 1065
1067 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 1066 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
1068 STB_GLOBAL, sympltname); 1067 STB_GLOBAL, sympltname);
1069 if (!f) 1068 if (!f)
1070 goto out_elf_end; 1069 goto out_elf_end;
1071 1070
1072 if (filter && filter(map, f)) 1071 if (filter && filter(map, f))
1073 symbol__delete(f); 1072 symbol__delete(f);
1074 else { 1073 else {
1075 symbols__insert(&dso->symbols[map->type], f); 1074 symbols__insert(&dso->symbols[map->type], f);
1076 ++nr; 1075 ++nr;
1077 } 1076 }
1078 } 1077 }
1079 } 1078 }
1080 1079
1081 err = 0; 1080 err = 0;
1082 out_elf_end: 1081 out_elf_end:
1083 elf_end(elf); 1082 elf_end(elf);
1084 out_close: 1083 out_close:
1085 close(fd); 1084 close(fd);
1086 1085
1087 if (err == 0) 1086 if (err == 0)
1088 return nr; 1087 return nr;
1089 out: 1088 out:
1090 pr_debug("%s: problems reading %s PLT info.\n", 1089 pr_debug("%s: problems reading %s PLT info.\n",
1091 __func__, dso->long_name); 1090 __func__, dso->long_name);
1092 return 0; 1091 return 0;
1093 } 1092 }
1094 1093
1095 static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type) 1094 static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type)
1096 { 1095 {
1097 switch (type) { 1096 switch (type) {
1098 case MAP__FUNCTION: 1097 case MAP__FUNCTION:
1099 return elf_sym__is_function(sym); 1098 return elf_sym__is_function(sym);
1100 case MAP__VARIABLE: 1099 case MAP__VARIABLE:
1101 return elf_sym__is_object(sym); 1100 return elf_sym__is_object(sym);
1102 default: 1101 default:
1103 return false; 1102 return false;
1104 } 1103 }
1105 } 1104 }
1106 1105
1107 static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs, 1106 static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs,
1108 enum map_type type) 1107 enum map_type type)
1109 { 1108 {
1110 switch (type) { 1109 switch (type) {
1111 case MAP__FUNCTION: 1110 case MAP__FUNCTION:
1112 return elf_sec__is_text(shdr, secstrs); 1111 return elf_sec__is_text(shdr, secstrs);
1113 case MAP__VARIABLE: 1112 case MAP__VARIABLE:
1114 return elf_sec__is_data(shdr, secstrs); 1113 return elf_sec__is_data(shdr, secstrs);
1115 default: 1114 default:
1116 return false; 1115 return false;
1117 } 1116 }
1118 } 1117 }
1119 1118
1120 static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr) 1119 static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
1121 { 1120 {
1122 Elf_Scn *sec = NULL; 1121 Elf_Scn *sec = NULL;
1123 GElf_Shdr shdr; 1122 GElf_Shdr shdr;
1124 size_t cnt = 1; 1123 size_t cnt = 1;
1125 1124
1126 while ((sec = elf_nextscn(elf, sec)) != NULL) { 1125 while ((sec = elf_nextscn(elf, sec)) != NULL) {
1127 gelf_getshdr(sec, &shdr); 1126 gelf_getshdr(sec, &shdr);
1128 1127
1129 if ((addr >= shdr.sh_addr) && 1128 if ((addr >= shdr.sh_addr) &&
1130 (addr < (shdr.sh_addr + shdr.sh_size))) 1129 (addr < (shdr.sh_addr + shdr.sh_size)))
1131 return cnt; 1130 return cnt;
1132 1131
1133 ++cnt; 1132 ++cnt;
1134 } 1133 }
1135 1134
1136 return -1; 1135 return -1;
1137 } 1136 }
1138 1137
1139 static int dso__load_sym(struct dso *dso, struct map *map, const char *name, 1138 static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
1140 int fd, symbol_filter_t filter, int kmodule, 1139 int fd, symbol_filter_t filter, int kmodule,
1141 int want_symtab) 1140 int want_symtab)
1142 { 1141 {
1143 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; 1142 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
1144 struct map *curr_map = map; 1143 struct map *curr_map = map;
1145 struct dso *curr_dso = dso; 1144 struct dso *curr_dso = dso;
1146 Elf_Data *symstrs, *secstrs; 1145 Elf_Data *symstrs, *secstrs;
1147 uint32_t nr_syms; 1146 uint32_t nr_syms;
1148 int err = -1; 1147 int err = -1;
1149 uint32_t idx; 1148 uint32_t idx;
1150 GElf_Ehdr ehdr; 1149 GElf_Ehdr ehdr;
1151 GElf_Shdr shdr, opdshdr; 1150 GElf_Shdr shdr, opdshdr;
1152 Elf_Data *syms, *opddata = NULL; 1151 Elf_Data *syms, *opddata = NULL;
1153 GElf_Sym sym; 1152 GElf_Sym sym;
1154 Elf_Scn *sec, *sec_strndx, *opdsec; 1153 Elf_Scn *sec, *sec_strndx, *opdsec;
1155 Elf *elf; 1154 Elf *elf;
1156 int nr = 0; 1155 int nr = 0;
1157 size_t opdidx = 0; 1156 size_t opdidx = 0;
1158 1157
1159 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 1158 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1160 if (elf == NULL) { 1159 if (elf == NULL) {
1161 pr_debug("%s: cannot read %s ELF file.\n", __func__, name); 1160 pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
1162 goto out_close; 1161 goto out_close;
1163 } 1162 }
1164 1163
1165 if (gelf_getehdr(elf, &ehdr) == NULL) { 1164 if (gelf_getehdr(elf, &ehdr) == NULL) {
1166 pr_debug("%s: cannot get elf header.\n", __func__); 1165 pr_debug("%s: cannot get elf header.\n", __func__);
1167 goto out_elf_end; 1166 goto out_elf_end;
1168 } 1167 }
1169 1168
1170 /* Always reject images with a mismatched build-id: */ 1169 /* Always reject images with a mismatched build-id: */
1171 if (dso->has_build_id) { 1170 if (dso->has_build_id) {
1172 u8 build_id[BUILD_ID_SIZE]; 1171 u8 build_id[BUILD_ID_SIZE];
1173 1172
1174 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) 1173 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
1175 goto out_elf_end; 1174 goto out_elf_end;
1176 1175
1177 if (!dso__build_id_equal(dso, build_id)) 1176 if (!dso__build_id_equal(dso, build_id))
1178 goto out_elf_end; 1177 goto out_elf_end;
1179 } 1178 }
1180 1179
1181 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 1180 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
1182 if (sec == NULL) { 1181 if (sec == NULL) {
1183 if (want_symtab) 1182 if (want_symtab)
1184 goto out_elf_end; 1183 goto out_elf_end;
1185 1184
1186 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); 1185 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
1187 if (sec == NULL) 1186 if (sec == NULL)
1188 goto out_elf_end; 1187 goto out_elf_end;
1189 } 1188 }
1190 1189
1191 opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx); 1190 opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx);
1192 if (opdshdr.sh_type != SHT_PROGBITS) 1191 if (opdshdr.sh_type != SHT_PROGBITS)
1193 opdsec = NULL; 1192 opdsec = NULL;
1194 if (opdsec) 1193 if (opdsec)
1195 opddata = elf_rawdata(opdsec, NULL); 1194 opddata = elf_rawdata(opdsec, NULL);
1196 1195
1197 syms = elf_getdata(sec, NULL); 1196 syms = elf_getdata(sec, NULL);
1198 if (syms == NULL) 1197 if (syms == NULL)
1199 goto out_elf_end; 1198 goto out_elf_end;
1200 1199
1201 sec = elf_getscn(elf, shdr.sh_link); 1200 sec = elf_getscn(elf, shdr.sh_link);
1202 if (sec == NULL) 1201 if (sec == NULL)
1203 goto out_elf_end; 1202 goto out_elf_end;
1204 1203
1205 symstrs = elf_getdata(sec, NULL); 1204 symstrs = elf_getdata(sec, NULL);
1206 if (symstrs == NULL) 1205 if (symstrs == NULL)
1207 goto out_elf_end; 1206 goto out_elf_end;
1208 1207
1209 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); 1208 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
1210 if (sec_strndx == NULL) 1209 if (sec_strndx == NULL)
1211 goto out_elf_end; 1210 goto out_elf_end;
1212 1211
1213 secstrs = elf_getdata(sec_strndx, NULL); 1212 secstrs = elf_getdata(sec_strndx, NULL);
1214 if (secstrs == NULL) 1213 if (secstrs == NULL)
1215 goto out_elf_end; 1214 goto out_elf_end;
1216 1215
1217 nr_syms = shdr.sh_size / shdr.sh_entsize; 1216 nr_syms = shdr.sh_size / shdr.sh_entsize;
1218 1217
1219 memset(&sym, 0, sizeof(sym)); 1218 memset(&sym, 0, sizeof(sym));
1220 if (dso->kernel == DSO_TYPE_USER) { 1219 if (dso->kernel == DSO_TYPE_USER) {
1221 dso->adjust_symbols = (ehdr.e_type == ET_EXEC || 1220 dso->adjust_symbols = (ehdr.e_type == ET_EXEC ||
1222 elf_section_by_name(elf, &ehdr, &shdr, 1221 elf_section_by_name(elf, &ehdr, &shdr,
1223 ".gnu.prelink_undo", 1222 ".gnu.prelink_undo",
1224 NULL) != NULL); 1223 NULL) != NULL);
1225 } else { 1224 } else {
1226 dso->adjust_symbols = 0; 1225 dso->adjust_symbols = 0;
1227 } 1226 }
1228 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { 1227 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
1229 struct symbol *f; 1228 struct symbol *f;
1230 const char *elf_name = elf_sym__name(&sym, symstrs); 1229 const char *elf_name = elf_sym__name(&sym, symstrs);
1231 char *demangled = NULL; 1230 char *demangled = NULL;
1232 int is_label = elf_sym__is_label(&sym); 1231 int is_label = elf_sym__is_label(&sym);
1233 const char *section_name; 1232 const char *section_name;
1234 1233
1235 if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name && 1234 if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
1236 strcmp(elf_name, kmap->ref_reloc_sym->name) == 0) 1235 strcmp(elf_name, kmap->ref_reloc_sym->name) == 0)
1237 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value; 1236 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
1238 1237
1239 if (!is_label && !elf_sym__is_a(&sym, map->type)) 1238 if (!is_label && !elf_sym__is_a(&sym, map->type))
1240 continue; 1239 continue;
1241 1240
1242 /* Reject ARM ELF "mapping symbols": these aren't unique and 1241 /* Reject ARM ELF "mapping symbols": these aren't unique and
1243 * don't identify functions, so will confuse the profile 1242 * don't identify functions, so will confuse the profile
1244 * output: */ 1243 * output: */
1245 if (ehdr.e_machine == EM_ARM) { 1244 if (ehdr.e_machine == EM_ARM) {
1246 if (!strcmp(elf_name, "$a") || 1245 if (!strcmp(elf_name, "$a") ||
1247 !strcmp(elf_name, "$d") || 1246 !strcmp(elf_name, "$d") ||
1248 !strcmp(elf_name, "$t")) 1247 !strcmp(elf_name, "$t"))
1249 continue; 1248 continue;
1250 } 1249 }
1251 1250
1252 if (opdsec && sym.st_shndx == opdidx) { 1251 if (opdsec && sym.st_shndx == opdidx) {
1253 u32 offset = sym.st_value - opdshdr.sh_addr; 1252 u32 offset = sym.st_value - opdshdr.sh_addr;
1254 u64 *opd = opddata->d_buf + offset; 1253 u64 *opd = opddata->d_buf + offset;
1255 sym.st_value = *opd; 1254 sym.st_value = *opd;
1256 sym.st_shndx = elf_addr_to_index(elf, sym.st_value); 1255 sym.st_shndx = elf_addr_to_index(elf, sym.st_value);
1257 } 1256 }
1258 1257
1259 sec = elf_getscn(elf, sym.st_shndx); 1258 sec = elf_getscn(elf, sym.st_shndx);
1260 if (!sec) 1259 if (!sec)
1261 goto out_elf_end; 1260 goto out_elf_end;
1262 1261
1263 gelf_getshdr(sec, &shdr); 1262 gelf_getshdr(sec, &shdr);
1264 1263
1265 if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type)) 1264 if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type))
1266 continue; 1265 continue;
1267 1266
1268 section_name = elf_sec__name(&shdr, secstrs); 1267 section_name = elf_sec__name(&shdr, secstrs);
1269 1268
1270 /* On ARM, symbols for thumb functions have 1 added to 1269 /* On ARM, symbols for thumb functions have 1 added to
1271 * the symbol address as a flag - remove it */ 1270 * the symbol address as a flag - remove it */
1272 if ((ehdr.e_machine == EM_ARM) && 1271 if ((ehdr.e_machine == EM_ARM) &&
1273 (map->type == MAP__FUNCTION) && 1272 (map->type == MAP__FUNCTION) &&
1274 (sym.st_value & 1)) 1273 (sym.st_value & 1))
1275 --sym.st_value; 1274 --sym.st_value;
1276 1275
1277 if (dso->kernel != DSO_TYPE_USER || kmodule) { 1276 if (dso->kernel != DSO_TYPE_USER || kmodule) {
1278 char dso_name[PATH_MAX]; 1277 char dso_name[PATH_MAX];
1279 1278
1280 if (strcmp(section_name, 1279 if (strcmp(section_name,
1281 (curr_dso->short_name + 1280 (curr_dso->short_name +
1282 dso->short_name_len)) == 0) 1281 dso->short_name_len)) == 0)
1283 goto new_symbol; 1282 goto new_symbol;
1284 1283
1285 if (strcmp(section_name, ".text") == 0) { 1284 if (strcmp(section_name, ".text") == 0) {
1286 curr_map = map; 1285 curr_map = map;
1287 curr_dso = dso; 1286 curr_dso = dso;
1288 goto new_symbol; 1287 goto new_symbol;
1289 } 1288 }
1290 1289
1291 snprintf(dso_name, sizeof(dso_name), 1290 snprintf(dso_name, sizeof(dso_name),
1292 "%s%s", dso->short_name, section_name); 1291 "%s%s", dso->short_name, section_name);
1293 1292
1294 curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name); 1293 curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
1295 if (curr_map == NULL) { 1294 if (curr_map == NULL) {
1296 u64 start = sym.st_value; 1295 u64 start = sym.st_value;
1297 1296
1298 if (kmodule) 1297 if (kmodule)
1299 start += map->start + shdr.sh_offset; 1298 start += map->start + shdr.sh_offset;
1300 1299
1301 curr_dso = dso__new(dso_name); 1300 curr_dso = dso__new(dso_name);
1302 if (curr_dso == NULL) 1301 if (curr_dso == NULL)
1303 goto out_elf_end; 1302 goto out_elf_end;
1304 curr_dso->kernel = dso->kernel; 1303 curr_dso->kernel = dso->kernel;
1305 curr_dso->long_name = dso->long_name; 1304 curr_dso->long_name = dso->long_name;
1306 curr_dso->long_name_len = dso->long_name_len; 1305 curr_dso->long_name_len = dso->long_name_len;
1307 curr_map = map__new2(start, curr_dso, 1306 curr_map = map__new2(start, curr_dso,
1308 map->type); 1307 map->type);
1309 if (curr_map == NULL) { 1308 if (curr_map == NULL) {
1310 dso__delete(curr_dso); 1309 dso__delete(curr_dso);
1311 goto out_elf_end; 1310 goto out_elf_end;
1312 } 1311 }
1313 curr_map->map_ip = identity__map_ip; 1312 curr_map->map_ip = identity__map_ip;
1314 curr_map->unmap_ip = identity__map_ip; 1313 curr_map->unmap_ip = identity__map_ip;
1315 curr_dso->symtab_type = dso->symtab_type; 1314 curr_dso->symtab_type = dso->symtab_type;
1316 map_groups__insert(kmap->kmaps, curr_map); 1315 map_groups__insert(kmap->kmaps, curr_map);
1317 dsos__add(&dso->node, curr_dso); 1316 dsos__add(&dso->node, curr_dso);
1318 dso__set_loaded(curr_dso, map->type); 1317 dso__set_loaded(curr_dso, map->type);
1319 } else 1318 } else
1320 curr_dso = curr_map->dso; 1319 curr_dso = curr_map->dso;
1321 1320
1322 goto new_symbol; 1321 goto new_symbol;
1323 } 1322 }
1324 1323
1325 if (curr_dso->adjust_symbols) { 1324 if (curr_dso->adjust_symbols) {
1326 pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " 1325 pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
1327 "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__, 1326 "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
1328 (u64)sym.st_value, (u64)shdr.sh_addr, 1327 (u64)sym.st_value, (u64)shdr.sh_addr,
1329 (u64)shdr.sh_offset); 1328 (u64)shdr.sh_offset);
1330 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 1329 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
1331 } 1330 }
1332 /* 1331 /*
1333 * We need to figure out if the object was created from C++ sources 1332 * We need to figure out if the object was created from C++ sources
1334 * DWARF DW_compile_unit has this, but we don't always have access 1333 * DWARF DW_compile_unit has this, but we don't always have access
1335 * to it... 1334 * to it...
1336 */ 1335 */
1337 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI); 1336 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
1338 if (demangled != NULL) 1337 if (demangled != NULL)
1339 elf_name = demangled; 1338 elf_name = demangled;
1340 new_symbol: 1339 new_symbol:
1341 f = symbol__new(sym.st_value, sym.st_size, 1340 f = symbol__new(sym.st_value, sym.st_size,
1342 GELF_ST_BIND(sym.st_info), elf_name); 1341 GELF_ST_BIND(sym.st_info), elf_name);
1343 free(demangled); 1342 free(demangled);
1344 if (!f) 1343 if (!f)
1345 goto out_elf_end; 1344 goto out_elf_end;
1346 1345
1347 if (filter && filter(curr_map, f)) 1346 if (filter && filter(curr_map, f))
1348 symbol__delete(f); 1347 symbol__delete(f);
1349 else { 1348 else {
1350 symbols__insert(&curr_dso->symbols[curr_map->type], f); 1349 symbols__insert(&curr_dso->symbols[curr_map->type], f);
1351 nr++; 1350 nr++;
1352 } 1351 }
1353 } 1352 }
1354 1353
1355 /* 1354 /*
1356 * For misannotated, zeroed, ASM function sizes. 1355 * For misannotated, zeroed, ASM function sizes.
1357 */ 1356 */
1358 if (nr > 0) { 1357 if (nr > 0) {
1359 symbols__fixup_duplicate(&dso->symbols[map->type]); 1358 symbols__fixup_duplicate(&dso->symbols[map->type]);
1360 symbols__fixup_end(&dso->symbols[map->type]); 1359 symbols__fixup_end(&dso->symbols[map->type]);
1361 if (kmap) { 1360 if (kmap) {
1362 /* 1361 /*
1363 * We need to fixup this here too because we create new 1362 * We need to fixup this here too because we create new
1364 * maps here, for things like vsyscall sections. 1363 * maps here, for things like vsyscall sections.
1365 */ 1364 */
1366 __map_groups__fixup_end(kmap->kmaps, map->type); 1365 __map_groups__fixup_end(kmap->kmaps, map->type);
1367 } 1366 }
1368 } 1367 }
1369 err = nr; 1368 err = nr;
1370 out_elf_end: 1369 out_elf_end:
1371 elf_end(elf); 1370 elf_end(elf);
1372 out_close: 1371 out_close:
1373 return err; 1372 return err;
1374 } 1373 }
1375 1374
1376 static bool dso__build_id_equal(const struct dso *dso, u8 *build_id) 1375 static bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
1377 { 1376 {
1378 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0; 1377 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
1379 } 1378 }
1380 1379
1381 bool __dsos__read_build_ids(struct list_head *head, bool with_hits) 1380 bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1382 { 1381 {
1383 bool have_build_id = false; 1382 bool have_build_id = false;
1384 struct dso *pos; 1383 struct dso *pos;
1385 1384
1386 list_for_each_entry(pos, head, node) { 1385 list_for_each_entry(pos, head, node) {
1387 if (with_hits && !pos->hit) 1386 if (with_hits && !pos->hit)
1388 continue; 1387 continue;
1389 if (pos->has_build_id) { 1388 if (pos->has_build_id) {
1390 have_build_id = true; 1389 have_build_id = true;
1391 continue; 1390 continue;
1392 } 1391 }
1393 if (filename__read_build_id(pos->long_name, pos->build_id, 1392 if (filename__read_build_id(pos->long_name, pos->build_id,
1394 sizeof(pos->build_id)) > 0) { 1393 sizeof(pos->build_id)) > 0) {
1395 have_build_id = true; 1394 have_build_id = true;
1396 pos->has_build_id = true; 1395 pos->has_build_id = true;
1397 } 1396 }
1398 } 1397 }
1399 1398
1400 return have_build_id; 1399 return have_build_id;
1401 } 1400 }
1402 1401
1403 /* 1402 /*
1404 * Align offset to 4 bytes as needed for note name and descriptor data. 1403 * Align offset to 4 bytes as needed for note name and descriptor data.
1405 */ 1404 */
1406 #define NOTE_ALIGN(n) (((n) + 3) & -4U) 1405 #define NOTE_ALIGN(n) (((n) + 3) & -4U)
1407 1406
1408 static int elf_read_build_id(Elf *elf, void *bf, size_t size) 1407 static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1409 { 1408 {
1410 int err = -1; 1409 int err = -1;
1411 GElf_Ehdr ehdr; 1410 GElf_Ehdr ehdr;
1412 GElf_Shdr shdr; 1411 GElf_Shdr shdr;
1413 Elf_Data *data; 1412 Elf_Data *data;
1414 Elf_Scn *sec; 1413 Elf_Scn *sec;
1415 Elf_Kind ek; 1414 Elf_Kind ek;
1416 void *ptr; 1415 void *ptr;
1417 1416
1418 if (size < BUILD_ID_SIZE) 1417 if (size < BUILD_ID_SIZE)
1419 goto out; 1418 goto out;
1420 1419
1421 ek = elf_kind(elf); 1420 ek = elf_kind(elf);
1422 if (ek != ELF_K_ELF) 1421 if (ek != ELF_K_ELF)
1423 goto out; 1422 goto out;
1424 1423
1425 if (gelf_getehdr(elf, &ehdr) == NULL) { 1424 if (gelf_getehdr(elf, &ehdr) == NULL) {
1426 pr_err("%s: cannot get elf header.\n", __func__); 1425 pr_err("%s: cannot get elf header.\n", __func__);
1427 goto out; 1426 goto out;
1428 } 1427 }
1429 1428
1430 sec = elf_section_by_name(elf, &ehdr, &shdr, 1429 sec = elf_section_by_name(elf, &ehdr, &shdr,
1431 ".note.gnu.build-id", NULL); 1430 ".note.gnu.build-id", NULL);
1432 if (sec == NULL) { 1431 if (sec == NULL) {
1433 sec = elf_section_by_name(elf, &ehdr, &shdr, 1432 sec = elf_section_by_name(elf, &ehdr, &shdr,
1434 ".notes", NULL); 1433 ".notes", NULL);
1435 if (sec == NULL) 1434 if (sec == NULL)
1436 goto out; 1435 goto out;
1437 } 1436 }
1438 1437
1439 data = elf_getdata(sec, NULL); 1438 data = elf_getdata(sec, NULL);
1440 if (data == NULL) 1439 if (data == NULL)
1441 goto out; 1440 goto out;
1442 1441
1443 ptr = data->d_buf; 1442 ptr = data->d_buf;
1444 while (ptr < (data->d_buf + data->d_size)) { 1443 while (ptr < (data->d_buf + data->d_size)) {
1445 GElf_Nhdr *nhdr = ptr; 1444 GElf_Nhdr *nhdr = ptr;
1446 size_t namesz = NOTE_ALIGN(nhdr->n_namesz), 1445 size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
1447 descsz = NOTE_ALIGN(nhdr->n_descsz); 1446 descsz = NOTE_ALIGN(nhdr->n_descsz);
1448 const char *name; 1447 const char *name;
1449 1448
1450 ptr += sizeof(*nhdr); 1449 ptr += sizeof(*nhdr);
1451 name = ptr; 1450 name = ptr;
1452 ptr += namesz; 1451 ptr += namesz;
1453 if (nhdr->n_type == NT_GNU_BUILD_ID && 1452 if (nhdr->n_type == NT_GNU_BUILD_ID &&
1454 nhdr->n_namesz == sizeof("GNU")) { 1453 nhdr->n_namesz == sizeof("GNU")) {
1455 if (memcmp(name, "GNU", sizeof("GNU")) == 0) { 1454 if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
1456 size_t sz = min(size, descsz); 1455 size_t sz = min(size, descsz);
1457 memcpy(bf, ptr, sz); 1456 memcpy(bf, ptr, sz);
1458 memset(bf + sz, 0, size - sz); 1457 memset(bf + sz, 0, size - sz);
1459 err = descsz; 1458 err = descsz;
1460 break; 1459 break;
1461 } 1460 }
1462 } 1461 }
1463 ptr += descsz; 1462 ptr += descsz;
1464 } 1463 }
1465 1464
1466 out: 1465 out:
1467 return err; 1466 return err;
1468 } 1467 }
1469 1468
1470 int filename__read_build_id(const char *filename, void *bf, size_t size) 1469 int filename__read_build_id(const char *filename, void *bf, size_t size)
1471 { 1470 {
1472 int fd, err = -1; 1471 int fd, err = -1;
1473 Elf *elf; 1472 Elf *elf;
1474 1473
1475 if (size < BUILD_ID_SIZE) 1474 if (size < BUILD_ID_SIZE)
1476 goto out; 1475 goto out;
1477 1476
1478 fd = open(filename, O_RDONLY); 1477 fd = open(filename, O_RDONLY);
1479 if (fd < 0) 1478 if (fd < 0)
1480 goto out; 1479 goto out;
1481 1480
1482 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 1481 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1483 if (elf == NULL) { 1482 if (elf == NULL) {
1484 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); 1483 pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
1485 goto out_close; 1484 goto out_close;
1486 } 1485 }
1487 1486
1488 err = elf_read_build_id(elf, bf, size); 1487 err = elf_read_build_id(elf, bf, size);
1489 1488
1490 elf_end(elf); 1489 elf_end(elf);
1491 out_close: 1490 out_close:
1492 close(fd); 1491 close(fd);
1493 out: 1492 out:
1494 return err; 1493 return err;
1495 } 1494 }
1496 1495
1497 int sysfs__read_build_id(const char *filename, void *build_id, size_t size) 1496 int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
1498 { 1497 {
1499 int fd, err = -1; 1498 int fd, err = -1;
1500 1499
1501 if (size < BUILD_ID_SIZE) 1500 if (size < BUILD_ID_SIZE)
1502 goto out; 1501 goto out;
1503 1502
1504 fd = open(filename, O_RDONLY); 1503 fd = open(filename, O_RDONLY);
1505 if (fd < 0) 1504 if (fd < 0)
1506 goto out; 1505 goto out;
1507 1506
1508 while (1) { 1507 while (1) {
1509 char bf[BUFSIZ]; 1508 char bf[BUFSIZ];
1510 GElf_Nhdr nhdr; 1509 GElf_Nhdr nhdr;
1511 size_t namesz, descsz; 1510 size_t namesz, descsz;
1512 1511
1513 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr)) 1512 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
1514 break; 1513 break;
1515 1514
1516 namesz = NOTE_ALIGN(nhdr.n_namesz); 1515 namesz = NOTE_ALIGN(nhdr.n_namesz);
1517 descsz = NOTE_ALIGN(nhdr.n_descsz); 1516 descsz = NOTE_ALIGN(nhdr.n_descsz);
1518 if (nhdr.n_type == NT_GNU_BUILD_ID && 1517 if (nhdr.n_type == NT_GNU_BUILD_ID &&
1519 nhdr.n_namesz == sizeof("GNU")) { 1518 nhdr.n_namesz == sizeof("GNU")) {
1520 if (read(fd, bf, namesz) != (ssize_t)namesz) 1519 if (read(fd, bf, namesz) != (ssize_t)namesz)
1521 break; 1520 break;
1522 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) { 1521 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
1523 size_t sz = min(descsz, size); 1522 size_t sz = min(descsz, size);
1524 if (read(fd, build_id, sz) == (ssize_t)sz) { 1523 if (read(fd, build_id, sz) == (ssize_t)sz) {
1525 memset(build_id + sz, 0, size - sz); 1524 memset(build_id + sz, 0, size - sz);
1526 err = 0; 1525 err = 0;
1527 break; 1526 break;
1528 } 1527 }
1529 } else if (read(fd, bf, descsz) != (ssize_t)descsz) 1528 } else if (read(fd, bf, descsz) != (ssize_t)descsz)
1530 break; 1529 break;
1531 } else { 1530 } else {
1532 int n = namesz + descsz; 1531 int n = namesz + descsz;
1533 if (read(fd, bf, n) != n) 1532 if (read(fd, bf, n) != n)
1534 break; 1533 break;
1535 } 1534 }
1536 } 1535 }
1537 close(fd); 1536 close(fd);
1538 out: 1537 out:
1539 return err; 1538 return err;
1540 } 1539 }
1541 1540
1542 char dso__symtab_origin(const struct dso *dso) 1541 char dso__symtab_origin(const struct dso *dso)
1543 { 1542 {
1544 static const char origin[] = { 1543 static const char origin[] = {
1545 [SYMTAB__KALLSYMS] = 'k', 1544 [SYMTAB__KALLSYMS] = 'k',
1546 [SYMTAB__JAVA_JIT] = 'j', 1545 [SYMTAB__JAVA_JIT] = 'j',
1547 [SYMTAB__BUILD_ID_CACHE] = 'B', 1546 [SYMTAB__BUILD_ID_CACHE] = 'B',
1548 [SYMTAB__FEDORA_DEBUGINFO] = 'f', 1547 [SYMTAB__FEDORA_DEBUGINFO] = 'f',
1549 [SYMTAB__UBUNTU_DEBUGINFO] = 'u', 1548 [SYMTAB__UBUNTU_DEBUGINFO] = 'u',
1550 [SYMTAB__BUILDID_DEBUGINFO] = 'b', 1549 [SYMTAB__BUILDID_DEBUGINFO] = 'b',
1551 [SYMTAB__SYSTEM_PATH_DSO] = 'd', 1550 [SYMTAB__SYSTEM_PATH_DSO] = 'd',
1552 [SYMTAB__SYSTEM_PATH_KMODULE] = 'K', 1551 [SYMTAB__SYSTEM_PATH_KMODULE] = 'K',
1553 [SYMTAB__GUEST_KALLSYMS] = 'g', 1552 [SYMTAB__GUEST_KALLSYMS] = 'g',
1554 [SYMTAB__GUEST_KMODULE] = 'G', 1553 [SYMTAB__GUEST_KMODULE] = 'G',
1555 }; 1554 };
1556 1555
1557 if (dso == NULL || dso->symtab_type == SYMTAB__NOT_FOUND) 1556 if (dso == NULL || dso->symtab_type == SYMTAB__NOT_FOUND)
1558 return '!'; 1557 return '!';
1559 return origin[dso->symtab_type]; 1558 return origin[dso->symtab_type];
1560 } 1559 }
1561 1560
1562 int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) 1561 int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1563 { 1562 {
1564 int size = PATH_MAX; 1563 int size = PATH_MAX;
1565 char *name; 1564 char *name;
1566 int ret = -1; 1565 int ret = -1;
1567 int fd; 1566 int fd;
1568 struct machine *machine; 1567 struct machine *machine;
1569 const char *root_dir; 1568 const char *root_dir;
1570 int want_symtab; 1569 int want_symtab;
1571 1570
1572 dso__set_loaded(dso, map->type); 1571 dso__set_loaded(dso, map->type);
1573 1572
1574 if (dso->kernel == DSO_TYPE_KERNEL) 1573 if (dso->kernel == DSO_TYPE_KERNEL)
1575 return dso__load_kernel_sym(dso, map, filter); 1574 return dso__load_kernel_sym(dso, map, filter);
1576 else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1575 else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1577 return dso__load_guest_kernel_sym(dso, map, filter); 1576 return dso__load_guest_kernel_sym(dso, map, filter);
1578 1577
1579 if (map->groups && map->groups->machine) 1578 if (map->groups && map->groups->machine)
1580 machine = map->groups->machine; 1579 machine = map->groups->machine;
1581 else 1580 else
1582 machine = NULL; 1581 machine = NULL;
1583 1582
1584 name = malloc(size); 1583 name = malloc(size);
1585 if (!name) 1584 if (!name)
1586 return -1; 1585 return -1;
1587 1586
1588 dso->adjust_symbols = 0; 1587 dso->adjust_symbols = 0;
1589 1588
1590 if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { 1589 if (strncmp(dso->name, "/tmp/perf-", 10) == 0) {
1591 struct stat st; 1590 struct stat st;
1592 1591
1593 if (lstat(dso->name, &st) < 0) 1592 if (lstat(dso->name, &st) < 0)
1594 return -1; 1593 return -1;
1595 1594
1596 if (st.st_uid && (st.st_uid != geteuid())) { 1595 if (st.st_uid && (st.st_uid != geteuid())) {
1597 pr_warning("File %s not owned by current user or root, " 1596 pr_warning("File %s not owned by current user or root, "
1598 "ignoring it.\n", dso->name); 1597 "ignoring it.\n", dso->name);
1599 return -1; 1598 return -1;
1600 } 1599 }
1601 1600
1602 ret = dso__load_perf_map(dso, map, filter); 1601 ret = dso__load_perf_map(dso, map, filter);
1603 dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : 1602 dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT :
1604 SYMTAB__NOT_FOUND; 1603 SYMTAB__NOT_FOUND;
1605 return ret; 1604 return ret;
1606 } 1605 }
1607 1606
1608 /* Iterate over candidate debug images. 1607 /* Iterate over candidate debug images.
1609 * On the first pass, only load images if they have a full symtab. 1608 * On the first pass, only load images if they have a full symtab.
1610 * Failing that, do a second pass where we accept .dynsym also 1609 * Failing that, do a second pass where we accept .dynsym also
1611 */ 1610 */
1612 want_symtab = 1; 1611 want_symtab = 1;
1613 restart: 1612 restart:
1614 for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE; 1613 for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE;
1615 dso->symtab_type != SYMTAB__NOT_FOUND; 1614 dso->symtab_type != SYMTAB__NOT_FOUND;
1616 dso->symtab_type++) { 1615 dso->symtab_type++) {
1617 switch (dso->symtab_type) { 1616 switch (dso->symtab_type) {
1618 case SYMTAB__BUILD_ID_CACHE: 1617 case SYMTAB__BUILD_ID_CACHE:
1619 /* skip the locally configured cache if a symfs is given */ 1618 /* skip the locally configured cache if a symfs is given */
1620 if (symbol_conf.symfs[0] || 1619 if (symbol_conf.symfs[0] ||
1621 (dso__build_id_filename(dso, name, size) == NULL)) { 1620 (dso__build_id_filename(dso, name, size) == NULL)) {
1622 continue; 1621 continue;
1623 } 1622 }
1624 break; 1623 break;
1625 case SYMTAB__FEDORA_DEBUGINFO: 1624 case SYMTAB__FEDORA_DEBUGINFO:
1626 snprintf(name, size, "%s/usr/lib/debug%s.debug", 1625 snprintf(name, size, "%s/usr/lib/debug%s.debug",
1627 symbol_conf.symfs, dso->long_name); 1626 symbol_conf.symfs, dso->long_name);
1628 break; 1627 break;
1629 case SYMTAB__UBUNTU_DEBUGINFO: 1628 case SYMTAB__UBUNTU_DEBUGINFO:
1630 snprintf(name, size, "%s/usr/lib/debug%s", 1629 snprintf(name, size, "%s/usr/lib/debug%s",
1631 symbol_conf.symfs, dso->long_name); 1630 symbol_conf.symfs, dso->long_name);
1632 break; 1631 break;
1633 case SYMTAB__BUILDID_DEBUGINFO: { 1632 case SYMTAB__BUILDID_DEBUGINFO: {
1634 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 1633 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1635 1634
1636 if (!dso->has_build_id) 1635 if (!dso->has_build_id)
1637 continue; 1636 continue;
1638 1637
1639 build_id__sprintf(dso->build_id, 1638 build_id__sprintf(dso->build_id,
1640 sizeof(dso->build_id), 1639 sizeof(dso->build_id),
1641 build_id_hex); 1640 build_id_hex);
1642 snprintf(name, size, 1641 snprintf(name, size,
1643 "%s/usr/lib/debug/.build-id/%.2s/%s.debug", 1642 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
1644 symbol_conf.symfs, build_id_hex, build_id_hex + 2); 1643 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1645 } 1644 }
1646 break; 1645 break;
1647 case SYMTAB__SYSTEM_PATH_DSO: 1646 case SYMTAB__SYSTEM_PATH_DSO:
1648 snprintf(name, size, "%s%s", 1647 snprintf(name, size, "%s%s",
1649 symbol_conf.symfs, dso->long_name); 1648 symbol_conf.symfs, dso->long_name);
1650 break; 1649 break;
1651 case SYMTAB__GUEST_KMODULE: 1650 case SYMTAB__GUEST_KMODULE:
1652 if (map->groups && machine) 1651 if (map->groups && machine)
1653 root_dir = machine->root_dir; 1652 root_dir = machine->root_dir;
1654 else 1653 else
1655 root_dir = ""; 1654 root_dir = "";
1656 snprintf(name, size, "%s%s%s", symbol_conf.symfs, 1655 snprintf(name, size, "%s%s%s", symbol_conf.symfs,
1657 root_dir, dso->long_name); 1656 root_dir, dso->long_name);
1658 break; 1657 break;
1659 1658
1660 case SYMTAB__SYSTEM_PATH_KMODULE: 1659 case SYMTAB__SYSTEM_PATH_KMODULE:
1661 snprintf(name, size, "%s%s", symbol_conf.symfs, 1660 snprintf(name, size, "%s%s", symbol_conf.symfs,
1662 dso->long_name); 1661 dso->long_name);
1663 break; 1662 break;
1664 default:; 1663 default:;
1665 } 1664 }
1666 1665
1667 /* Name is now the name of the next image to try */ 1666 /* Name is now the name of the next image to try */
1668 fd = open(name, O_RDONLY); 1667 fd = open(name, O_RDONLY);
1669 if (fd < 0) 1668 if (fd < 0)
1670 continue; 1669 continue;
1671 1670
1672 ret = dso__load_sym(dso, map, name, fd, filter, 0, 1671 ret = dso__load_sym(dso, map, name, fd, filter, 0,
1673 want_symtab); 1672 want_symtab);
1674 close(fd); 1673 close(fd);
1675 1674
1676 /* 1675 /*
1677 * Some people seem to have debuginfo files _WITHOUT_ debug 1676 * Some people seem to have debuginfo files _WITHOUT_ debug
1678 * info!?!? 1677 * info!?!?
1679 */ 1678 */
1680 if (!ret) 1679 if (!ret)
1681 continue; 1680 continue;
1682 1681
1683 if (ret > 0) { 1682 if (ret > 0) {
1684 int nr_plt = dso__synthesize_plt_symbols(dso, map, 1683 int nr_plt = dso__synthesize_plt_symbols(dso, map,
1685 filter); 1684 filter);
1686 if (nr_plt > 0) 1685 if (nr_plt > 0)
1687 ret += nr_plt; 1686 ret += nr_plt;
1688 break; 1687 break;
1689 } 1688 }
1690 } 1689 }
1691 1690
1692 /* 1691 /*
1693 * If we wanted a full symtab but no image had one, 1692 * If we wanted a full symtab but no image had one,
1694 * relax our requirements and repeat the search. 1693 * relax our requirements and repeat the search.
1695 */ 1694 */
1696 if (ret <= 0 && want_symtab) { 1695 if (ret <= 0 && want_symtab) {
1697 want_symtab = 0; 1696 want_symtab = 0;
1698 goto restart; 1697 goto restart;
1699 } 1698 }
1700 1699
1701 free(name); 1700 free(name);
1702 if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) 1701 if (ret < 0 && strstr(dso->name, " (deleted)") != NULL)
1703 return 0; 1702 return 0;
1704 return ret; 1703 return ret;
1705 } 1704 }
1706 1705
1707 struct map *map_groups__find_by_name(struct map_groups *mg, 1706 struct map *map_groups__find_by_name(struct map_groups *mg,
1708 enum map_type type, const char *name) 1707 enum map_type type, const char *name)
1709 { 1708 {
1710 struct rb_node *nd; 1709 struct rb_node *nd;
1711 1710
1712 for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) { 1711 for (nd = rb_first(&mg->maps[type]); nd; nd = rb_next(nd)) {
1713 struct map *map = rb_entry(nd, struct map, rb_node); 1712 struct map *map = rb_entry(nd, struct map, rb_node);
1714 1713
1715 if (map->dso && strcmp(map->dso->short_name, name) == 0) 1714 if (map->dso && strcmp(map->dso->short_name, name) == 0)
1716 return map; 1715 return map;
1717 } 1716 }
1718 1717
1719 return NULL; 1718 return NULL;
1720 } 1719 }
1721 1720
1722 static int dso__kernel_module_get_build_id(struct dso *dso, 1721 static int dso__kernel_module_get_build_id(struct dso *dso,
1723 const char *root_dir) 1722 const char *root_dir)
1724 { 1723 {
1725 char filename[PATH_MAX]; 1724 char filename[PATH_MAX];
1726 /* 1725 /*
1727 * kernel module short names are of the form "[module]" and 1726 * kernel module short names are of the form "[module]" and
1728 * we need just "module" here. 1727 * we need just "module" here.
1729 */ 1728 */
1730 const char *name = dso->short_name + 1; 1729 const char *name = dso->short_name + 1;
1731 1730
1732 snprintf(filename, sizeof(filename), 1731 snprintf(filename, sizeof(filename),
1733 "%s/sys/module/%.*s/notes/.note.gnu.build-id", 1732 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
1734 root_dir, (int)strlen(name) - 1, name); 1733 root_dir, (int)strlen(name) - 1, name);
1735 1734
1736 if (sysfs__read_build_id(filename, dso->build_id, 1735 if (sysfs__read_build_id(filename, dso->build_id,
1737 sizeof(dso->build_id)) == 0) 1736 sizeof(dso->build_id)) == 0)
1738 dso->has_build_id = true; 1737 dso->has_build_id = true;
1739 1738
1740 return 0; 1739 return 0;
1741 } 1740 }
1742 1741
1743 static int map_groups__set_modules_path_dir(struct map_groups *mg, 1742 static int map_groups__set_modules_path_dir(struct map_groups *mg,
1744 const char *dir_name) 1743 const char *dir_name)
1745 { 1744 {
1746 struct dirent *dent; 1745 struct dirent *dent;
1747 DIR *dir = opendir(dir_name); 1746 DIR *dir = opendir(dir_name);
1748 int ret = 0; 1747 int ret = 0;
1749 1748
1750 if (!dir) { 1749 if (!dir) {
1751 pr_debug("%s: cannot open %s dir\n", __func__, dir_name); 1750 pr_debug("%s: cannot open %s dir\n", __func__, dir_name);
1752 return -1; 1751 return -1;
1753 } 1752 }
1754 1753
1755 while ((dent = readdir(dir)) != NULL) { 1754 while ((dent = readdir(dir)) != NULL) {
1756 char path[PATH_MAX]; 1755 char path[PATH_MAX];
1757 struct stat st; 1756 struct stat st;
1758 1757
1759 /*sshfs might return bad dent->d_type, so we have to stat*/ 1758 /*sshfs might return bad dent->d_type, so we have to stat*/
1760 snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name); 1759 snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
1761 if (stat(path, &st)) 1760 if (stat(path, &st))
1762 continue; 1761 continue;
1763 1762
1764 if (S_ISDIR(st.st_mode)) { 1763 if (S_ISDIR(st.st_mode)) {
1765 if (!strcmp(dent->d_name, ".") || 1764 if (!strcmp(dent->d_name, ".") ||
1766 !strcmp(dent->d_name, "..")) 1765 !strcmp(dent->d_name, ".."))
1767 continue; 1766 continue;
1768 1767
1769 ret = map_groups__set_modules_path_dir(mg, path); 1768 ret = map_groups__set_modules_path_dir(mg, path);
1770 if (ret < 0) 1769 if (ret < 0)
1771 goto out; 1770 goto out;
1772 } else { 1771 } else {
1773 char *dot = strrchr(dent->d_name, '.'), 1772 char *dot = strrchr(dent->d_name, '.'),
1774 dso_name[PATH_MAX]; 1773 dso_name[PATH_MAX];
1775 struct map *map; 1774 struct map *map;
1776 char *long_name; 1775 char *long_name;
1777 1776
1778 if (dot == NULL || strcmp(dot, ".ko")) 1777 if (dot == NULL || strcmp(dot, ".ko"))
1779 continue; 1778 continue;
1780 snprintf(dso_name, sizeof(dso_name), "[%.*s]", 1779 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
1781 (int)(dot - dent->d_name), dent->d_name); 1780 (int)(dot - dent->d_name), dent->d_name);
1782 1781
1783 strxfrchar(dso_name, '-', '_'); 1782 strxfrchar(dso_name, '-', '_');
1784 map = map_groups__find_by_name(mg, MAP__FUNCTION, 1783 map = map_groups__find_by_name(mg, MAP__FUNCTION,
1785 dso_name); 1784 dso_name);
1786 if (map == NULL) 1785 if (map == NULL)
1787 continue; 1786 continue;
1788 1787
1789 long_name = strdup(path); 1788 long_name = strdup(path);
1790 if (long_name == NULL) { 1789 if (long_name == NULL) {
1791 ret = -1; 1790 ret = -1;
1792 goto out; 1791 goto out;
1793 } 1792 }
1794 dso__set_long_name(map->dso, long_name); 1793 dso__set_long_name(map->dso, long_name);
1795 map->dso->lname_alloc = 1; 1794 map->dso->lname_alloc = 1;
1796 dso__kernel_module_get_build_id(map->dso, ""); 1795 dso__kernel_module_get_build_id(map->dso, "");
1797 } 1796 }
1798 } 1797 }
1799 1798
1800 out: 1799 out:
1801 closedir(dir); 1800 closedir(dir);
1802 return ret; 1801 return ret;
1803 } 1802 }
1804 1803
1805 static char *get_kernel_version(const char *root_dir) 1804 static char *get_kernel_version(const char *root_dir)
1806 { 1805 {
1807 char version[PATH_MAX]; 1806 char version[PATH_MAX];
1808 FILE *file; 1807 FILE *file;
1809 char *name, *tmp; 1808 char *name, *tmp;
1810 const char *prefix = "Linux version "; 1809 const char *prefix = "Linux version ";
1811 1810
1812 sprintf(version, "%s/proc/version", root_dir); 1811 sprintf(version, "%s/proc/version", root_dir);
1813 file = fopen(version, "r"); 1812 file = fopen(version, "r");
1814 if (!file) 1813 if (!file)
1815 return NULL; 1814 return NULL;
1816 1815
1817 version[0] = '\0'; 1816 version[0] = '\0';
1818 tmp = fgets(version, sizeof(version), file); 1817 tmp = fgets(version, sizeof(version), file);
1819 fclose(file); 1818 fclose(file);
1820 1819
1821 name = strstr(version, prefix); 1820 name = strstr(version, prefix);
1822 if (!name) 1821 if (!name)
1823 return NULL; 1822 return NULL;
1824 name += strlen(prefix); 1823 name += strlen(prefix);
1825 tmp = strchr(name, ' '); 1824 tmp = strchr(name, ' ');
1826 if (tmp) 1825 if (tmp)
1827 *tmp = '\0'; 1826 *tmp = '\0';
1828 1827
1829 return strdup(name); 1828 return strdup(name);
1830 } 1829 }
1831 1830
1832 static int machine__set_modules_path(struct machine *machine) 1831 static int machine__set_modules_path(struct machine *machine)
1833 { 1832 {
1834 char *version; 1833 char *version;
1835 char modules_path[PATH_MAX]; 1834 char modules_path[PATH_MAX];
1836 1835
1837 version = get_kernel_version(machine->root_dir); 1836 version = get_kernel_version(machine->root_dir);
1838 if (!version) 1837 if (!version)
1839 return -1; 1838 return -1;
1840 1839
1841 snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", 1840 snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
1842 machine->root_dir, version); 1841 machine->root_dir, version);
1843 free(version); 1842 free(version);
1844 1843
1845 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); 1844 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
1846 } 1845 }
1847 1846
1848 /* 1847 /*
1849 * Constructor variant for modules (where we know from /proc/modules where 1848 * Constructor variant for modules (where we know from /proc/modules where
1850 * they are loaded) and for vmlinux, where only after we load all the 1849 * they are loaded) and for vmlinux, where only after we load all the
1851 * symbols we'll know where it starts and ends. 1850 * symbols we'll know where it starts and ends.
1852 */ 1851 */
1853 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) 1852 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
1854 { 1853 {
1855 struct map *map = calloc(1, (sizeof(*map) + 1854 struct map *map = calloc(1, (sizeof(*map) +
1856 (dso->kernel ? sizeof(struct kmap) : 0))); 1855 (dso->kernel ? sizeof(struct kmap) : 0)));
1857 if (map != NULL) { 1856 if (map != NULL) {
1858 /* 1857 /*
1859 * ->end will be filled after we load all the symbols 1858 * ->end will be filled after we load all the symbols
1860 */ 1859 */
1861 map__init(map, type, start, 0, 0, dso); 1860 map__init(map, type, start, 0, 0, dso);
1862 } 1861 }
1863 1862
1864 return map; 1863 return map;
1865 } 1864 }
1866 1865
1867 struct map *machine__new_module(struct machine *machine, u64 start, 1866 struct map *machine__new_module(struct machine *machine, u64 start,
1868 const char *filename) 1867 const char *filename)
1869 { 1868 {
1870 struct map *map; 1869 struct map *map;
1871 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); 1870 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
1872 1871
1873 if (dso == NULL) 1872 if (dso == NULL)
1874 return NULL; 1873 return NULL;
1875 1874
1876 map = map__new2(start, dso, MAP__FUNCTION); 1875 map = map__new2(start, dso, MAP__FUNCTION);
1877 if (map == NULL) 1876 if (map == NULL)
1878 return NULL; 1877 return NULL;
1879 1878
1880 if (machine__is_host(machine)) 1879 if (machine__is_host(machine))
1881 dso->symtab_type = SYMTAB__SYSTEM_PATH_KMODULE; 1880 dso->symtab_type = SYMTAB__SYSTEM_PATH_KMODULE;
1882 else 1881 else
1883 dso->symtab_type = SYMTAB__GUEST_KMODULE; 1882 dso->symtab_type = SYMTAB__GUEST_KMODULE;
1884 map_groups__insert(&machine->kmaps, map); 1883 map_groups__insert(&machine->kmaps, map);
1885 return map; 1884 return map;
1886 } 1885 }
1887 1886
1888 static int machine__create_modules(struct machine *machine) 1887 static int machine__create_modules(struct machine *machine)
1889 { 1888 {
1890 char *line = NULL; 1889 char *line = NULL;
1891 size_t n; 1890 size_t n;
1892 FILE *file; 1891 FILE *file;
1893 struct map *map; 1892 struct map *map;
1894 const char *modules; 1893 const char *modules;
1895 char path[PATH_MAX]; 1894 char path[PATH_MAX];
1896 1895
1897 if (machine__is_default_guest(machine)) 1896 if (machine__is_default_guest(machine))
1898 modules = symbol_conf.default_guest_modules; 1897 modules = symbol_conf.default_guest_modules;
1899 else { 1898 else {
1900 sprintf(path, "%s/proc/modules", machine->root_dir); 1899 sprintf(path, "%s/proc/modules", machine->root_dir);
1901 modules = path; 1900 modules = path;
1902 } 1901 }
1903 1902
1904 if (symbol__restricted_filename(path, "/proc/modules")) 1903 if (symbol__restricted_filename(path, "/proc/modules"))
1905 return -1; 1904 return -1;
1906 1905
1907 file = fopen(modules, "r"); 1906 file = fopen(modules, "r");
1908 if (file == NULL) 1907 if (file == NULL)
1909 return -1; 1908 return -1;
1910 1909
1911 while (!feof(file)) { 1910 while (!feof(file)) {
1912 char name[PATH_MAX]; 1911 char name[PATH_MAX];
1913 u64 start; 1912 u64 start;
1914 char *sep; 1913 char *sep;
1915 int line_len; 1914 int line_len;
1916 1915
1917 line_len = getline(&line, &n, file); 1916 line_len = getline(&line, &n, file);
1918 if (line_len < 0) 1917 if (line_len < 0)
1919 break; 1918 break;
1920 1919
1921 if (!line) 1920 if (!line)
1922 goto out_failure; 1921 goto out_failure;
1923 1922
1924 line[--line_len] = '\0'; /* \n */ 1923 line[--line_len] = '\0'; /* \n */
1925 1924
1926 sep = strrchr(line, 'x'); 1925 sep = strrchr(line, 'x');
1927 if (sep == NULL) 1926 if (sep == NULL)
1928 continue; 1927 continue;
1929 1928
1930 hex2u64(sep + 1, &start); 1929 hex2u64(sep + 1, &start);
1931 1930
1932 sep = strchr(line, ' '); 1931 sep = strchr(line, ' ');
1933 if (sep == NULL) 1932 if (sep == NULL)
1934 continue; 1933 continue;
1935 1934
1936 *sep = '\0'; 1935 *sep = '\0';
1937 1936
1938 snprintf(name, sizeof(name), "[%s]", line); 1937 snprintf(name, sizeof(name), "[%s]", line);
1939 map = machine__new_module(machine, start, name); 1938 map = machine__new_module(machine, start, name);
1940 if (map == NULL) 1939 if (map == NULL)
1941 goto out_delete_line; 1940 goto out_delete_line;
1942 dso__kernel_module_get_build_id(map->dso, machine->root_dir); 1941 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
1943 } 1942 }
1944 1943
1945 free(line); 1944 free(line);
1946 fclose(file); 1945 fclose(file);
1947 1946
1948 return machine__set_modules_path(machine); 1947 return machine__set_modules_path(machine);
1949 1948
1950 out_delete_line: 1949 out_delete_line:
1951 free(line); 1950 free(line);
1952 out_failure: 1951 out_failure:
1953 return -1; 1952 return -1;
1954 } 1953 }
1955 1954
1956 int dso__load_vmlinux(struct dso *dso, struct map *map, 1955 int dso__load_vmlinux(struct dso *dso, struct map *map,
1957 const char *vmlinux, symbol_filter_t filter) 1956 const char *vmlinux, symbol_filter_t filter)
1958 { 1957 {
1959 int err = -1, fd; 1958 int err = -1, fd;
1960 char symfs_vmlinux[PATH_MAX]; 1959 char symfs_vmlinux[PATH_MAX];
1961 1960
1962 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", 1961 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s",
1963 symbol_conf.symfs, vmlinux); 1962 symbol_conf.symfs, vmlinux);
1964 fd = open(symfs_vmlinux, O_RDONLY); 1963 fd = open(symfs_vmlinux, O_RDONLY);
1965 if (fd < 0) 1964 if (fd < 0)
1966 return -1; 1965 return -1;
1967 1966
1968 dso__set_long_name(dso, (char *)vmlinux); 1967 dso__set_long_name(dso, (char *)vmlinux);
1969 dso__set_loaded(dso, map->type); 1968 dso__set_loaded(dso, map->type);
1970 err = dso__load_sym(dso, map, symfs_vmlinux, fd, filter, 0, 0); 1969 err = dso__load_sym(dso, map, symfs_vmlinux, fd, filter, 0, 0);
1971 close(fd); 1970 close(fd);
1972 1971
1973 if (err > 0) 1972 if (err > 0)
1974 pr_debug("Using %s for symbols\n", symfs_vmlinux); 1973 pr_debug("Using %s for symbols\n", symfs_vmlinux);
1975 1974
1976 return err; 1975 return err;
1977 } 1976 }
1978 1977
1979 int dso__load_vmlinux_path(struct dso *dso, struct map *map, 1978 int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1980 symbol_filter_t filter) 1979 symbol_filter_t filter)
1981 { 1980 {
1982 int i, err = 0; 1981 int i, err = 0;
1983 char *filename; 1982 char *filename;
1984 1983
1985 pr_debug("Looking at the vmlinux_path (%d entries long)\n", 1984 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1986 vmlinux_path__nr_entries + 1); 1985 vmlinux_path__nr_entries + 1);
1987 1986
1988 filename = dso__build_id_filename(dso, NULL, 0); 1987 filename = dso__build_id_filename(dso, NULL, 0);
1989 if (filename != NULL) { 1988 if (filename != NULL) {
1990 err = dso__load_vmlinux(dso, map, filename, filter); 1989 err = dso__load_vmlinux(dso, map, filename, filter);
1991 if (err > 0) { 1990 if (err > 0) {
1992 dso__set_long_name(dso, filename); 1991 dso__set_long_name(dso, filename);
1993 goto out; 1992 goto out;
1994 } 1993 }
1995 free(filename); 1994 free(filename);
1996 } 1995 }
1997 1996
1998 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1997 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1999 err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); 1998 err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter);
2000 if (err > 0) { 1999 if (err > 0) {
2001 dso__set_long_name(dso, strdup(vmlinux_path[i])); 2000 dso__set_long_name(dso, strdup(vmlinux_path[i]));
2002 break; 2001 break;
2003 } 2002 }
2004 } 2003 }
2005 out: 2004 out:
2006 return err; 2005 return err;
2007 } 2006 }
2008 2007
2009 static int dso__load_kernel_sym(struct dso *dso, struct map *map, 2008 static int dso__load_kernel_sym(struct dso *dso, struct map *map,
2010 symbol_filter_t filter) 2009 symbol_filter_t filter)
2011 { 2010 {
2012 int err; 2011 int err;
2013 const char *kallsyms_filename = NULL; 2012 const char *kallsyms_filename = NULL;
2014 char *kallsyms_allocated_filename = NULL; 2013 char *kallsyms_allocated_filename = NULL;
2015 /* 2014 /*
2016 * Step 1: if the user specified a kallsyms or vmlinux filename, use 2015 * Step 1: if the user specified a kallsyms or vmlinux filename, use
2017 * it and only it, reporting errors to the user if it cannot be used. 2016 * it and only it, reporting errors to the user if it cannot be used.
2018 * 2017 *
2019 * For instance, try to analyse an ARM perf.data file _without_ a 2018 * For instance, try to analyse an ARM perf.data file _without_ a
2020 * build-id, or if the user specifies the wrong path to the right 2019 * build-id, or if the user specifies the wrong path to the right
2021 * vmlinux file, obviously we can't fallback to another vmlinux (a 2020 * vmlinux file, obviously we can't fallback to another vmlinux (a
2022 * x86_86 one, on the machine where analysis is being performed, say), 2021 * x86_86 one, on the machine where analysis is being performed, say),
2023 * or worse, /proc/kallsyms. 2022 * or worse, /proc/kallsyms.
2024 * 2023 *
2025 * If the specified file _has_ a build-id and there is a build-id 2024 * If the specified file _has_ a build-id and there is a build-id
2026 * section in the perf.data file, we will still do the expected 2025 * section in the perf.data file, we will still do the expected
2027 * validation in dso__load_vmlinux and will bail out if they don't 2026 * validation in dso__load_vmlinux and will bail out if they don't
2028 * match. 2027 * match.
2029 */ 2028 */
2030 if (symbol_conf.kallsyms_name != NULL) { 2029 if (symbol_conf.kallsyms_name != NULL) {
2031 kallsyms_filename = symbol_conf.kallsyms_name; 2030 kallsyms_filename = symbol_conf.kallsyms_name;
2032 goto do_kallsyms; 2031 goto do_kallsyms;
2033 } 2032 }
2034 2033
2035 if (symbol_conf.vmlinux_name != NULL) { 2034 if (symbol_conf.vmlinux_name != NULL) {
2036 err = dso__load_vmlinux(dso, map, 2035 err = dso__load_vmlinux(dso, map,
2037 symbol_conf.vmlinux_name, filter); 2036 symbol_conf.vmlinux_name, filter);
2038 if (err > 0) { 2037 if (err > 0) {
2039 dso__set_long_name(dso, 2038 dso__set_long_name(dso,
2040 strdup(symbol_conf.vmlinux_name)); 2039 strdup(symbol_conf.vmlinux_name));
2041 goto out_fixup; 2040 goto out_fixup;
2042 } 2041 }
2043 return err; 2042 return err;
2044 } 2043 }
2045 2044
2046 if (vmlinux_path != NULL) { 2045 if (vmlinux_path != NULL) {
2047 err = dso__load_vmlinux_path(dso, map, filter); 2046 err = dso__load_vmlinux_path(dso, map, filter);
2048 if (err > 0) 2047 if (err > 0)
2049 goto out_fixup; 2048 goto out_fixup;
2050 } 2049 }
2051 2050
2052 /* do not try local files if a symfs was given */ 2051 /* do not try local files if a symfs was given */
2053 if (symbol_conf.symfs[0] != 0) 2052 if (symbol_conf.symfs[0] != 0)
2054 return -1; 2053 return -1;
2055 2054
2056 /* 2055 /*
2057 * Say the kernel DSO was created when processing the build-id header table, 2056 * Say the kernel DSO was created when processing the build-id header table,
2058 * we have a build-id, so check if it is the same as the running kernel, 2057 * we have a build-id, so check if it is the same as the running kernel,
2059 * using it if it is. 2058 * using it if it is.
2060 */ 2059 */
2061 if (dso->has_build_id) { 2060 if (dso->has_build_id) {
2062 u8 kallsyms_build_id[BUILD_ID_SIZE]; 2061 u8 kallsyms_build_id[BUILD_ID_SIZE];
2063 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 2062 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
2064 2063
2065 if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id, 2064 if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
2066 sizeof(kallsyms_build_id)) == 0) { 2065 sizeof(kallsyms_build_id)) == 0) {
2067 if (dso__build_id_equal(dso, kallsyms_build_id)) { 2066 if (dso__build_id_equal(dso, kallsyms_build_id)) {
2068 kallsyms_filename = "/proc/kallsyms"; 2067 kallsyms_filename = "/proc/kallsyms";
2069 goto do_kallsyms; 2068 goto do_kallsyms;
2070 } 2069 }
2071 } 2070 }
2072 /* 2071 /*
2073 * Now look if we have it on the build-id cache in 2072 * Now look if we have it on the build-id cache in
2074 * $HOME/.debug/[kernel.kallsyms]. 2073 * $HOME/.debug/[kernel.kallsyms].
2075 */ 2074 */
2076 build_id__sprintf(dso->build_id, sizeof(dso->build_id), 2075 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
2077 sbuild_id); 2076 sbuild_id);
2078 2077
2079 if (asprintf(&kallsyms_allocated_filename, 2078 if (asprintf(&kallsyms_allocated_filename,
2080 "%s/.debug/[kernel.kallsyms]/%s", 2079 "%s/.debug/[kernel.kallsyms]/%s",
2081 getenv("HOME"), sbuild_id) == -1) { 2080 getenv("HOME"), sbuild_id) == -1) {
2082 pr_err("Not enough memory for kallsyms file lookup\n"); 2081 pr_err("Not enough memory for kallsyms file lookup\n");
2083 return -1; 2082 return -1;
2084 } 2083 }
2085 2084
2086 kallsyms_filename = kallsyms_allocated_filename; 2085 kallsyms_filename = kallsyms_allocated_filename;
2087 2086
2088 if (access(kallsyms_filename, F_OK)) { 2087 if (access(kallsyms_filename, F_OK)) {
2089 pr_err("No kallsyms or vmlinux with build-id %s " 2088 pr_err("No kallsyms or vmlinux with build-id %s "
2090 "was found\n", sbuild_id); 2089 "was found\n", sbuild_id);
2091 free(kallsyms_allocated_filename); 2090 free(kallsyms_allocated_filename);
2092 return -1; 2091 return -1;
2093 } 2092 }
2094 } else { 2093 } else {
2095 /* 2094 /*
2096 * Last resort, if we don't have a build-id and couldn't find 2095 * Last resort, if we don't have a build-id and couldn't find
2097 * any vmlinux file, try the running kernel kallsyms table. 2096 * any vmlinux file, try the running kernel kallsyms table.
2098 */ 2097 */
2099 kallsyms_filename = "/proc/kallsyms"; 2098 kallsyms_filename = "/proc/kallsyms";
2100 } 2099 }
2101 2100
2102 do_kallsyms: 2101 do_kallsyms:
2103 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 2102 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
2104 if (err > 0) 2103 if (err > 0)
2105 pr_debug("Using %s for symbols\n", kallsyms_filename); 2104 pr_debug("Using %s for symbols\n", kallsyms_filename);
2106 free(kallsyms_allocated_filename); 2105 free(kallsyms_allocated_filename);
2107 2106
2108 if (err > 0) { 2107 if (err > 0) {
2109 out_fixup: 2108 out_fixup:
2110 if (kallsyms_filename != NULL) 2109 if (kallsyms_filename != NULL)
2111 dso__set_long_name(dso, strdup("[kernel.kallsyms]")); 2110 dso__set_long_name(dso, strdup("[kernel.kallsyms]"));
2112 map__fixup_start(map); 2111 map__fixup_start(map);
2113 map__fixup_end(map); 2112 map__fixup_end(map);
2114 } 2113 }
2115 2114
2116 return err; 2115 return err;
2117 } 2116 }
2118 2117
2119 static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 2118 static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
2120 symbol_filter_t filter) 2119 symbol_filter_t filter)
2121 { 2120 {
2122 int err; 2121 int err;
2123 const char *kallsyms_filename = NULL; 2122 const char *kallsyms_filename = NULL;
2124 struct machine *machine; 2123 struct machine *machine;
2125 char path[PATH_MAX]; 2124 char path[PATH_MAX];
2126 2125
2127 if (!map->groups) { 2126 if (!map->groups) {
2128 pr_debug("Guest kernel map hasn't the point to groups\n"); 2127 pr_debug("Guest kernel map hasn't the point to groups\n");
2129 return -1; 2128 return -1;
2130 } 2129 }
2131 machine = map->groups->machine; 2130 machine = map->groups->machine;
2132 2131
2133 if (machine__is_default_guest(machine)) { 2132 if (machine__is_default_guest(machine)) {
2134 /* 2133 /*
2135 * if the user specified a vmlinux filename, use it and only 2134 * if the user specified a vmlinux filename, use it and only
2136 * it, reporting errors to the user if it cannot be used. 2135 * it, reporting errors to the user if it cannot be used.
2137 * Or use file guest_kallsyms inputted by user on commandline 2136 * Or use file guest_kallsyms inputted by user on commandline
2138 */ 2137 */
2139 if (symbol_conf.default_guest_vmlinux_name != NULL) { 2138 if (symbol_conf.default_guest_vmlinux_name != NULL) {
2140 err = dso__load_vmlinux(dso, map, 2139 err = dso__load_vmlinux(dso, map,
2141 symbol_conf.default_guest_vmlinux_name, filter); 2140 symbol_conf.default_guest_vmlinux_name, filter);
2142 goto out_try_fixup; 2141 goto out_try_fixup;
2143 } 2142 }
2144 2143
2145 kallsyms_filename = symbol_conf.default_guest_kallsyms; 2144 kallsyms_filename = symbol_conf.default_guest_kallsyms;
2146 if (!kallsyms_filename) 2145 if (!kallsyms_filename)
2147 return -1; 2146 return -1;
2148 } else { 2147 } else {
2149 sprintf(path, "%s/proc/kallsyms", machine->root_dir); 2148 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
2150 kallsyms_filename = path; 2149 kallsyms_filename = path;
2151 } 2150 }
2152 2151
2153 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 2152 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
2154 if (err > 0) 2153 if (err > 0)
2155 pr_debug("Using %s for symbols\n", kallsyms_filename); 2154 pr_debug("Using %s for symbols\n", kallsyms_filename);
2156 2155
2157 out_try_fixup: 2156 out_try_fixup:
2158 if (err > 0) { 2157 if (err > 0) {
2159 if (kallsyms_filename != NULL) { 2158 if (kallsyms_filename != NULL) {
2160 machine__mmap_name(machine, path, sizeof(path)); 2159 machine__mmap_name(machine, path, sizeof(path));
2161 dso__set_long_name(dso, strdup(path)); 2160 dso__set_long_name(dso, strdup(path));
2162 } 2161 }
2163 map__fixup_start(map); 2162 map__fixup_start(map);
2164 map__fixup_end(map); 2163 map__fixup_end(map);
2165 } 2164 }
2166 2165
2167 return err; 2166 return err;
2168 } 2167 }
2169 2168
2170 static void dsos__add(struct list_head *head, struct dso *dso) 2169 static void dsos__add(struct list_head *head, struct dso *dso)
2171 { 2170 {
2172 list_add_tail(&dso->node, head); 2171 list_add_tail(&dso->node, head);
2173 } 2172 }
2174 2173
2175 static struct dso *dsos__find(struct list_head *head, const char *name) 2174 static struct dso *dsos__find(struct list_head *head, const char *name)
2176 { 2175 {
2177 struct dso *pos; 2176 struct dso *pos;
2178 2177
2179 list_for_each_entry(pos, head, node) 2178 list_for_each_entry(pos, head, node)
2180 if (strcmp(pos->long_name, name) == 0) 2179 if (strcmp(pos->long_name, name) == 0)
2181 return pos; 2180 return pos;
2182 return NULL; 2181 return NULL;
2183 } 2182 }
2184 2183
2185 struct dso *__dsos__findnew(struct list_head *head, const char *name) 2184 struct dso *__dsos__findnew(struct list_head *head, const char *name)
2186 { 2185 {
2187 struct dso *dso = dsos__find(head, name); 2186 struct dso *dso = dsos__find(head, name);
2188 2187
2189 if (!dso) { 2188 if (!dso) {
2190 dso = dso__new(name); 2189 dso = dso__new(name);
2191 if (dso != NULL) { 2190 if (dso != NULL) {
2192 dsos__add(head, dso); 2191 dsos__add(head, dso);
2193 dso__set_basename(dso); 2192 dso__set_basename(dso);
2194 } 2193 }
2195 } 2194 }
2196 2195
2197 return dso; 2196 return dso;
2198 } 2197 }
2199 2198
2200 size_t __dsos__fprintf(struct list_head *head, FILE *fp) 2199 size_t __dsos__fprintf(struct list_head *head, FILE *fp)
2201 { 2200 {
2202 struct dso *pos; 2201 struct dso *pos;
2203 size_t ret = 0; 2202 size_t ret = 0;
2204 2203
2205 list_for_each_entry(pos, head, node) { 2204 list_for_each_entry(pos, head, node) {
2206 int i; 2205 int i;
2207 for (i = 0; i < MAP__NR_TYPES; ++i) 2206 for (i = 0; i < MAP__NR_TYPES; ++i)
2208 ret += dso__fprintf(pos, i, fp); 2207 ret += dso__fprintf(pos, i, fp);
2209 } 2208 }
2210 2209
2211 return ret; 2210 return ret;
2212 } 2211 }
2213 2212
2214 size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp) 2213 size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
2215 { 2214 {
2216 struct rb_node *nd; 2215 struct rb_node *nd;
2217 size_t ret = 0; 2216 size_t ret = 0;
2218 2217
2219 for (nd = rb_first(machines); nd; nd = rb_next(nd)) { 2218 for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
2220 struct machine *pos = rb_entry(nd, struct machine, rb_node); 2219 struct machine *pos = rb_entry(nd, struct machine, rb_node);
2221 ret += __dsos__fprintf(&pos->kernel_dsos, fp); 2220 ret += __dsos__fprintf(&pos->kernel_dsos, fp);
2222 ret += __dsos__fprintf(&pos->user_dsos, fp); 2221 ret += __dsos__fprintf(&pos->user_dsos, fp);
2223 } 2222 }
2224 2223
2225 return ret; 2224 return ret;
2226 } 2225 }
2227 2226
2228 static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 2227 static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
2229 bool with_hits) 2228 bool with_hits)
2230 { 2229 {
2231 struct dso *pos; 2230 struct dso *pos;
2232 size_t ret = 0; 2231 size_t ret = 0;
2233 2232
2234 list_for_each_entry(pos, head, node) { 2233 list_for_each_entry(pos, head, node) {
2235 if (with_hits && !pos->hit) 2234 if (with_hits && !pos->hit)
2236 continue; 2235 continue;
2237 ret += dso__fprintf_buildid(pos, fp); 2236 ret += dso__fprintf_buildid(pos, fp);
2238 ret += fprintf(fp, " %s\n", pos->long_name); 2237 ret += fprintf(fp, " %s\n", pos->long_name);
2239 } 2238 }
2240 return ret; 2239 return ret;
2241 } 2240 }
2242 2241
2243 size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 2242 size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
2244 bool with_hits) 2243 bool with_hits)
2245 { 2244 {
2246 return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, with_hits) + 2245 return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, with_hits) +
2247 __dsos__fprintf_buildid(&machine->user_dsos, fp, with_hits); 2246 __dsos__fprintf_buildid(&machine->user_dsos, fp, with_hits);
2248 } 2247 }
2249 2248
2250 size_t machines__fprintf_dsos_buildid(struct rb_root *machines, 2249 size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
2251 FILE *fp, bool with_hits) 2250 FILE *fp, bool with_hits)
2252 { 2251 {
2253 struct rb_node *nd; 2252 struct rb_node *nd;
2254 size_t ret = 0; 2253 size_t ret = 0;
2255 2254
2256 for (nd = rb_first(machines); nd; nd = rb_next(nd)) { 2255 for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
2257 struct machine *pos = rb_entry(nd, struct machine, rb_node); 2256 struct machine *pos = rb_entry(nd, struct machine, rb_node);
2258 ret += machine__fprintf_dsos_buildid(pos, fp, with_hits); 2257 ret += machine__fprintf_dsos_buildid(pos, fp, with_hits);
2259 } 2258 }
2260 return ret; 2259 return ret;
2261 } 2260 }
2262 2261
2263 static struct dso* 2262 static struct dso*
2264 dso__kernel_findnew(struct machine *machine, const char *name, 2263 dso__kernel_findnew(struct machine *machine, const char *name,
2265 const char *short_name, int dso_type) 2264 const char *short_name, int dso_type)
2266 { 2265 {
2267 /* 2266 /*
2268 * The kernel dso could be created by build_id processing. 2267 * The kernel dso could be created by build_id processing.
2269 */ 2268 */
2270 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name); 2269 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
2271 2270
2272 /* 2271 /*
2273 * We need to run this in all cases, since during the build_id 2272 * We need to run this in all cases, since during the build_id
2274 * processing we had no idea this was the kernel dso. 2273 * processing we had no idea this was the kernel dso.
2275 */ 2274 */
2276 if (dso != NULL) { 2275 if (dso != NULL) {
2277 dso__set_short_name(dso, short_name); 2276 dso__set_short_name(dso, short_name);
2278 dso->kernel = dso_type; 2277 dso->kernel = dso_type;
2279 } 2278 }
2280 2279
2281 return dso; 2280 return dso;
2282 } 2281 }
2283 2282
2284 void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine) 2283 void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
2285 { 2284 {
2286 char path[PATH_MAX]; 2285 char path[PATH_MAX];
2287 2286
2288 if (machine__is_default_guest(machine)) 2287 if (machine__is_default_guest(machine))
2289 return; 2288 return;
2290 sprintf(path, "%s/sys/kernel/notes", machine->root_dir); 2289 sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
2291 if (sysfs__read_build_id(path, dso->build_id, 2290 if (sysfs__read_build_id(path, dso->build_id,
2292 sizeof(dso->build_id)) == 0) 2291 sizeof(dso->build_id)) == 0)
2293 dso->has_build_id = true; 2292 dso->has_build_id = true;
2294 } 2293 }
2295 2294
2296 static struct dso *machine__get_kernel(struct machine *machine) 2295 static struct dso *machine__get_kernel(struct machine *machine)
2297 { 2296 {
2298 const char *vmlinux_name = NULL; 2297 const char *vmlinux_name = NULL;
2299 struct dso *kernel; 2298 struct dso *kernel;
2300 2299
2301 if (machine__is_host(machine)) { 2300 if (machine__is_host(machine)) {
2302 vmlinux_name = symbol_conf.vmlinux_name; 2301 vmlinux_name = symbol_conf.vmlinux_name;
2303 if (!vmlinux_name) 2302 if (!vmlinux_name)
2304 vmlinux_name = "[kernel.kallsyms]"; 2303 vmlinux_name = "[kernel.kallsyms]";
2305 2304
2306 kernel = dso__kernel_findnew(machine, vmlinux_name, 2305 kernel = dso__kernel_findnew(machine, vmlinux_name,
2307 "[kernel]", 2306 "[kernel]",
2308 DSO_TYPE_KERNEL); 2307 DSO_TYPE_KERNEL);
2309 } else { 2308 } else {
2310 char bf[PATH_MAX]; 2309 char bf[PATH_MAX];
2311 2310
2312 if (machine__is_default_guest(machine)) 2311 if (machine__is_default_guest(machine))
2313 vmlinux_name = symbol_conf.default_guest_vmlinux_name; 2312 vmlinux_name = symbol_conf.default_guest_vmlinux_name;
2314 if (!vmlinux_name) 2313 if (!vmlinux_name)
2315 vmlinux_name = machine__mmap_name(machine, bf, 2314 vmlinux_name = machine__mmap_name(machine, bf,
2316 sizeof(bf)); 2315 sizeof(bf));
2317 2316
2318 kernel = dso__kernel_findnew(machine, vmlinux_name, 2317 kernel = dso__kernel_findnew(machine, vmlinux_name,
2319 "[guest.kernel]", 2318 "[guest.kernel]",
2320 DSO_TYPE_GUEST_KERNEL); 2319 DSO_TYPE_GUEST_KERNEL);
2321 } 2320 }
2322 2321
2323 if (kernel != NULL && (!kernel->has_build_id)) 2322 if (kernel != NULL && (!kernel->has_build_id))
2324 dso__read_running_kernel_build_id(kernel, machine); 2323 dso__read_running_kernel_build_id(kernel, machine);
2325 2324
2326 return kernel; 2325 return kernel;
2327 } 2326 }
2328 2327
2329 struct process_args { 2328 struct process_args {
2330 u64 start; 2329 u64 start;
2331 }; 2330 };
2332 2331
2333 static int symbol__in_kernel(void *arg, const char *name, 2332 static int symbol__in_kernel(void *arg, const char *name,
2334 char type __used, u64 start, u64 end __used) 2333 char type __used, u64 start, u64 end __used)
2335 { 2334 {
2336 struct process_args *args = arg; 2335 struct process_args *args = arg;
2337 2336
2338 if (strchr(name, '[')) 2337 if (strchr(name, '['))
2339 return 0; 2338 return 0;
2340 2339
2341 args->start = start; 2340 args->start = start;
2342 return 1; 2341 return 1;
2343 } 2342 }
2344 2343
2345 /* Figure out the start address of kernel map from /proc/kallsyms */ 2344 /* Figure out the start address of kernel map from /proc/kallsyms */
2346 static u64 machine__get_kernel_start_addr(struct machine *machine) 2345 static u64 machine__get_kernel_start_addr(struct machine *machine)
2347 { 2346 {
2348 const char *filename; 2347 const char *filename;
2349 char path[PATH_MAX]; 2348 char path[PATH_MAX];
2350 struct process_args args; 2349 struct process_args args;
2351 2350
2352 if (machine__is_host(machine)) { 2351 if (machine__is_host(machine)) {
2353 filename = "/proc/kallsyms"; 2352 filename = "/proc/kallsyms";
2354 } else { 2353 } else {
2355 if (machine__is_default_guest(machine)) 2354 if (machine__is_default_guest(machine))
2356 filename = (char *)symbol_conf.default_guest_kallsyms; 2355 filename = (char *)symbol_conf.default_guest_kallsyms;
2357 else { 2356 else {
2358 sprintf(path, "%s/proc/kallsyms", machine->root_dir); 2357 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
2359 filename = path; 2358 filename = path;
2360 } 2359 }
2361 } 2360 }
2362 2361
2363 if (symbol__restricted_filename(filename, "/proc/kallsyms")) 2362 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
2364 return 0; 2363 return 0;
2365 2364
2366 if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0) 2365 if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
2367 return 0; 2366 return 0;
2368 2367
2369 return args.start; 2368 return args.start;
2370 } 2369 }
2371 2370
2372 int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 2371 int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
2373 { 2372 {
2374 enum map_type type; 2373 enum map_type type;
2375 u64 start = machine__get_kernel_start_addr(machine); 2374 u64 start = machine__get_kernel_start_addr(machine);
2376 2375
2377 for (type = 0; type < MAP__NR_TYPES; ++type) { 2376 for (type = 0; type < MAP__NR_TYPES; ++type) {
2378 struct kmap *kmap; 2377 struct kmap *kmap;
2379 2378
2380 machine->vmlinux_maps[type] = map__new2(start, kernel, type); 2379 machine->vmlinux_maps[type] = map__new2(start, kernel, type);
2381 if (machine->vmlinux_maps[type] == NULL) 2380 if (machine->vmlinux_maps[type] == NULL)
2382 return -1; 2381 return -1;
2383 2382
2384 machine->vmlinux_maps[type]->map_ip = 2383 machine->vmlinux_maps[type]->map_ip =
2385 machine->vmlinux_maps[type]->unmap_ip = 2384 machine->vmlinux_maps[type]->unmap_ip =
2386 identity__map_ip; 2385 identity__map_ip;
2387 kmap = map__kmap(machine->vmlinux_maps[type]); 2386 kmap = map__kmap(machine->vmlinux_maps[type]);
2388 kmap->kmaps = &machine->kmaps; 2387 kmap->kmaps = &machine->kmaps;
2389 map_groups__insert(&machine->kmaps, 2388 map_groups__insert(&machine->kmaps,
2390 machine->vmlinux_maps[type]); 2389 machine->vmlinux_maps[type]);
2391 } 2390 }
2392 2391
2393 return 0; 2392 return 0;
2394 } 2393 }
2395 2394
2396 void machine__destroy_kernel_maps(struct machine *machine) 2395 void machine__destroy_kernel_maps(struct machine *machine)
2397 { 2396 {
2398 enum map_type type; 2397 enum map_type type;
2399 2398
2400 for (type = 0; type < MAP__NR_TYPES; ++type) { 2399 for (type = 0; type < MAP__NR_TYPES; ++type) {
2401 struct kmap *kmap; 2400 struct kmap *kmap;
2402 2401
2403 if (machine->vmlinux_maps[type] == NULL) 2402 if (machine->vmlinux_maps[type] == NULL)
2404 continue; 2403 continue;
2405 2404
2406 kmap = map__kmap(machine->vmlinux_maps[type]); 2405 kmap = map__kmap(machine->vmlinux_maps[type]);
2407 map_groups__remove(&machine->kmaps, 2406 map_groups__remove(&machine->kmaps,
2408 machine->vmlinux_maps[type]); 2407 machine->vmlinux_maps[type]);
2409 if (kmap->ref_reloc_sym) { 2408 if (kmap->ref_reloc_sym) {
2410 /* 2409 /*
2411 * ref_reloc_sym is shared among all maps, so free just 2410 * ref_reloc_sym is shared among all maps, so free just
2412 * on one of them. 2411 * on one of them.
2413 */ 2412 */
2414 if (type == MAP__FUNCTION) { 2413 if (type == MAP__FUNCTION) {
2415 free((char *)kmap->ref_reloc_sym->name); 2414 free((char *)kmap->ref_reloc_sym->name);
2416 kmap->ref_reloc_sym->name = NULL; 2415 kmap->ref_reloc_sym->name = NULL;
2417 free(kmap->ref_reloc_sym); 2416 free(kmap->ref_reloc_sym);
2418 } 2417 }
2419 kmap->ref_reloc_sym = NULL; 2418 kmap->ref_reloc_sym = NULL;
2420 } 2419 }
2421 2420
2422 map__delete(machine->vmlinux_maps[type]); 2421 map__delete(machine->vmlinux_maps[type]);
2423 machine->vmlinux_maps[type] = NULL; 2422 machine->vmlinux_maps[type] = NULL;
2424 } 2423 }
2425 } 2424 }
2426 2425
2427 int machine__create_kernel_maps(struct machine *machine) 2426 int machine__create_kernel_maps(struct machine *machine)
2428 { 2427 {
2429 struct dso *kernel = machine__get_kernel(machine); 2428 struct dso *kernel = machine__get_kernel(machine);
2430 2429
2431 if (kernel == NULL || 2430 if (kernel == NULL ||
2432 __machine__create_kernel_maps(machine, kernel) < 0) 2431 __machine__create_kernel_maps(machine, kernel) < 0)
2433 return -1; 2432 return -1;
2434 2433
2435 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) 2434 if (symbol_conf.use_modules && machine__create_modules(machine) < 0)
2436 pr_debug("Problems creating module maps, continuing anyway...\n"); 2435 pr_debug("Problems creating module maps, continuing anyway...\n");
2437 /* 2436 /*
2438 * Now that we have all the maps created, just set the ->end of them: 2437 * Now that we have all the maps created, just set the ->end of them:
2439 */ 2438 */
2440 map_groups__fixup_end(&machine->kmaps); 2439 map_groups__fixup_end(&machine->kmaps);
2441 return 0; 2440 return 0;
2442 } 2441 }
2443 2442
2444 static void vmlinux_path__exit(void) 2443 static void vmlinux_path__exit(void)
2445 { 2444 {
2446 while (--vmlinux_path__nr_entries >= 0) { 2445 while (--vmlinux_path__nr_entries >= 0) {
2447 free(vmlinux_path[vmlinux_path__nr_entries]); 2446 free(vmlinux_path[vmlinux_path__nr_entries]);
2448 vmlinux_path[vmlinux_path__nr_entries] = NULL; 2447 vmlinux_path[vmlinux_path__nr_entries] = NULL;
2449 } 2448 }
2450 2449
2451 free(vmlinux_path); 2450 free(vmlinux_path);
2452 vmlinux_path = NULL; 2451 vmlinux_path = NULL;
2453 } 2452 }
2454 2453
2455 static int vmlinux_path__init(void) 2454 static int vmlinux_path__init(void)
2456 { 2455 {
2457 struct utsname uts; 2456 struct utsname uts;
2458 char bf[PATH_MAX]; 2457 char bf[PATH_MAX];
2459 2458
2460 vmlinux_path = malloc(sizeof(char *) * 5); 2459 vmlinux_path = malloc(sizeof(char *) * 5);
2461 if (vmlinux_path == NULL) 2460 if (vmlinux_path == NULL)
2462 return -1; 2461 return -1;
2463 2462
2464 vmlinux_path[vmlinux_path__nr_entries] = strdup("vmlinux"); 2463 vmlinux_path[vmlinux_path__nr_entries] = strdup("vmlinux");
2465 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2464 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
2466 goto out_fail; 2465 goto out_fail;
2467 ++vmlinux_path__nr_entries; 2466 ++vmlinux_path__nr_entries;
2468 vmlinux_path[vmlinux_path__nr_entries] = strdup("/boot/vmlinux"); 2467 vmlinux_path[vmlinux_path__nr_entries] = strdup("/boot/vmlinux");
2469 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2468 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
2470 goto out_fail; 2469 goto out_fail;
2471 ++vmlinux_path__nr_entries; 2470 ++vmlinux_path__nr_entries;
2472 2471
2473 /* only try running kernel version if no symfs was given */ 2472 /* only try running kernel version if no symfs was given */
2474 if (symbol_conf.symfs[0] != 0) 2473 if (symbol_conf.symfs[0] != 0)
2475 return 0; 2474 return 0;
2476 2475
2477 if (uname(&uts) < 0) 2476 if (uname(&uts) < 0)
2478 return -1; 2477 return -1;
2479 2478
2480 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 2479 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
2481 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 2480 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
2482 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2481 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
2483 goto out_fail; 2482 goto out_fail;
2484 ++vmlinux_path__nr_entries; 2483 ++vmlinux_path__nr_entries;
2485 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release); 2484 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release);
2486 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 2485 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
2487 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2486 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
2488 goto out_fail; 2487 goto out_fail;
2489 ++vmlinux_path__nr_entries; 2488 ++vmlinux_path__nr_entries;
2490 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux", 2489 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
2491 uts.release); 2490 uts.release);
2492 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 2491 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
2493 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2492 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
2494 goto out_fail; 2493 goto out_fail;
2495 ++vmlinux_path__nr_entries; 2494 ++vmlinux_path__nr_entries;
2496 2495
2497 return 0; 2496 return 0;
2498 2497
2499 out_fail: 2498 out_fail:
2500 vmlinux_path__exit(); 2499 vmlinux_path__exit();
2501 return -1; 2500 return -1;
2502 } 2501 }
2503 2502
2504 size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp) 2503 size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
2505 { 2504 {
2506 int i; 2505 int i;
2507 size_t printed = 0; 2506 size_t printed = 0;
2508 struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso; 2507 struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso;
2509 2508
2510 if (kdso->has_build_id) { 2509 if (kdso->has_build_id) {
2511 char filename[PATH_MAX]; 2510 char filename[PATH_MAX];
2512 if (dso__build_id_filename(kdso, filename, sizeof(filename))) 2511 if (dso__build_id_filename(kdso, filename, sizeof(filename)))
2513 printed += fprintf(fp, "[0] %s\n", filename); 2512 printed += fprintf(fp, "[0] %s\n", filename);
2514 } 2513 }
2515 2514
2516 for (i = 0; i < vmlinux_path__nr_entries; ++i) 2515 for (i = 0; i < vmlinux_path__nr_entries; ++i)
2517 printed += fprintf(fp, "[%d] %s\n", 2516 printed += fprintf(fp, "[%d] %s\n",
2518 i + kdso->has_build_id, vmlinux_path[i]); 2517 i + kdso->has_build_id, vmlinux_path[i]);
2519 2518
2520 return printed; 2519 return printed;
2521 } 2520 }
2522 2521
2523 static int setup_list(struct strlist **list, const char *list_str, 2522 static int setup_list(struct strlist **list, const char *list_str,
2524 const char *list_name) 2523 const char *list_name)
2525 { 2524 {
2526 if (list_str == NULL) 2525 if (list_str == NULL)
2527 return 0; 2526 return 0;
2528 2527
2529 *list = strlist__new(true, list_str); 2528 *list = strlist__new(true, list_str);
2530 if (!*list) { 2529 if (!*list) {
2531 pr_err("problems parsing %s list\n", list_name); 2530 pr_err("problems parsing %s list\n", list_name);
2532 return -1; 2531 return -1;
2533 } 2532 }
2534 return 0; 2533 return 0;
2535 } 2534 }
2536 2535
2537 static bool symbol__read_kptr_restrict(void) 2536 static bool symbol__read_kptr_restrict(void)
2538 { 2537 {
2539 bool value = false; 2538 bool value = false;
2540 2539
2541 if (geteuid() != 0) { 2540 if (geteuid() != 0) {
2542 FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r"); 2541 FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r");
2543 if (fp != NULL) { 2542 if (fp != NULL) {
2544 char line[8]; 2543 char line[8];
2545 2544
2546 if (fgets(line, sizeof(line), fp) != NULL) 2545 if (fgets(line, sizeof(line), fp) != NULL)
2547 value = atoi(line) != 0; 2546 value = atoi(line) != 0;
2548 2547
2549 fclose(fp); 2548 fclose(fp);
2550 } 2549 }
2551 } 2550 }
2552 2551
2553 return value; 2552 return value;
2554 } 2553 }
2555 2554
2556 int symbol__init(void) 2555 int symbol__init(void)
2557 { 2556 {
2558 const char *symfs; 2557 const char *symfs;
2559 2558
2560 if (symbol_conf.initialized) 2559 if (symbol_conf.initialized)
2561 return 0; 2560 return 0;
2562 2561
2563 symbol_conf.priv_size = ALIGN(symbol_conf.priv_size, sizeof(u64)); 2562 symbol_conf.priv_size = ALIGN(symbol_conf.priv_size, sizeof(u64));
2564 2563
2565 elf_version(EV_CURRENT); 2564 elf_version(EV_CURRENT);
2566 if (symbol_conf.sort_by_name) 2565 if (symbol_conf.sort_by_name)
2567 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - 2566 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
2568 sizeof(struct symbol)); 2567 sizeof(struct symbol));
2569 2568
2570 if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0) 2569 if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0)
2571 return -1; 2570 return -1;
2572 2571
2573 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') { 2572 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') {
2574 pr_err("'.' is the only non valid --field-separator argument\n"); 2573 pr_err("'.' is the only non valid --field-separator argument\n");
2575 return -1; 2574 return -1;
2576 } 2575 }
2577 2576
2578 if (setup_list(&symbol_conf.dso_list, 2577 if (setup_list(&symbol_conf.dso_list,
2579 symbol_conf.dso_list_str, "dso") < 0) 2578 symbol_conf.dso_list_str, "dso") < 0)
2580 return -1; 2579 return -1;
2581 2580
2582 if (setup_list(&symbol_conf.comm_list, 2581 if (setup_list(&symbol_conf.comm_list,
2583 symbol_conf.comm_list_str, "comm") < 0) 2582 symbol_conf.comm_list_str, "comm") < 0)
2584 goto out_free_dso_list; 2583 goto out_free_dso_list;
2585 2584
2586 if (setup_list(&symbol_conf.sym_list, 2585 if (setup_list(&symbol_conf.sym_list,
2587 symbol_conf.sym_list_str, "symbol") < 0) 2586 symbol_conf.sym_list_str, "symbol") < 0)
2588 goto out_free_comm_list; 2587 goto out_free_comm_list;
2589 2588
2590 /* 2589 /*
2591 * A path to symbols of "/" is identical to "" 2590 * A path to symbols of "/" is identical to ""
2592 * reset here for simplicity. 2591 * reset here for simplicity.
2593 */ 2592 */
2594 symfs = realpath(symbol_conf.symfs, NULL); 2593 symfs = realpath(symbol_conf.symfs, NULL);
2595 if (symfs == NULL) 2594 if (symfs == NULL)
2596 symfs = symbol_conf.symfs; 2595 symfs = symbol_conf.symfs;
2597 if (strcmp(symfs, "/") == 0) 2596 if (strcmp(symfs, "/") == 0)
2598 symbol_conf.symfs = ""; 2597 symbol_conf.symfs = "";
2599 if (symfs != symbol_conf.symfs) 2598 if (symfs != symbol_conf.symfs)
2600 free((void *)symfs); 2599 free((void *)symfs);
2601 2600
2602 symbol_conf.kptr_restrict = symbol__read_kptr_restrict(); 2601 symbol_conf.kptr_restrict = symbol__read_kptr_restrict();
2603 2602
2604 symbol_conf.initialized = true; 2603 symbol_conf.initialized = true;
2605 return 0; 2604 return 0;
2606 2605
2607 out_free_comm_list: 2606 out_free_comm_list:
2608 strlist__delete(symbol_conf.comm_list); 2607 strlist__delete(symbol_conf.comm_list);
2609 out_free_dso_list: 2608 out_free_dso_list:
2610 strlist__delete(symbol_conf.dso_list); 2609 strlist__delete(symbol_conf.dso_list);
2611 return -1; 2610 return -1;
2612 } 2611 }
2613 2612
2614 void symbol__exit(void) 2613 void symbol__exit(void)
2615 { 2614 {
2616 if (!symbol_conf.initialized) 2615 if (!symbol_conf.initialized)
2617 return; 2616 return;
2618 strlist__delete(symbol_conf.sym_list); 2617 strlist__delete(symbol_conf.sym_list);
2619 strlist__delete(symbol_conf.dso_list); 2618 strlist__delete(symbol_conf.dso_list);
2620 strlist__delete(symbol_conf.comm_list); 2619 strlist__delete(symbol_conf.comm_list);
2621 vmlinux_path__exit(); 2620 vmlinux_path__exit();
2622 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; 2621 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
2623 symbol_conf.initialized = false; 2622 symbol_conf.initialized = false;
2624 } 2623 }
2625 2624
2626 int machines__create_kernel_maps(struct rb_root *machines, pid_t pid) 2625 int machines__create_kernel_maps(struct rb_root *machines, pid_t pid)
2627 { 2626 {
2628 struct machine *machine = machines__findnew(machines, pid); 2627 struct machine *machine = machines__findnew(machines, pid);
2629 2628
2630 if (machine == NULL) 2629 if (machine == NULL)
2631 return -1; 2630 return -1;
2632 2631
2633 return machine__create_kernel_maps(machine); 2632 return machine__create_kernel_maps(machine);
2634 } 2633 }
2635 2634
2636 static int hex(char ch) 2635 static int hex(char ch)
2637 { 2636 {
2638 if ((ch >= '0') && (ch <= '9')) 2637 if ((ch >= '0') && (ch <= '9'))
2639 return ch - '0'; 2638 return ch - '0';
2640 if ((ch >= 'a') && (ch <= 'f')) 2639 if ((ch >= 'a') && (ch <= 'f'))
2641 return ch - 'a' + 10; 2640 return ch - 'a' + 10;
2642 if ((ch >= 'A') && (ch <= 'F')) 2641 if ((ch >= 'A') && (ch <= 'F'))
2643 return ch - 'A' + 10; 2642 return ch - 'A' + 10;
2644 return -1; 2643 return -1;
2645 } 2644 }
2646 2645
2647 /* 2646 /*
2648 * While we find nice hex chars, build a long_val. 2647 * While we find nice hex chars, build a long_val.
2649 * Return number of chars processed. 2648 * Return number of chars processed.
2650 */ 2649 */
2651 int hex2u64(const char *ptr, u64 *long_val) 2650 int hex2u64(const char *ptr, u64 *long_val)
2652 { 2651 {
2653 const char *p = ptr; 2652 const char *p = ptr;
2654 *long_val = 0; 2653 *long_val = 0;
2655 2654
2656 while (*p) { 2655 while (*p) {
2657 const int hex_val = hex(*p); 2656 const int hex_val = hex(*p);
2658 2657
2659 if (hex_val < 0) 2658 if (hex_val < 0)
2660 break; 2659 break;
2661 2660
2662 *long_val = (*long_val << 4) | hex_val; 2661 *long_val = (*long_val << 4) | hex_val;
2663 p++; 2662 p++;
2664 } 2663 }
2665 2664
2666 return p - ptr; 2665 return p - ptr;
2667 } 2666 }
2668 2667
2669 char *strxfrchar(char *s, char from, char to) 2668 char *strxfrchar(char *s, char from, char to)
2670 { 2669 {
2671 char *p = s; 2670 char *p = s;
2672 2671
2673 while ((p = strchr(p, from)) != NULL) 2672 while ((p = strchr(p, from)) != NULL)
2674 *p++ = to; 2673 *p++ = to;
2675 2674
2676 return s; 2675 return s;
2677 } 2676 }
2678 2677
2679 int machines__create_guest_kernel_maps(struct rb_root *machines) 2678 int machines__create_guest_kernel_maps(struct rb_root *machines)
2680 { 2679 {
2681 int ret = 0; 2680 int ret = 0;
2682 struct dirent **namelist = NULL; 2681 struct dirent **namelist = NULL;
2683 int i, items = 0; 2682 int i, items = 0;
2684 char path[PATH_MAX]; 2683 char path[PATH_MAX];
2685 pid_t pid; 2684 pid_t pid;
2686 2685
2687 if (symbol_conf.default_guest_vmlinux_name || 2686 if (symbol_conf.default_guest_vmlinux_name ||
2688 symbol_conf.default_guest_modules || 2687 symbol_conf.default_guest_modules ||
2689 symbol_conf.default_guest_kallsyms) { 2688 symbol_conf.default_guest_kallsyms) {
2690 machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID); 2689 machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID);
2691 } 2690 }
2692 2691
2693 if (symbol_conf.guestmount) { 2692 if (symbol_conf.guestmount) {
2694 items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL); 2693 items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL);
2695 if (items <= 0) 2694 if (items <= 0)
2696 return -ENOENT; 2695 return -ENOENT;
2697 for (i = 0; i < items; i++) { 2696 for (i = 0; i < items; i++) {
2698 if (!isdigit(namelist[i]->d_name[0])) { 2697 if (!isdigit(namelist[i]->d_name[0])) {
2699 /* Filter out . and .. */ 2698 /* Filter out . and .. */
2700 continue; 2699 continue;
2701 } 2700 }
2702 pid = atoi(namelist[i]->d_name); 2701 pid = atoi(namelist[i]->d_name);
2703 sprintf(path, "%s/%s/proc/kallsyms", 2702 sprintf(path, "%s/%s/proc/kallsyms",
2704 symbol_conf.guestmount, 2703 symbol_conf.guestmount,
2705 namelist[i]->d_name); 2704 namelist[i]->d_name);
2706 ret = access(path, R_OK); 2705 ret = access(path, R_OK);
2707 if (ret) { 2706 if (ret) {
2708 pr_debug("Can't access file %s\n", path); 2707 pr_debug("Can't access file %s\n", path);
2709 goto failure; 2708 goto failure;
2710 } 2709 }
2711 machines__create_kernel_maps(machines, pid); 2710 machines__create_kernel_maps(machines, pid);
2712 } 2711 }
2713 failure: 2712 failure:
2714 free(namelist); 2713 free(namelist);
2715 } 2714 }
2716 2715
2717 return ret; 2716 return ret;
2718 } 2717 }
2719 2718
2720 void machines__destroy_guest_kernel_maps(struct rb_root *machines) 2719 void machines__destroy_guest_kernel_maps(struct rb_root *machines)
2721 { 2720 {
2722 struct rb_node *next = rb_first(machines); 2721 struct rb_node *next = rb_first(machines);
2723 2722
2724 while (next) { 2723 while (next) {
2725 struct machine *pos = rb_entry(next, struct machine, rb_node); 2724 struct machine *pos = rb_entry(next, struct machine, rb_node);
2726 2725
2727 next = rb_next(&pos->rb_node); 2726 next = rb_next(&pos->rb_node);
2728 rb_erase(&pos->rb_node, machines); 2727 rb_erase(&pos->rb_node, machines);
2729 machine__delete(pos); 2728 machine__delete(pos);
2730 } 2729 }
2731 } 2730 }
2732 2731
2733 int machine__load_kallsyms(struct machine *machine, const char *filename, 2732 int machine__load_kallsyms(struct machine *machine, const char *filename,
2734 enum map_type type, symbol_filter_t filter) 2733 enum map_type type, symbol_filter_t filter)
2735 { 2734 {
2736 struct map *map = machine->vmlinux_maps[type]; 2735 struct map *map = machine->vmlinux_maps[type];
2737 int ret = dso__load_kallsyms(map->dso, filename, map, filter); 2736 int ret = dso__load_kallsyms(map->dso, filename, map, filter);
2738 2737
2739 if (ret > 0) { 2738 if (ret > 0) {
2740 dso__set_loaded(map->dso, type); 2739 dso__set_loaded(map->dso, type);
2741 /* 2740 /*
2742 * Since /proc/kallsyms will have multiple sessions for the 2741 * Since /proc/kallsyms will have multiple sessions for the
2743 * kernel, with modules between them, fixup the end of all 2742 * kernel, with modules between them, fixup the end of all
2744 * sections. 2743 * sections.
2745 */ 2744 */
2746 __map_groups__fixup_end(&machine->kmaps, type); 2745 __map_groups__fixup_end(&machine->kmaps, type);
2747 } 2746 }
2748 2747
2749 return ret; 2748 return ret;
2750 } 2749 }
2751 2750
2752 int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 2751 int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
2753 symbol_filter_t filter) 2752 symbol_filter_t filter)
2754 { 2753 {
2755 struct map *map = machine->vmlinux_maps[type]; 2754 struct map *map = machine->vmlinux_maps[type];
2756 int ret = dso__load_vmlinux_path(map->dso, map, filter); 2755 int ret = dso__load_vmlinux_path(map->dso, map, filter);
2757 2756
2758 if (ret > 0) { 2757 if (ret > 0) {
2759 dso__set_loaded(map->dso, type); 2758 dso__set_loaded(map->dso, type);
2760 map__reloc_vmlinux(map); 2759 map__reloc_vmlinux(map);
2761 } 2760 }
2762 2761
2763 return ret; 2762 return ret;
2764 } 2763 }
2765 2764
tools/perf/util/trace-event-parse.c
1 /* 1 /*
2 * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com> 2 * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com>
3 * 3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License (not later!) 8 * the Free Software Foundation; version 2 of the License (not later!)
9 * 9 *
10 * This program is distributed in the hope that it will be useful, 10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU General Public License 15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software 16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * 18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 * 20 *
21 * The parts for function graph printing was taken and modified from the 21 * The parts for function graph printing was taken and modified from the
22 * Linux Kernel that were written by Frederic Weisbecker. 22 * Linux Kernel that were written by Frederic Weisbecker.
23 */ 23 */
24 #define _GNU_SOURCE 24
25 #include <stdio.h> 25 #include <stdio.h>
26 #include <stdlib.h> 26 #include <stdlib.h>
27 #include <string.h> 27 #include <string.h>
28 #include <ctype.h> 28 #include <ctype.h>
29 #include <errno.h> 29 #include <errno.h>
30 30
31 #undef _GNU_SOURCE
32 #include "../perf.h" 31 #include "../perf.h"
33 #include "util.h" 32 #include "util.h"
34 #include "trace-event.h" 33 #include "trace-event.h"
35 34
36 int header_page_ts_offset; 35 int header_page_ts_offset;
37 int header_page_ts_size; 36 int header_page_ts_size;
38 int header_page_size_offset; 37 int header_page_size_offset;
39 int header_page_size_size; 38 int header_page_size_size;
40 int header_page_overwrite_offset; 39 int header_page_overwrite_offset;
41 int header_page_overwrite_size; 40 int header_page_overwrite_size;
42 int header_page_data_offset; 41 int header_page_data_offset;
43 int header_page_data_size; 42 int header_page_data_size;
44 43
45 bool latency_format; 44 bool latency_format;
46 45
47 static char *input_buf; 46 static char *input_buf;
48 static unsigned long long input_buf_ptr; 47 static unsigned long long input_buf_ptr;
49 static unsigned long long input_buf_siz; 48 static unsigned long long input_buf_siz;
50 49
51 static int cpus; 50 static int cpus;
52 static int long_size; 51 static int long_size;
53 static int is_flag_field; 52 static int is_flag_field;
54 static int is_symbolic_field; 53 static int is_symbolic_field;
55 54
56 static struct format_field * 55 static struct format_field *
57 find_any_field(struct event *event, const char *name); 56 find_any_field(struct event *event, const char *name);
58 57
59 static void init_input_buf(char *buf, unsigned long long size) 58 static void init_input_buf(char *buf, unsigned long long size)
60 { 59 {
61 input_buf = buf; 60 input_buf = buf;
62 input_buf_siz = size; 61 input_buf_siz = size;
63 input_buf_ptr = 0; 62 input_buf_ptr = 0;
64 } 63 }
65 64
66 struct cmdline { 65 struct cmdline {
67 char *comm; 66 char *comm;
68 int pid; 67 int pid;
69 }; 68 };
70 69
71 static struct cmdline *cmdlines; 70 static struct cmdline *cmdlines;
72 static int cmdline_count; 71 static int cmdline_count;
73 72
74 static int cmdline_cmp(const void *a, const void *b) 73 static int cmdline_cmp(const void *a, const void *b)
75 { 74 {
76 const struct cmdline *ca = a; 75 const struct cmdline *ca = a;
77 const struct cmdline *cb = b; 76 const struct cmdline *cb = b;
78 77
79 if (ca->pid < cb->pid) 78 if (ca->pid < cb->pid)
80 return -1; 79 return -1;
81 if (ca->pid > cb->pid) 80 if (ca->pid > cb->pid)
82 return 1; 81 return 1;
83 82
84 return 0; 83 return 0;
85 } 84 }
86 85
87 void parse_cmdlines(char *file, int size __unused) 86 void parse_cmdlines(char *file, int size __unused)
88 { 87 {
89 struct cmdline_list { 88 struct cmdline_list {
90 struct cmdline_list *next; 89 struct cmdline_list *next;
91 char *comm; 90 char *comm;
92 int pid; 91 int pid;
93 } *list = NULL, *item; 92 } *list = NULL, *item;
94 char *line; 93 char *line;
95 char *next = NULL; 94 char *next = NULL;
96 int i; 95 int i;
97 96
98 line = strtok_r(file, "\n", &next); 97 line = strtok_r(file, "\n", &next);
99 while (line) { 98 while (line) {
100 item = malloc_or_die(sizeof(*item)); 99 item = malloc_or_die(sizeof(*item));
101 sscanf(line, "%d %as", &item->pid, 100 sscanf(line, "%d %as", &item->pid,
102 (float *)(void *)&item->comm); /* workaround gcc warning */ 101 (float *)(void *)&item->comm); /* workaround gcc warning */
103 item->next = list; 102 item->next = list;
104 list = item; 103 list = item;
105 line = strtok_r(NULL, "\n", &next); 104 line = strtok_r(NULL, "\n", &next);
106 cmdline_count++; 105 cmdline_count++;
107 } 106 }
108 107
109 cmdlines = malloc_or_die(sizeof(*cmdlines) * cmdline_count); 108 cmdlines = malloc_or_die(sizeof(*cmdlines) * cmdline_count);
110 109
111 i = 0; 110 i = 0;
112 while (list) { 111 while (list) {
113 cmdlines[i].pid = list->pid; 112 cmdlines[i].pid = list->pid;
114 cmdlines[i].comm = list->comm; 113 cmdlines[i].comm = list->comm;
115 i++; 114 i++;
116 item = list; 115 item = list;
117 list = list->next; 116 list = list->next;
118 free(item); 117 free(item);
119 } 118 }
120 119
121 qsort(cmdlines, cmdline_count, sizeof(*cmdlines), cmdline_cmp); 120 qsort(cmdlines, cmdline_count, sizeof(*cmdlines), cmdline_cmp);
122 } 121 }
123 122
124 static struct func_map { 123 static struct func_map {
125 unsigned long long addr; 124 unsigned long long addr;
126 char *func; 125 char *func;
127 char *mod; 126 char *mod;
128 } *func_list; 127 } *func_list;
129 static unsigned int func_count; 128 static unsigned int func_count;
130 129
131 static int func_cmp(const void *a, const void *b) 130 static int func_cmp(const void *a, const void *b)
132 { 131 {
133 const struct func_map *fa = a; 132 const struct func_map *fa = a;
134 const struct func_map *fb = b; 133 const struct func_map *fb = b;
135 134
136 if (fa->addr < fb->addr) 135 if (fa->addr < fb->addr)
137 return -1; 136 return -1;
138 if (fa->addr > fb->addr) 137 if (fa->addr > fb->addr)
139 return 1; 138 return 1;
140 139
141 return 0; 140 return 0;
142 } 141 }
143 142
144 void parse_proc_kallsyms(char *file, unsigned int size __unused) 143 void parse_proc_kallsyms(char *file, unsigned int size __unused)
145 { 144 {
146 struct func_list { 145 struct func_list {
147 struct func_list *next; 146 struct func_list *next;
148 unsigned long long addr; 147 unsigned long long addr;
149 char *func; 148 char *func;
150 char *mod; 149 char *mod;
151 } *list = NULL, *item; 150 } *list = NULL, *item;
152 char *line; 151 char *line;
153 char *next = NULL; 152 char *next = NULL;
154 char *addr_str; 153 char *addr_str;
155 char ch; 154 char ch;
156 int ret __used; 155 int ret __used;
157 int i; 156 int i;
158 157
159 line = strtok_r(file, "\n", &next); 158 line = strtok_r(file, "\n", &next);
160 while (line) { 159 while (line) {
161 item = malloc_or_die(sizeof(*item)); 160 item = malloc_or_die(sizeof(*item));
162 item->mod = NULL; 161 item->mod = NULL;
163 ret = sscanf(line, "%as %c %as\t[%as", 162 ret = sscanf(line, "%as %c %as\t[%as",
164 (float *)(void *)&addr_str, /* workaround gcc warning */ 163 (float *)(void *)&addr_str, /* workaround gcc warning */
165 &ch, 164 &ch,
166 (float *)(void *)&item->func, 165 (float *)(void *)&item->func,
167 (float *)(void *)&item->mod); 166 (float *)(void *)&item->mod);
168 item->addr = strtoull(addr_str, NULL, 16); 167 item->addr = strtoull(addr_str, NULL, 16);
169 free(addr_str); 168 free(addr_str);
170 169
171 /* truncate the extra ']' */ 170 /* truncate the extra ']' */
172 if (item->mod) 171 if (item->mod)
173 item->mod[strlen(item->mod) - 1] = 0; 172 item->mod[strlen(item->mod) - 1] = 0;
174 173
175 174
176 item->next = list; 175 item->next = list;
177 list = item; 176 list = item;
178 line = strtok_r(NULL, "\n", &next); 177 line = strtok_r(NULL, "\n", &next);
179 func_count++; 178 func_count++;
180 } 179 }
181 180
182 func_list = malloc_or_die(sizeof(*func_list) * (func_count + 1)); 181 func_list = malloc_or_die(sizeof(*func_list) * (func_count + 1));
183 182
184 i = 0; 183 i = 0;
185 while (list) { 184 while (list) {
186 func_list[i].func = list->func; 185 func_list[i].func = list->func;
187 func_list[i].addr = list->addr; 186 func_list[i].addr = list->addr;
188 func_list[i].mod = list->mod; 187 func_list[i].mod = list->mod;
189 i++; 188 i++;
190 item = list; 189 item = list;
191 list = list->next; 190 list = list->next;
192 free(item); 191 free(item);
193 } 192 }
194 193
195 qsort(func_list, func_count, sizeof(*func_list), func_cmp); 194 qsort(func_list, func_count, sizeof(*func_list), func_cmp);
196 195
197 /* 196 /*
198 * Add a special record at the end. 197 * Add a special record at the end.
199 */ 198 */
200 func_list[func_count].func = NULL; 199 func_list[func_count].func = NULL;
201 func_list[func_count].addr = 0; 200 func_list[func_count].addr = 0;
202 func_list[func_count].mod = NULL; 201 func_list[func_count].mod = NULL;
203 } 202 }
204 203
205 /* 204 /*
206 * We are searching for a record in between, not an exact 205 * We are searching for a record in between, not an exact
207 * match. 206 * match.
208 */ 207 */
209 static int func_bcmp(const void *a, const void *b) 208 static int func_bcmp(const void *a, const void *b)
210 { 209 {
211 const struct func_map *fa = a; 210 const struct func_map *fa = a;
212 const struct func_map *fb = b; 211 const struct func_map *fb = b;
213 212
214 if ((fa->addr == fb->addr) || 213 if ((fa->addr == fb->addr) ||
215 214
216 (fa->addr > fb->addr && 215 (fa->addr > fb->addr &&
217 fa->addr < (fb+1)->addr)) 216 fa->addr < (fb+1)->addr))
218 return 0; 217 return 0;
219 218
220 if (fa->addr < fb->addr) 219 if (fa->addr < fb->addr)
221 return -1; 220 return -1;
222 221
223 return 1; 222 return 1;
224 } 223 }
225 224
226 static struct func_map *find_func(unsigned long long addr) 225 static struct func_map *find_func(unsigned long long addr)
227 { 226 {
228 struct func_map *func; 227 struct func_map *func;
229 struct func_map key; 228 struct func_map key;
230 229
231 key.addr = addr; 230 key.addr = addr;
232 231
233 func = bsearch(&key, func_list, func_count, sizeof(*func_list), 232 func = bsearch(&key, func_list, func_count, sizeof(*func_list),
234 func_bcmp); 233 func_bcmp);
235 234
236 return func; 235 return func;
237 } 236 }
238 237
239 void print_funcs(void) 238 void print_funcs(void)
240 { 239 {
241 int i; 240 int i;
242 241
243 for (i = 0; i < (int)func_count; i++) { 242 for (i = 0; i < (int)func_count; i++) {
244 printf("%016llx %s", 243 printf("%016llx %s",
245 func_list[i].addr, 244 func_list[i].addr,
246 func_list[i].func); 245 func_list[i].func);
247 if (func_list[i].mod) 246 if (func_list[i].mod)
248 printf(" [%s]\n", func_list[i].mod); 247 printf(" [%s]\n", func_list[i].mod);
249 else 248 else
250 printf("\n"); 249 printf("\n");
251 } 250 }
252 } 251 }
253 252
254 static struct printk_map { 253 static struct printk_map {
255 unsigned long long addr; 254 unsigned long long addr;
256 char *printk; 255 char *printk;
257 } *printk_list; 256 } *printk_list;
258 static unsigned int printk_count; 257 static unsigned int printk_count;
259 258
260 static int printk_cmp(const void *a, const void *b) 259 static int printk_cmp(const void *a, const void *b)
261 { 260 {
262 const struct func_map *fa = a; 261 const struct func_map *fa = a;
263 const struct func_map *fb = b; 262 const struct func_map *fb = b;
264 263
265 if (fa->addr < fb->addr) 264 if (fa->addr < fb->addr)
266 return -1; 265 return -1;
267 if (fa->addr > fb->addr) 266 if (fa->addr > fb->addr)
268 return 1; 267 return 1;
269 268
270 return 0; 269 return 0;
271 } 270 }
272 271
273 static struct printk_map *find_printk(unsigned long long addr) 272 static struct printk_map *find_printk(unsigned long long addr)
274 { 273 {
275 struct printk_map *printk; 274 struct printk_map *printk;
276 struct printk_map key; 275 struct printk_map key;
277 276
278 key.addr = addr; 277 key.addr = addr;
279 278
280 printk = bsearch(&key, printk_list, printk_count, sizeof(*printk_list), 279 printk = bsearch(&key, printk_list, printk_count, sizeof(*printk_list),
281 printk_cmp); 280 printk_cmp);
282 281
283 return printk; 282 return printk;
284 } 283 }
285 284
286 void parse_ftrace_printk(char *file, unsigned int size __unused) 285 void parse_ftrace_printk(char *file, unsigned int size __unused)
287 { 286 {
288 struct printk_list { 287 struct printk_list {
289 struct printk_list *next; 288 struct printk_list *next;
290 unsigned long long addr; 289 unsigned long long addr;
291 char *printk; 290 char *printk;
292 } *list = NULL, *item; 291 } *list = NULL, *item;
293 char *line; 292 char *line;
294 char *next = NULL; 293 char *next = NULL;
295 char *addr_str; 294 char *addr_str;
296 int i; 295 int i;
297 296
298 line = strtok_r(file, "\n", &next); 297 line = strtok_r(file, "\n", &next);
299 while (line) { 298 while (line) {
300 addr_str = strsep(&line, ":"); 299 addr_str = strsep(&line, ":");
301 if (!line) { 300 if (!line) {
302 warning("error parsing print strings"); 301 warning("error parsing print strings");
303 break; 302 break;
304 } 303 }
305 item = malloc_or_die(sizeof(*item)); 304 item = malloc_or_die(sizeof(*item));
306 item->addr = strtoull(addr_str, NULL, 16); 305 item->addr = strtoull(addr_str, NULL, 16);
307 /* fmt still has a space, skip it */ 306 /* fmt still has a space, skip it */
308 item->printk = strdup(line+1); 307 item->printk = strdup(line+1);
309 item->next = list; 308 item->next = list;
310 list = item; 309 list = item;
311 line = strtok_r(NULL, "\n", &next); 310 line = strtok_r(NULL, "\n", &next);
312 printk_count++; 311 printk_count++;
313 } 312 }
314 313
315 printk_list = malloc_or_die(sizeof(*printk_list) * printk_count + 1); 314 printk_list = malloc_or_die(sizeof(*printk_list) * printk_count + 1);
316 315
317 i = 0; 316 i = 0;
318 while (list) { 317 while (list) {
319 printk_list[i].printk = list->printk; 318 printk_list[i].printk = list->printk;
320 printk_list[i].addr = list->addr; 319 printk_list[i].addr = list->addr;
321 i++; 320 i++;
322 item = list; 321 item = list;
323 list = list->next; 322 list = list->next;
324 free(item); 323 free(item);
325 } 324 }
326 325
327 qsort(printk_list, printk_count, sizeof(*printk_list), printk_cmp); 326 qsort(printk_list, printk_count, sizeof(*printk_list), printk_cmp);
328 } 327 }
329 328
330 void print_printk(void) 329 void print_printk(void)
331 { 330 {
332 int i; 331 int i;
333 332
334 for (i = 0; i < (int)printk_count; i++) { 333 for (i = 0; i < (int)printk_count; i++) {
335 printf("%016llx %s\n", 334 printf("%016llx %s\n",
336 printk_list[i].addr, 335 printk_list[i].addr,
337 printk_list[i].printk); 336 printk_list[i].printk);
338 } 337 }
339 } 338 }
340 339
341 static struct event *alloc_event(void) 340 static struct event *alloc_event(void)
342 { 341 {
343 struct event *event; 342 struct event *event;
344 343
345 event = malloc_or_die(sizeof(*event)); 344 event = malloc_or_die(sizeof(*event));
346 memset(event, 0, sizeof(*event)); 345 memset(event, 0, sizeof(*event));
347 346
348 return event; 347 return event;
349 } 348 }
350 349
351 enum event_type { 350 enum event_type {
352 EVENT_ERROR, 351 EVENT_ERROR,
353 EVENT_NONE, 352 EVENT_NONE,
354 EVENT_SPACE, 353 EVENT_SPACE,
355 EVENT_NEWLINE, 354 EVENT_NEWLINE,
356 EVENT_OP, 355 EVENT_OP,
357 EVENT_DELIM, 356 EVENT_DELIM,
358 EVENT_ITEM, 357 EVENT_ITEM,
359 EVENT_DQUOTE, 358 EVENT_DQUOTE,
360 EVENT_SQUOTE, 359 EVENT_SQUOTE,
361 }; 360 };
362 361
363 static struct event *event_list; 362 static struct event *event_list;
364 363
365 static void add_event(struct event *event) 364 static void add_event(struct event *event)
366 { 365 {
367 event->next = event_list; 366 event->next = event_list;
368 event_list = event; 367 event_list = event;
369 } 368 }
370 369
371 static int event_item_type(enum event_type type) 370 static int event_item_type(enum event_type type)
372 { 371 {
373 switch (type) { 372 switch (type) {
374 case EVENT_ITEM ... EVENT_SQUOTE: 373 case EVENT_ITEM ... EVENT_SQUOTE:
375 return 1; 374 return 1;
376 case EVENT_ERROR ... EVENT_DELIM: 375 case EVENT_ERROR ... EVENT_DELIM:
377 default: 376 default:
378 return 0; 377 return 0;
379 } 378 }
380 } 379 }
381 380
382 static void free_arg(struct print_arg *arg) 381 static void free_arg(struct print_arg *arg)
383 { 382 {
384 if (!arg) 383 if (!arg)
385 return; 384 return;
386 385
387 switch (arg->type) { 386 switch (arg->type) {
388 case PRINT_ATOM: 387 case PRINT_ATOM:
389 if (arg->atom.atom) 388 if (arg->atom.atom)
390 free(arg->atom.atom); 389 free(arg->atom.atom);
391 break; 390 break;
392 case PRINT_NULL: 391 case PRINT_NULL:
393 case PRINT_FIELD ... PRINT_OP: 392 case PRINT_FIELD ... PRINT_OP:
394 default: 393 default:
395 /* todo */ 394 /* todo */
396 break; 395 break;
397 } 396 }
398 397
399 free(arg); 398 free(arg);
400 } 399 }
401 400
402 static enum event_type get_type(int ch) 401 static enum event_type get_type(int ch)
403 { 402 {
404 if (ch == '\n') 403 if (ch == '\n')
405 return EVENT_NEWLINE; 404 return EVENT_NEWLINE;
406 if (isspace(ch)) 405 if (isspace(ch))
407 return EVENT_SPACE; 406 return EVENT_SPACE;
408 if (isalnum(ch) || ch == '_') 407 if (isalnum(ch) || ch == '_')
409 return EVENT_ITEM; 408 return EVENT_ITEM;
410 if (ch == '\'') 409 if (ch == '\'')
411 return EVENT_SQUOTE; 410 return EVENT_SQUOTE;
412 if (ch == '"') 411 if (ch == '"')
413 return EVENT_DQUOTE; 412 return EVENT_DQUOTE;
414 if (!isprint(ch)) 413 if (!isprint(ch))
415 return EVENT_NONE; 414 return EVENT_NONE;
416 if (ch == '(' || ch == ')' || ch == ',') 415 if (ch == '(' || ch == ')' || ch == ',')
417 return EVENT_DELIM; 416 return EVENT_DELIM;
418 417
419 return EVENT_OP; 418 return EVENT_OP;
420 } 419 }
421 420
422 static int __read_char(void) 421 static int __read_char(void)
423 { 422 {
424 if (input_buf_ptr >= input_buf_siz) 423 if (input_buf_ptr >= input_buf_siz)
425 return -1; 424 return -1;
426 425
427 return input_buf[input_buf_ptr++]; 426 return input_buf[input_buf_ptr++];
428 } 427 }
429 428
430 static int __peek_char(void) 429 static int __peek_char(void)
431 { 430 {
432 if (input_buf_ptr >= input_buf_siz) 431 if (input_buf_ptr >= input_buf_siz)
433 return -1; 432 return -1;
434 433
435 return input_buf[input_buf_ptr]; 434 return input_buf[input_buf_ptr];
436 } 435 }
437 436
438 static enum event_type __read_token(char **tok) 437 static enum event_type __read_token(char **tok)
439 { 438 {
440 char buf[BUFSIZ]; 439 char buf[BUFSIZ];
441 int ch, last_ch, quote_ch, next_ch; 440 int ch, last_ch, quote_ch, next_ch;
442 int i = 0; 441 int i = 0;
443 int tok_size = 0; 442 int tok_size = 0;
444 enum event_type type; 443 enum event_type type;
445 444
446 *tok = NULL; 445 *tok = NULL;
447 446
448 447
449 ch = __read_char(); 448 ch = __read_char();
450 if (ch < 0) 449 if (ch < 0)
451 return EVENT_NONE; 450 return EVENT_NONE;
452 451
453 type = get_type(ch); 452 type = get_type(ch);
454 if (type == EVENT_NONE) 453 if (type == EVENT_NONE)
455 return type; 454 return type;
456 455
457 buf[i++] = ch; 456 buf[i++] = ch;
458 457
459 switch (type) { 458 switch (type) {
460 case EVENT_NEWLINE: 459 case EVENT_NEWLINE:
461 case EVENT_DELIM: 460 case EVENT_DELIM:
462 *tok = malloc_or_die(2); 461 *tok = malloc_or_die(2);
463 (*tok)[0] = ch; 462 (*tok)[0] = ch;
464 (*tok)[1] = 0; 463 (*tok)[1] = 0;
465 return type; 464 return type;
466 465
467 case EVENT_OP: 466 case EVENT_OP:
468 switch (ch) { 467 switch (ch) {
469 case '-': 468 case '-':
470 next_ch = __peek_char(); 469 next_ch = __peek_char();
471 if (next_ch == '>') { 470 if (next_ch == '>') {
472 buf[i++] = __read_char(); 471 buf[i++] = __read_char();
473 break; 472 break;
474 } 473 }
475 /* fall through */ 474 /* fall through */
476 case '+': 475 case '+':
477 case '|': 476 case '|':
478 case '&': 477 case '&':
479 case '>': 478 case '>':
480 case '<': 479 case '<':
481 last_ch = ch; 480 last_ch = ch;
482 ch = __peek_char(); 481 ch = __peek_char();
483 if (ch != last_ch) 482 if (ch != last_ch)
484 goto test_equal; 483 goto test_equal;
485 buf[i++] = __read_char(); 484 buf[i++] = __read_char();
486 switch (last_ch) { 485 switch (last_ch) {
487 case '>': 486 case '>':
488 case '<': 487 case '<':
489 goto test_equal; 488 goto test_equal;
490 default: 489 default:
491 break; 490 break;
492 } 491 }
493 break; 492 break;
494 case '!': 493 case '!':
495 case '=': 494 case '=':
496 goto test_equal; 495 goto test_equal;
497 default: /* what should we do instead? */ 496 default: /* what should we do instead? */
498 break; 497 break;
499 } 498 }
500 buf[i] = 0; 499 buf[i] = 0;
501 *tok = strdup(buf); 500 *tok = strdup(buf);
502 return type; 501 return type;
503 502
504 test_equal: 503 test_equal:
505 ch = __peek_char(); 504 ch = __peek_char();
506 if (ch == '=') 505 if (ch == '=')
507 buf[i++] = __read_char(); 506 buf[i++] = __read_char();
508 break; 507 break;
509 508
510 case EVENT_DQUOTE: 509 case EVENT_DQUOTE:
511 case EVENT_SQUOTE: 510 case EVENT_SQUOTE:
512 /* don't keep quotes */ 511 /* don't keep quotes */
513 i--; 512 i--;
514 quote_ch = ch; 513 quote_ch = ch;
515 last_ch = 0; 514 last_ch = 0;
516 do { 515 do {
517 if (i == (BUFSIZ - 1)) { 516 if (i == (BUFSIZ - 1)) {
518 buf[i] = 0; 517 buf[i] = 0;
519 if (*tok) { 518 if (*tok) {
520 *tok = realloc(*tok, tok_size + BUFSIZ); 519 *tok = realloc(*tok, tok_size + BUFSIZ);
521 if (!*tok) 520 if (!*tok)
522 return EVENT_NONE; 521 return EVENT_NONE;
523 strcat(*tok, buf); 522 strcat(*tok, buf);
524 } else 523 } else
525 *tok = strdup(buf); 524 *tok = strdup(buf);
526 525
527 if (!*tok) 526 if (!*tok)
528 return EVENT_NONE; 527 return EVENT_NONE;
529 tok_size += BUFSIZ; 528 tok_size += BUFSIZ;
530 i = 0; 529 i = 0;
531 } 530 }
532 last_ch = ch; 531 last_ch = ch;
533 ch = __read_char(); 532 ch = __read_char();
534 buf[i++] = ch; 533 buf[i++] = ch;
535 /* the '\' '\' will cancel itself */ 534 /* the '\' '\' will cancel itself */
536 if (ch == '\\' && last_ch == '\\') 535 if (ch == '\\' && last_ch == '\\')
537 last_ch = 0; 536 last_ch = 0;
538 } while (ch != quote_ch || last_ch == '\\'); 537 } while (ch != quote_ch || last_ch == '\\');
539 /* remove the last quote */ 538 /* remove the last quote */
540 i--; 539 i--;
541 goto out; 540 goto out;
542 541
543 case EVENT_ERROR ... EVENT_SPACE: 542 case EVENT_ERROR ... EVENT_SPACE:
544 case EVENT_ITEM: 543 case EVENT_ITEM:
545 default: 544 default:
546 break; 545 break;
547 } 546 }
548 547
549 while (get_type(__peek_char()) == type) { 548 while (get_type(__peek_char()) == type) {
550 if (i == (BUFSIZ - 1)) { 549 if (i == (BUFSIZ - 1)) {
551 buf[i] = 0; 550 buf[i] = 0;
552 if (*tok) { 551 if (*tok) {
553 *tok = realloc(*tok, tok_size + BUFSIZ); 552 *tok = realloc(*tok, tok_size + BUFSIZ);
554 if (!*tok) 553 if (!*tok)
555 return EVENT_NONE; 554 return EVENT_NONE;
556 strcat(*tok, buf); 555 strcat(*tok, buf);
557 } else 556 } else
558 *tok = strdup(buf); 557 *tok = strdup(buf);
559 558
560 if (!*tok) 559 if (!*tok)
561 return EVENT_NONE; 560 return EVENT_NONE;
562 tok_size += BUFSIZ; 561 tok_size += BUFSIZ;
563 i = 0; 562 i = 0;
564 } 563 }
565 ch = __read_char(); 564 ch = __read_char();
566 buf[i++] = ch; 565 buf[i++] = ch;
567 } 566 }
568 567
569 out: 568 out:
570 buf[i] = 0; 569 buf[i] = 0;
571 if (*tok) { 570 if (*tok) {
572 *tok = realloc(*tok, tok_size + i); 571 *tok = realloc(*tok, tok_size + i);
573 if (!*tok) 572 if (!*tok)
574 return EVENT_NONE; 573 return EVENT_NONE;
575 strcat(*tok, buf); 574 strcat(*tok, buf);
576 } else 575 } else
577 *tok = strdup(buf); 576 *tok = strdup(buf);
578 if (!*tok) 577 if (!*tok)
579 return EVENT_NONE; 578 return EVENT_NONE;
580 579
581 return type; 580 return type;
582 } 581 }
583 582
584 static void free_token(char *tok) 583 static void free_token(char *tok)
585 { 584 {
586 if (tok) 585 if (tok)
587 free(tok); 586 free(tok);
588 } 587 }
589 588
590 static enum event_type read_token(char **tok) 589 static enum event_type read_token(char **tok)
591 { 590 {
592 enum event_type type; 591 enum event_type type;
593 592
594 for (;;) { 593 for (;;) {
595 type = __read_token(tok); 594 type = __read_token(tok);
596 if (type != EVENT_SPACE) 595 if (type != EVENT_SPACE)
597 return type; 596 return type;
598 597
599 free_token(*tok); 598 free_token(*tok);
600 } 599 }
601 600
602 /* not reached */ 601 /* not reached */
603 return EVENT_NONE; 602 return EVENT_NONE;
604 } 603 }
605 604
606 /* no newline */ 605 /* no newline */
607 static enum event_type read_token_item(char **tok) 606 static enum event_type read_token_item(char **tok)
608 { 607 {
609 enum event_type type; 608 enum event_type type;
610 609
611 for (;;) { 610 for (;;) {
612 type = __read_token(tok); 611 type = __read_token(tok);
613 if (type != EVENT_SPACE && type != EVENT_NEWLINE) 612 if (type != EVENT_SPACE && type != EVENT_NEWLINE)
614 return type; 613 return type;
615 614
616 free_token(*tok); 615 free_token(*tok);
617 } 616 }
618 617
619 /* not reached */ 618 /* not reached */
620 return EVENT_NONE; 619 return EVENT_NONE;
621 } 620 }
622 621
623 static int test_type(enum event_type type, enum event_type expect) 622 static int test_type(enum event_type type, enum event_type expect)
624 { 623 {
625 if (type != expect) { 624 if (type != expect) {
626 warning("Error: expected type %d but read %d", 625 warning("Error: expected type %d but read %d",
627 expect, type); 626 expect, type);
628 return -1; 627 return -1;
629 } 628 }
630 return 0; 629 return 0;
631 } 630 }
632 631
633 static int __test_type_token(enum event_type type, char *token, 632 static int __test_type_token(enum event_type type, char *token,
634 enum event_type expect, const char *expect_tok, 633 enum event_type expect, const char *expect_tok,
635 bool warn) 634 bool warn)
636 { 635 {
637 if (type != expect) { 636 if (type != expect) {
638 if (warn) 637 if (warn)
639 warning("Error: expected type %d but read %d", 638 warning("Error: expected type %d but read %d",
640 expect, type); 639 expect, type);
641 return -1; 640 return -1;
642 } 641 }
643 642
644 if (strcmp(token, expect_tok) != 0) { 643 if (strcmp(token, expect_tok) != 0) {
645 if (warn) 644 if (warn)
646 warning("Error: expected '%s' but read '%s'", 645 warning("Error: expected '%s' but read '%s'",
647 expect_tok, token); 646 expect_tok, token);
648 return -1; 647 return -1;
649 } 648 }
650 return 0; 649 return 0;
651 } 650 }
652 651
653 static int test_type_token(enum event_type type, char *token, 652 static int test_type_token(enum event_type type, char *token,
654 enum event_type expect, const char *expect_tok) 653 enum event_type expect, const char *expect_tok)
655 { 654 {
656 return __test_type_token(type, token, expect, expect_tok, true); 655 return __test_type_token(type, token, expect, expect_tok, true);
657 } 656 }
658 657
659 static int __read_expect_type(enum event_type expect, char **tok, int newline_ok) 658 static int __read_expect_type(enum event_type expect, char **tok, int newline_ok)
660 { 659 {
661 enum event_type type; 660 enum event_type type;
662 661
663 if (newline_ok) 662 if (newline_ok)
664 type = read_token(tok); 663 type = read_token(tok);
665 else 664 else
666 type = read_token_item(tok); 665 type = read_token_item(tok);
667 return test_type(type, expect); 666 return test_type(type, expect);
668 } 667 }
669 668
670 static int read_expect_type(enum event_type expect, char **tok) 669 static int read_expect_type(enum event_type expect, char **tok)
671 { 670 {
672 return __read_expect_type(expect, tok, 1); 671 return __read_expect_type(expect, tok, 1);
673 } 672 }
674 673
675 static int __read_expected(enum event_type expect, const char *str, 674 static int __read_expected(enum event_type expect, const char *str,
676 int newline_ok, bool warn) 675 int newline_ok, bool warn)
677 { 676 {
678 enum event_type type; 677 enum event_type type;
679 char *token; 678 char *token;
680 int ret; 679 int ret;
681 680
682 if (newline_ok) 681 if (newline_ok)
683 type = read_token(&token); 682 type = read_token(&token);
684 else 683 else
685 type = read_token_item(&token); 684 type = read_token_item(&token);
686 685
687 ret = __test_type_token(type, token, expect, str, warn); 686 ret = __test_type_token(type, token, expect, str, warn);
688 687
689 free_token(token); 688 free_token(token);
690 689
691 return ret; 690 return ret;
692 } 691 }
693 692
694 static int read_expected(enum event_type expect, const char *str) 693 static int read_expected(enum event_type expect, const char *str)
695 { 694 {
696 return __read_expected(expect, str, 1, true); 695 return __read_expected(expect, str, 1, true);
697 } 696 }
698 697
699 static int read_expected_item(enum event_type expect, const char *str) 698 static int read_expected_item(enum event_type expect, const char *str)
700 { 699 {
701 return __read_expected(expect, str, 0, true); 700 return __read_expected(expect, str, 0, true);
702 } 701 }
703 702
704 static char *event_read_name(void) 703 static char *event_read_name(void)
705 { 704 {
706 char *token; 705 char *token;
707 706
708 if (read_expected(EVENT_ITEM, "name") < 0) 707 if (read_expected(EVENT_ITEM, "name") < 0)
709 return NULL; 708 return NULL;
710 709
711 if (read_expected(EVENT_OP, ":") < 0) 710 if (read_expected(EVENT_OP, ":") < 0)
712 return NULL; 711 return NULL;
713 712
714 if (read_expect_type(EVENT_ITEM, &token) < 0) 713 if (read_expect_type(EVENT_ITEM, &token) < 0)
715 goto fail; 714 goto fail;
716 715
717 return token; 716 return token;
718 717
719 fail: 718 fail:
720 free_token(token); 719 free_token(token);
721 return NULL; 720 return NULL;
722 } 721 }
723 722
724 static int event_read_id(void) 723 static int event_read_id(void)
725 { 724 {
726 char *token; 725 char *token;
727 int id; 726 int id;
728 727
729 if (read_expected_item(EVENT_ITEM, "ID") < 0) 728 if (read_expected_item(EVENT_ITEM, "ID") < 0)
730 return -1; 729 return -1;
731 730
732 if (read_expected(EVENT_OP, ":") < 0) 731 if (read_expected(EVENT_OP, ":") < 0)
733 return -1; 732 return -1;
734 733
735 if (read_expect_type(EVENT_ITEM, &token) < 0) 734 if (read_expect_type(EVENT_ITEM, &token) < 0)
736 goto fail; 735 goto fail;
737 736
738 id = strtoul(token, NULL, 0); 737 id = strtoul(token, NULL, 0);
739 free_token(token); 738 free_token(token);
740 return id; 739 return id;
741 740
742 fail: 741 fail:
743 free_token(token); 742 free_token(token);
744 return -1; 743 return -1;
745 } 744 }
746 745
747 static int field_is_string(struct format_field *field) 746 static int field_is_string(struct format_field *field)
748 { 747 {
749 if ((field->flags & FIELD_IS_ARRAY) && 748 if ((field->flags & FIELD_IS_ARRAY) &&
750 (!strstr(field->type, "char") || !strstr(field->type, "u8") || 749 (!strstr(field->type, "char") || !strstr(field->type, "u8") ||
751 !strstr(field->type, "s8"))) 750 !strstr(field->type, "s8")))
752 return 1; 751 return 1;
753 752
754 return 0; 753 return 0;
755 } 754 }
756 755
757 static int field_is_dynamic(struct format_field *field) 756 static int field_is_dynamic(struct format_field *field)
758 { 757 {
759 if (!strncmp(field->type, "__data_loc", 10)) 758 if (!strncmp(field->type, "__data_loc", 10))
760 return 1; 759 return 1;
761 760
762 return 0; 761 return 0;
763 } 762 }
764 763
765 static int event_read_fields(struct event *event, struct format_field **fields) 764 static int event_read_fields(struct event *event, struct format_field **fields)
766 { 765 {
767 struct format_field *field = NULL; 766 struct format_field *field = NULL;
768 enum event_type type; 767 enum event_type type;
769 char *token; 768 char *token;
770 char *last_token; 769 char *last_token;
771 int count = 0; 770 int count = 0;
772 771
773 do { 772 do {
774 type = read_token(&token); 773 type = read_token(&token);
775 if (type == EVENT_NEWLINE) { 774 if (type == EVENT_NEWLINE) {
776 free_token(token); 775 free_token(token);
777 return count; 776 return count;
778 } 777 }
779 778
780 count++; 779 count++;
781 780
782 if (test_type_token(type, token, EVENT_ITEM, "field")) 781 if (test_type_token(type, token, EVENT_ITEM, "field"))
783 goto fail; 782 goto fail;
784 free_token(token); 783 free_token(token);
785 784
786 type = read_token(&token); 785 type = read_token(&token);
787 /* 786 /*
788 * The ftrace fields may still use the "special" name. 787 * The ftrace fields may still use the "special" name.
789 * Just ignore it. 788 * Just ignore it.
790 */ 789 */
791 if (event->flags & EVENT_FL_ISFTRACE && 790 if (event->flags & EVENT_FL_ISFTRACE &&
792 type == EVENT_ITEM && strcmp(token, "special") == 0) { 791 type == EVENT_ITEM && strcmp(token, "special") == 0) {
793 free_token(token); 792 free_token(token);
794 type = read_token(&token); 793 type = read_token(&token);
795 } 794 }
796 795
797 if (test_type_token(type, token, EVENT_OP, ":") < 0) 796 if (test_type_token(type, token, EVENT_OP, ":") < 0)
798 return -1; 797 return -1;
799 798
800 if (read_expect_type(EVENT_ITEM, &token) < 0) 799 if (read_expect_type(EVENT_ITEM, &token) < 0)
801 goto fail; 800 goto fail;
802 801
803 last_token = token; 802 last_token = token;
804 803
805 field = malloc_or_die(sizeof(*field)); 804 field = malloc_or_die(sizeof(*field));
806 memset(field, 0, sizeof(*field)); 805 memset(field, 0, sizeof(*field));
807 806
808 /* read the rest of the type */ 807 /* read the rest of the type */
809 for (;;) { 808 for (;;) {
810 type = read_token(&token); 809 type = read_token(&token);
811 if (type == EVENT_ITEM || 810 if (type == EVENT_ITEM ||
812 (type == EVENT_OP && strcmp(token, "*") == 0) || 811 (type == EVENT_OP && strcmp(token, "*") == 0) ||
813 /* 812 /*
814 * Some of the ftrace fields are broken and have 813 * Some of the ftrace fields are broken and have
815 * an illegal "." in them. 814 * an illegal "." in them.
816 */ 815 */
817 (event->flags & EVENT_FL_ISFTRACE && 816 (event->flags & EVENT_FL_ISFTRACE &&
818 type == EVENT_OP && strcmp(token, ".") == 0)) { 817 type == EVENT_OP && strcmp(token, ".") == 0)) {
819 818
820 if (strcmp(token, "*") == 0) 819 if (strcmp(token, "*") == 0)
821 field->flags |= FIELD_IS_POINTER; 820 field->flags |= FIELD_IS_POINTER;
822 821
823 if (field->type) { 822 if (field->type) {
824 field->type = realloc(field->type, 823 field->type = realloc(field->type,
825 strlen(field->type) + 824 strlen(field->type) +
826 strlen(last_token) + 2); 825 strlen(last_token) + 2);
827 strcat(field->type, " "); 826 strcat(field->type, " ");
828 strcat(field->type, last_token); 827 strcat(field->type, last_token);
829 } else 828 } else
830 field->type = last_token; 829 field->type = last_token;
831 last_token = token; 830 last_token = token;
832 continue; 831 continue;
833 } 832 }
834 833
835 break; 834 break;
836 } 835 }
837 836
838 if (!field->type) { 837 if (!field->type) {
839 die("no type found"); 838 die("no type found");
840 goto fail; 839 goto fail;
841 } 840 }
842 field->name = last_token; 841 field->name = last_token;
843 842
844 if (test_type(type, EVENT_OP)) 843 if (test_type(type, EVENT_OP))
845 goto fail; 844 goto fail;
846 845
847 if (strcmp(token, "[") == 0) { 846 if (strcmp(token, "[") == 0) {
848 enum event_type last_type = type; 847 enum event_type last_type = type;
849 char *brackets = token; 848 char *brackets = token;
850 int len; 849 int len;
851 850
852 field->flags |= FIELD_IS_ARRAY; 851 field->flags |= FIELD_IS_ARRAY;
853 852
854 type = read_token(&token); 853 type = read_token(&token);
855 while (strcmp(token, "]") != 0) { 854 while (strcmp(token, "]") != 0) {
856 if (last_type == EVENT_ITEM && 855 if (last_type == EVENT_ITEM &&
857 type == EVENT_ITEM) 856 type == EVENT_ITEM)
858 len = 2; 857 len = 2;
859 else 858 else
860 len = 1; 859 len = 1;
861 last_type = type; 860 last_type = type;
862 861
863 brackets = realloc(brackets, 862 brackets = realloc(brackets,
864 strlen(brackets) + 863 strlen(brackets) +
865 strlen(token) + len); 864 strlen(token) + len);
866 if (len == 2) 865 if (len == 2)
867 strcat(brackets, " "); 866 strcat(brackets, " ");
868 strcat(brackets, token); 867 strcat(brackets, token);
869 free_token(token); 868 free_token(token);
870 type = read_token(&token); 869 type = read_token(&token);
871 if (type == EVENT_NONE) { 870 if (type == EVENT_NONE) {
872 die("failed to find token"); 871 die("failed to find token");
873 goto fail; 872 goto fail;
874 } 873 }
875 } 874 }
876 875
877 free_token(token); 876 free_token(token);
878 877
879 brackets = realloc(brackets, strlen(brackets) + 2); 878 brackets = realloc(brackets, strlen(brackets) + 2);
880 strcat(brackets, "]"); 879 strcat(brackets, "]");
881 880
882 /* add brackets to type */ 881 /* add brackets to type */
883 882
884 type = read_token(&token); 883 type = read_token(&token);
885 /* 884 /*
886 * If the next token is not an OP, then it is of 885 * If the next token is not an OP, then it is of
887 * the format: type [] item; 886 * the format: type [] item;
888 */ 887 */
889 if (type == EVENT_ITEM) { 888 if (type == EVENT_ITEM) {
890 field->type = realloc(field->type, 889 field->type = realloc(field->type,
891 strlen(field->type) + 890 strlen(field->type) +
892 strlen(field->name) + 891 strlen(field->name) +
893 strlen(brackets) + 2); 892 strlen(brackets) + 2);
894 strcat(field->type, " "); 893 strcat(field->type, " ");
895 strcat(field->type, field->name); 894 strcat(field->type, field->name);
896 free_token(field->name); 895 free_token(field->name);
897 strcat(field->type, brackets); 896 strcat(field->type, brackets);
898 field->name = token; 897 field->name = token;
899 type = read_token(&token); 898 type = read_token(&token);
900 } else { 899 } else {
901 field->type = realloc(field->type, 900 field->type = realloc(field->type,
902 strlen(field->type) + 901 strlen(field->type) +
903 strlen(brackets) + 1); 902 strlen(brackets) + 1);
904 strcat(field->type, brackets); 903 strcat(field->type, brackets);
905 } 904 }
906 free(brackets); 905 free(brackets);
907 } 906 }
908 907
909 if (field_is_string(field)) { 908 if (field_is_string(field)) {
910 field->flags |= FIELD_IS_STRING; 909 field->flags |= FIELD_IS_STRING;
911 if (field_is_dynamic(field)) 910 if (field_is_dynamic(field))
912 field->flags |= FIELD_IS_DYNAMIC; 911 field->flags |= FIELD_IS_DYNAMIC;
913 } 912 }
914 913
915 if (test_type_token(type, token, EVENT_OP, ";")) 914 if (test_type_token(type, token, EVENT_OP, ";"))
916 goto fail; 915 goto fail;
917 free_token(token); 916 free_token(token);
918 917
919 if (read_expected(EVENT_ITEM, "offset") < 0) 918 if (read_expected(EVENT_ITEM, "offset") < 0)
920 goto fail_expect; 919 goto fail_expect;
921 920
922 if (read_expected(EVENT_OP, ":") < 0) 921 if (read_expected(EVENT_OP, ":") < 0)
923 goto fail_expect; 922 goto fail_expect;
924 923
925 if (read_expect_type(EVENT_ITEM, &token)) 924 if (read_expect_type(EVENT_ITEM, &token))
926 goto fail; 925 goto fail;
927 field->offset = strtoul(token, NULL, 0); 926 field->offset = strtoul(token, NULL, 0);
928 free_token(token); 927 free_token(token);
929 928
930 if (read_expected(EVENT_OP, ";") < 0) 929 if (read_expected(EVENT_OP, ";") < 0)
931 goto fail_expect; 930 goto fail_expect;
932 931
933 if (read_expected(EVENT_ITEM, "size") < 0) 932 if (read_expected(EVENT_ITEM, "size") < 0)
934 goto fail_expect; 933 goto fail_expect;
935 934
936 if (read_expected(EVENT_OP, ":") < 0) 935 if (read_expected(EVENT_OP, ":") < 0)
937 goto fail_expect; 936 goto fail_expect;
938 937
939 if (read_expect_type(EVENT_ITEM, &token)) 938 if (read_expect_type(EVENT_ITEM, &token))
940 goto fail; 939 goto fail;
941 field->size = strtoul(token, NULL, 0); 940 field->size = strtoul(token, NULL, 0);
942 free_token(token); 941 free_token(token);
943 942
944 if (read_expected(EVENT_OP, ";") < 0) 943 if (read_expected(EVENT_OP, ";") < 0)
945 goto fail_expect; 944 goto fail_expect;
946 945
947 type = read_token(&token); 946 type = read_token(&token);
948 if (type != EVENT_NEWLINE) { 947 if (type != EVENT_NEWLINE) {
949 /* newer versions of the kernel have a "signed" type */ 948 /* newer versions of the kernel have a "signed" type */
950 if (test_type_token(type, token, EVENT_ITEM, "signed")) 949 if (test_type_token(type, token, EVENT_ITEM, "signed"))
951 goto fail; 950 goto fail;
952 951
953 free_token(token); 952 free_token(token);
954 953
955 if (read_expected(EVENT_OP, ":") < 0) 954 if (read_expected(EVENT_OP, ":") < 0)
956 goto fail_expect; 955 goto fail_expect;
957 956
958 if (read_expect_type(EVENT_ITEM, &token)) 957 if (read_expect_type(EVENT_ITEM, &token))
959 goto fail; 958 goto fail;
960 959
961 if (strtoul(token, NULL, 0)) 960 if (strtoul(token, NULL, 0))
962 field->flags |= FIELD_IS_SIGNED; 961 field->flags |= FIELD_IS_SIGNED;
963 962
964 free_token(token); 963 free_token(token);
965 if (read_expected(EVENT_OP, ";") < 0) 964 if (read_expected(EVENT_OP, ";") < 0)
966 goto fail_expect; 965 goto fail_expect;
967 966
968 if (read_expect_type(EVENT_NEWLINE, &token)) 967 if (read_expect_type(EVENT_NEWLINE, &token))
969 goto fail; 968 goto fail;
970 } 969 }
971 970
972 free_token(token); 971 free_token(token);
973 972
974 *fields = field; 973 *fields = field;
975 fields = &field->next; 974 fields = &field->next;
976 975
977 } while (1); 976 } while (1);
978 977
979 return 0; 978 return 0;
980 979
981 fail: 980 fail:
982 free_token(token); 981 free_token(token);
983 fail_expect: 982 fail_expect:
984 if (field) 983 if (field)
985 free(field); 984 free(field);
986 return -1; 985 return -1;
987 } 986 }
988 987
989 static int event_read_format(struct event *event) 988 static int event_read_format(struct event *event)
990 { 989 {
991 char *token; 990 char *token;
992 int ret; 991 int ret;
993 992
994 if (read_expected_item(EVENT_ITEM, "format") < 0) 993 if (read_expected_item(EVENT_ITEM, "format") < 0)
995 return -1; 994 return -1;
996 995
997 if (read_expected(EVENT_OP, ":") < 0) 996 if (read_expected(EVENT_OP, ":") < 0)
998 return -1; 997 return -1;
999 998
1000 if (read_expect_type(EVENT_NEWLINE, &token)) 999 if (read_expect_type(EVENT_NEWLINE, &token))
1001 goto fail; 1000 goto fail;
1002 free_token(token); 1001 free_token(token);
1003 1002
1004 ret = event_read_fields(event, &event->format.common_fields); 1003 ret = event_read_fields(event, &event->format.common_fields);
1005 if (ret < 0) 1004 if (ret < 0)
1006 return ret; 1005 return ret;
1007 event->format.nr_common = ret; 1006 event->format.nr_common = ret;
1008 1007
1009 ret = event_read_fields(event, &event->format.fields); 1008 ret = event_read_fields(event, &event->format.fields);
1010 if (ret < 0) 1009 if (ret < 0)
1011 return ret; 1010 return ret;
1012 event->format.nr_fields = ret; 1011 event->format.nr_fields = ret;
1013 1012
1014 return 0; 1013 return 0;
1015 1014
1016 fail: 1015 fail:
1017 free_token(token); 1016 free_token(token);
1018 return -1; 1017 return -1;
1019 } 1018 }
1020 1019
1021 enum event_type 1020 enum event_type
1022 process_arg_token(struct event *event, struct print_arg *arg, 1021 process_arg_token(struct event *event, struct print_arg *arg,
1023 char **tok, enum event_type type); 1022 char **tok, enum event_type type);
1024 1023
1025 static enum event_type 1024 static enum event_type
1026 process_arg(struct event *event, struct print_arg *arg, char **tok) 1025 process_arg(struct event *event, struct print_arg *arg, char **tok)
1027 { 1026 {
1028 enum event_type type; 1027 enum event_type type;
1029 char *token; 1028 char *token;
1030 1029
1031 type = read_token(&token); 1030 type = read_token(&token);
1032 *tok = token; 1031 *tok = token;
1033 1032
1034 return process_arg_token(event, arg, tok, type); 1033 return process_arg_token(event, arg, tok, type);
1035 } 1034 }
1036 1035
1037 static enum event_type 1036 static enum event_type
1038 process_cond(struct event *event, struct print_arg *top, char **tok) 1037 process_cond(struct event *event, struct print_arg *top, char **tok)
1039 { 1038 {
1040 struct print_arg *arg, *left, *right; 1039 struct print_arg *arg, *left, *right;
1041 enum event_type type; 1040 enum event_type type;
1042 char *token = NULL; 1041 char *token = NULL;
1043 1042
1044 arg = malloc_or_die(sizeof(*arg)); 1043 arg = malloc_or_die(sizeof(*arg));
1045 memset(arg, 0, sizeof(*arg)); 1044 memset(arg, 0, sizeof(*arg));
1046 1045
1047 left = malloc_or_die(sizeof(*left)); 1046 left = malloc_or_die(sizeof(*left));
1048 1047
1049 right = malloc_or_die(sizeof(*right)); 1048 right = malloc_or_die(sizeof(*right));
1050 1049
1051 arg->type = PRINT_OP; 1050 arg->type = PRINT_OP;
1052 arg->op.left = left; 1051 arg->op.left = left;
1053 arg->op.right = right; 1052 arg->op.right = right;
1054 1053
1055 *tok = NULL; 1054 *tok = NULL;
1056 type = process_arg(event, left, &token); 1055 type = process_arg(event, left, &token);
1057 if (test_type_token(type, token, EVENT_OP, ":")) 1056 if (test_type_token(type, token, EVENT_OP, ":"))
1058 goto out_free; 1057 goto out_free;
1059 1058
1060 arg->op.op = token; 1059 arg->op.op = token;
1061 1060
1062 type = process_arg(event, right, &token); 1061 type = process_arg(event, right, &token);
1063 1062
1064 top->op.right = arg; 1063 top->op.right = arg;
1065 1064
1066 *tok = token; 1065 *tok = token;
1067 return type; 1066 return type;
1068 1067
1069 out_free: 1068 out_free:
1070 free_token(*tok); 1069 free_token(*tok);
1071 free(right); 1070 free(right);
1072 free(left); 1071 free(left);
1073 free_arg(arg); 1072 free_arg(arg);
1074 return EVENT_ERROR; 1073 return EVENT_ERROR;
1075 } 1074 }
1076 1075
1077 static enum event_type 1076 static enum event_type
1078 process_array(struct event *event, struct print_arg *top, char **tok) 1077 process_array(struct event *event, struct print_arg *top, char **tok)
1079 { 1078 {
1080 struct print_arg *arg; 1079 struct print_arg *arg;
1081 enum event_type type; 1080 enum event_type type;
1082 char *token = NULL; 1081 char *token = NULL;
1083 1082
1084 arg = malloc_or_die(sizeof(*arg)); 1083 arg = malloc_or_die(sizeof(*arg));
1085 memset(arg, 0, sizeof(*arg)); 1084 memset(arg, 0, sizeof(*arg));
1086 1085
1087 *tok = NULL; 1086 *tok = NULL;
1088 type = process_arg(event, arg, &token); 1087 type = process_arg(event, arg, &token);
1089 if (test_type_token(type, token, EVENT_OP, "]")) 1088 if (test_type_token(type, token, EVENT_OP, "]"))
1090 goto out_free; 1089 goto out_free;
1091 1090
1092 top->op.right = arg; 1091 top->op.right = arg;
1093 1092
1094 free_token(token); 1093 free_token(token);
1095 type = read_token_item(&token); 1094 type = read_token_item(&token);
1096 *tok = token; 1095 *tok = token;
1097 1096
1098 return type; 1097 return type;
1099 1098
1100 out_free: 1099 out_free:
1101 free_token(*tok); 1100 free_token(*tok);
1102 free_arg(arg); 1101 free_arg(arg);
1103 return EVENT_ERROR; 1102 return EVENT_ERROR;
1104 } 1103 }
1105 1104
1106 static int get_op_prio(char *op) 1105 static int get_op_prio(char *op)
1107 { 1106 {
1108 if (!op[1]) { 1107 if (!op[1]) {
1109 switch (op[0]) { 1108 switch (op[0]) {
1110 case '*': 1109 case '*':
1111 case '/': 1110 case '/':
1112 case '%': 1111 case '%':
1113 return 6; 1112 return 6;
1114 case '+': 1113 case '+':
1115 case '-': 1114 case '-':
1116 return 7; 1115 return 7;
1117 /* '>>' and '<<' are 8 */ 1116 /* '>>' and '<<' are 8 */
1118 case '<': 1117 case '<':
1119 case '>': 1118 case '>':
1120 return 9; 1119 return 9;
1121 /* '==' and '!=' are 10 */ 1120 /* '==' and '!=' are 10 */
1122 case '&': 1121 case '&':
1123 return 11; 1122 return 11;
1124 case '^': 1123 case '^':
1125 return 12; 1124 return 12;
1126 case '|': 1125 case '|':
1127 return 13; 1126 return 13;
1128 case '?': 1127 case '?':
1129 return 16; 1128 return 16;
1130 default: 1129 default:
1131 die("unknown op '%c'", op[0]); 1130 die("unknown op '%c'", op[0]);
1132 return -1; 1131 return -1;
1133 } 1132 }
1134 } else { 1133 } else {
1135 if (strcmp(op, "++") == 0 || 1134 if (strcmp(op, "++") == 0 ||
1136 strcmp(op, "--") == 0) { 1135 strcmp(op, "--") == 0) {
1137 return 3; 1136 return 3;
1138 } else if (strcmp(op, ">>") == 0 || 1137 } else if (strcmp(op, ">>") == 0 ||
1139 strcmp(op, "<<") == 0) { 1138 strcmp(op, "<<") == 0) {
1140 return 8; 1139 return 8;
1141 } else if (strcmp(op, ">=") == 0 || 1140 } else if (strcmp(op, ">=") == 0 ||
1142 strcmp(op, "<=") == 0) { 1141 strcmp(op, "<=") == 0) {
1143 return 9; 1142 return 9;
1144 } else if (strcmp(op, "==") == 0 || 1143 } else if (strcmp(op, "==") == 0 ||
1145 strcmp(op, "!=") == 0) { 1144 strcmp(op, "!=") == 0) {
1146 return 10; 1145 return 10;
1147 } else if (strcmp(op, "&&") == 0) { 1146 } else if (strcmp(op, "&&") == 0) {
1148 return 14; 1147 return 14;
1149 } else if (strcmp(op, "||") == 0) { 1148 } else if (strcmp(op, "||") == 0) {
1150 return 15; 1149 return 15;
1151 } else { 1150 } else {
1152 die("unknown op '%s'", op); 1151 die("unknown op '%s'", op);
1153 return -1; 1152 return -1;
1154 } 1153 }
1155 } 1154 }
1156 } 1155 }
1157 1156
1158 static void set_op_prio(struct print_arg *arg) 1157 static void set_op_prio(struct print_arg *arg)
1159 { 1158 {
1160 1159
1161 /* single ops are the greatest */ 1160 /* single ops are the greatest */
1162 if (!arg->op.left || arg->op.left->type == PRINT_NULL) { 1161 if (!arg->op.left || arg->op.left->type == PRINT_NULL) {
1163 arg->op.prio = 0; 1162 arg->op.prio = 0;
1164 return; 1163 return;
1165 } 1164 }
1166 1165
1167 arg->op.prio = get_op_prio(arg->op.op); 1166 arg->op.prio = get_op_prio(arg->op.op);
1168 } 1167 }
1169 1168
1170 static enum event_type 1169 static enum event_type
1171 process_op(struct event *event, struct print_arg *arg, char **tok) 1170 process_op(struct event *event, struct print_arg *arg, char **tok)
1172 { 1171 {
1173 struct print_arg *left, *right = NULL; 1172 struct print_arg *left, *right = NULL;
1174 enum event_type type; 1173 enum event_type type;
1175 char *token; 1174 char *token;
1176 1175
1177 /* the op is passed in via tok */ 1176 /* the op is passed in via tok */
1178 token = *tok; 1177 token = *tok;
1179 1178
1180 if (arg->type == PRINT_OP && !arg->op.left) { 1179 if (arg->type == PRINT_OP && !arg->op.left) {
1181 /* handle single op */ 1180 /* handle single op */
1182 if (token[1]) { 1181 if (token[1]) {
1183 die("bad op token %s", token); 1182 die("bad op token %s", token);
1184 return EVENT_ERROR; 1183 return EVENT_ERROR;
1185 } 1184 }
1186 switch (token[0]) { 1185 switch (token[0]) {
1187 case '!': 1186 case '!':
1188 case '+': 1187 case '+':
1189 case '-': 1188 case '-':
1190 break; 1189 break;
1191 default: 1190 default:
1192 die("bad op token %s", token); 1191 die("bad op token %s", token);
1193 return EVENT_ERROR; 1192 return EVENT_ERROR;
1194 } 1193 }
1195 1194
1196 /* make an empty left */ 1195 /* make an empty left */
1197 left = malloc_or_die(sizeof(*left)); 1196 left = malloc_or_die(sizeof(*left));
1198 left->type = PRINT_NULL; 1197 left->type = PRINT_NULL;
1199 arg->op.left = left; 1198 arg->op.left = left;
1200 1199
1201 right = malloc_or_die(sizeof(*right)); 1200 right = malloc_or_die(sizeof(*right));
1202 arg->op.right = right; 1201 arg->op.right = right;
1203 1202
1204 type = process_arg(event, right, tok); 1203 type = process_arg(event, right, tok);
1205 1204
1206 } else if (strcmp(token, "?") == 0) { 1205 } else if (strcmp(token, "?") == 0) {
1207 1206
1208 left = malloc_or_die(sizeof(*left)); 1207 left = malloc_or_die(sizeof(*left));
1209 /* copy the top arg to the left */ 1208 /* copy the top arg to the left */
1210 *left = *arg; 1209 *left = *arg;
1211 1210
1212 arg->type = PRINT_OP; 1211 arg->type = PRINT_OP;
1213 arg->op.op = token; 1212 arg->op.op = token;
1214 arg->op.left = left; 1213 arg->op.left = left;
1215 arg->op.prio = 0; 1214 arg->op.prio = 0;
1216 1215
1217 type = process_cond(event, arg, tok); 1216 type = process_cond(event, arg, tok);
1218 1217
1219 } else if (strcmp(token, ">>") == 0 || 1218 } else if (strcmp(token, ">>") == 0 ||
1220 strcmp(token, "<<") == 0 || 1219 strcmp(token, "<<") == 0 ||
1221 strcmp(token, "&") == 0 || 1220 strcmp(token, "&") == 0 ||
1222 strcmp(token, "|") == 0 || 1221 strcmp(token, "|") == 0 ||
1223 strcmp(token, "&&") == 0 || 1222 strcmp(token, "&&") == 0 ||
1224 strcmp(token, "||") == 0 || 1223 strcmp(token, "||") == 0 ||
1225 strcmp(token, "-") == 0 || 1224 strcmp(token, "-") == 0 ||
1226 strcmp(token, "+") == 0 || 1225 strcmp(token, "+") == 0 ||
1227 strcmp(token, "*") == 0 || 1226 strcmp(token, "*") == 0 ||
1228 strcmp(token, "^") == 0 || 1227 strcmp(token, "^") == 0 ||
1229 strcmp(token, "/") == 0 || 1228 strcmp(token, "/") == 0 ||
1230 strcmp(token, "<") == 0 || 1229 strcmp(token, "<") == 0 ||
1231 strcmp(token, ">") == 0 || 1230 strcmp(token, ">") == 0 ||
1232 strcmp(token, "==") == 0 || 1231 strcmp(token, "==") == 0 ||
1233 strcmp(token, "!=") == 0) { 1232 strcmp(token, "!=") == 0) {
1234 1233
1235 left = malloc_or_die(sizeof(*left)); 1234 left = malloc_or_die(sizeof(*left));
1236 1235
1237 /* copy the top arg to the left */ 1236 /* copy the top arg to the left */
1238 *left = *arg; 1237 *left = *arg;
1239 1238
1240 arg->type = PRINT_OP; 1239 arg->type = PRINT_OP;
1241 arg->op.op = token; 1240 arg->op.op = token;
1242 arg->op.left = left; 1241 arg->op.left = left;
1243 1242
1244 set_op_prio(arg); 1243 set_op_prio(arg);
1245 1244
1246 right = malloc_or_die(sizeof(*right)); 1245 right = malloc_or_die(sizeof(*right));
1247 1246
1248 type = read_token_item(&token); 1247 type = read_token_item(&token);
1249 *tok = token; 1248 *tok = token;
1250 1249
1251 /* could just be a type pointer */ 1250 /* could just be a type pointer */
1252 if ((strcmp(arg->op.op, "*") == 0) && 1251 if ((strcmp(arg->op.op, "*") == 0) &&
1253 type == EVENT_DELIM && (strcmp(token, ")") == 0)) { 1252 type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
1254 if (left->type != PRINT_ATOM) 1253 if (left->type != PRINT_ATOM)
1255 die("bad pointer type"); 1254 die("bad pointer type");
1256 left->atom.atom = realloc(left->atom.atom, 1255 left->atom.atom = realloc(left->atom.atom,
1257 sizeof(left->atom.atom) + 3); 1256 sizeof(left->atom.atom) + 3);
1258 strcat(left->atom.atom, " *"); 1257 strcat(left->atom.atom, " *");
1259 *arg = *left; 1258 *arg = *left;
1260 free(arg); 1259 free(arg);
1261 1260
1262 return type; 1261 return type;
1263 } 1262 }
1264 1263
1265 type = process_arg_token(event, right, tok, type); 1264 type = process_arg_token(event, right, tok, type);
1266 1265
1267 arg->op.right = right; 1266 arg->op.right = right;
1268 1267
1269 } else if (strcmp(token, "[") == 0) { 1268 } else if (strcmp(token, "[") == 0) {
1270 1269
1271 left = malloc_or_die(sizeof(*left)); 1270 left = malloc_or_die(sizeof(*left));
1272 *left = *arg; 1271 *left = *arg;
1273 1272
1274 arg->type = PRINT_OP; 1273 arg->type = PRINT_OP;
1275 arg->op.op = token; 1274 arg->op.op = token;
1276 arg->op.left = left; 1275 arg->op.left = left;
1277 1276
1278 arg->op.prio = 0; 1277 arg->op.prio = 0;
1279 type = process_array(event, arg, tok); 1278 type = process_array(event, arg, tok);
1280 1279
1281 } else { 1280 } else {
1282 warning("unknown op '%s'", token); 1281 warning("unknown op '%s'", token);
1283 event->flags |= EVENT_FL_FAILED; 1282 event->flags |= EVENT_FL_FAILED;
1284 /* the arg is now the left side */ 1283 /* the arg is now the left side */
1285 return EVENT_NONE; 1284 return EVENT_NONE;
1286 } 1285 }
1287 1286
1288 if (type == EVENT_OP) { 1287 if (type == EVENT_OP) {
1289 int prio; 1288 int prio;
1290 1289
1291 /* higher prios need to be closer to the root */ 1290 /* higher prios need to be closer to the root */
1292 prio = get_op_prio(*tok); 1291 prio = get_op_prio(*tok);
1293 1292
1294 if (prio > arg->op.prio) 1293 if (prio > arg->op.prio)
1295 return process_op(event, arg, tok); 1294 return process_op(event, arg, tok);
1296 1295
1297 return process_op(event, right, tok); 1296 return process_op(event, right, tok);
1298 } 1297 }
1299 1298
1300 return type; 1299 return type;
1301 } 1300 }
1302 1301
1303 static enum event_type 1302 static enum event_type
1304 process_entry(struct event *event __unused, struct print_arg *arg, 1303 process_entry(struct event *event __unused, struct print_arg *arg,
1305 char **tok) 1304 char **tok)
1306 { 1305 {
1307 enum event_type type; 1306 enum event_type type;
1308 char *field; 1307 char *field;
1309 char *token; 1308 char *token;
1310 1309
1311 if (read_expected(EVENT_OP, "->") < 0) 1310 if (read_expected(EVENT_OP, "->") < 0)
1312 return EVENT_ERROR; 1311 return EVENT_ERROR;
1313 1312
1314 if (read_expect_type(EVENT_ITEM, &token) < 0) 1313 if (read_expect_type(EVENT_ITEM, &token) < 0)
1315 goto fail; 1314 goto fail;
1316 field = token; 1315 field = token;
1317 1316
1318 arg->type = PRINT_FIELD; 1317 arg->type = PRINT_FIELD;
1319 arg->field.name = field; 1318 arg->field.name = field;
1320 1319
1321 if (is_flag_field) { 1320 if (is_flag_field) {
1322 arg->field.field = find_any_field(event, arg->field.name); 1321 arg->field.field = find_any_field(event, arg->field.name);
1323 arg->field.field->flags |= FIELD_IS_FLAG; 1322 arg->field.field->flags |= FIELD_IS_FLAG;
1324 is_flag_field = 0; 1323 is_flag_field = 0;
1325 } else if (is_symbolic_field) { 1324 } else if (is_symbolic_field) {
1326 arg->field.field = find_any_field(event, arg->field.name); 1325 arg->field.field = find_any_field(event, arg->field.name);
1327 arg->field.field->flags |= FIELD_IS_SYMBOLIC; 1326 arg->field.field->flags |= FIELD_IS_SYMBOLIC;
1328 is_symbolic_field = 0; 1327 is_symbolic_field = 0;
1329 } 1328 }
1330 1329
1331 type = read_token(&token); 1330 type = read_token(&token);
1332 *tok = token; 1331 *tok = token;
1333 1332
1334 return type; 1333 return type;
1335 1334
1336 fail: 1335 fail:
1337 free_token(token); 1336 free_token(token);
1338 return EVENT_ERROR; 1337 return EVENT_ERROR;
1339 } 1338 }
1340 1339
1341 static char *arg_eval (struct print_arg *arg); 1340 static char *arg_eval (struct print_arg *arg);
1342 1341
1343 static long long arg_num_eval(struct print_arg *arg) 1342 static long long arg_num_eval(struct print_arg *arg)
1344 { 1343 {
1345 long long left, right; 1344 long long left, right;
1346 long long val = 0; 1345 long long val = 0;
1347 1346
1348 switch (arg->type) { 1347 switch (arg->type) {
1349 case PRINT_ATOM: 1348 case PRINT_ATOM:
1350 val = strtoll(arg->atom.atom, NULL, 0); 1349 val = strtoll(arg->atom.atom, NULL, 0);
1351 break; 1350 break;
1352 case PRINT_TYPE: 1351 case PRINT_TYPE:
1353 val = arg_num_eval(arg->typecast.item); 1352 val = arg_num_eval(arg->typecast.item);
1354 break; 1353 break;
1355 case PRINT_OP: 1354 case PRINT_OP:
1356 switch (arg->op.op[0]) { 1355 switch (arg->op.op[0]) {
1357 case '|': 1356 case '|':
1358 left = arg_num_eval(arg->op.left); 1357 left = arg_num_eval(arg->op.left);
1359 right = arg_num_eval(arg->op.right); 1358 right = arg_num_eval(arg->op.right);
1360 if (arg->op.op[1]) 1359 if (arg->op.op[1])
1361 val = left || right; 1360 val = left || right;
1362 else 1361 else
1363 val = left | right; 1362 val = left | right;
1364 break; 1363 break;
1365 case '&': 1364 case '&':
1366 left = arg_num_eval(arg->op.left); 1365 left = arg_num_eval(arg->op.left);
1367 right = arg_num_eval(arg->op.right); 1366 right = arg_num_eval(arg->op.right);
1368 if (arg->op.op[1]) 1367 if (arg->op.op[1])
1369 val = left && right; 1368 val = left && right;
1370 else 1369 else
1371 val = left & right; 1370 val = left & right;
1372 break; 1371 break;
1373 case '<': 1372 case '<':
1374 left = arg_num_eval(arg->op.left); 1373 left = arg_num_eval(arg->op.left);
1375 right = arg_num_eval(arg->op.right); 1374 right = arg_num_eval(arg->op.right);
1376 switch (arg->op.op[1]) { 1375 switch (arg->op.op[1]) {
1377 case 0: 1376 case 0:
1378 val = left < right; 1377 val = left < right;
1379 break; 1378 break;
1380 case '<': 1379 case '<':
1381 val = left << right; 1380 val = left << right;
1382 break; 1381 break;
1383 case '=': 1382 case '=':
1384 val = left <= right; 1383 val = left <= right;
1385 break; 1384 break;
1386 default: 1385 default:
1387 die("unknown op '%s'", arg->op.op); 1386 die("unknown op '%s'", arg->op.op);
1388 } 1387 }
1389 break; 1388 break;
1390 case '>': 1389 case '>':
1391 left = arg_num_eval(arg->op.left); 1390 left = arg_num_eval(arg->op.left);
1392 right = arg_num_eval(arg->op.right); 1391 right = arg_num_eval(arg->op.right);
1393 switch (arg->op.op[1]) { 1392 switch (arg->op.op[1]) {
1394 case 0: 1393 case 0:
1395 val = left > right; 1394 val = left > right;
1396 break; 1395 break;
1397 case '>': 1396 case '>':
1398 val = left >> right; 1397 val = left >> right;
1399 break; 1398 break;
1400 case '=': 1399 case '=':
1401 val = left >= right; 1400 val = left >= right;
1402 break; 1401 break;
1403 default: 1402 default:
1404 die("unknown op '%s'", arg->op.op); 1403 die("unknown op '%s'", arg->op.op);
1405 } 1404 }
1406 break; 1405 break;
1407 case '=': 1406 case '=':
1408 left = arg_num_eval(arg->op.left); 1407 left = arg_num_eval(arg->op.left);
1409 right = arg_num_eval(arg->op.right); 1408 right = arg_num_eval(arg->op.right);
1410 1409
1411 if (arg->op.op[1] != '=') 1410 if (arg->op.op[1] != '=')
1412 die("unknown op '%s'", arg->op.op); 1411 die("unknown op '%s'", arg->op.op);
1413 1412
1414 val = left == right; 1413 val = left == right;
1415 break; 1414 break;
1416 case '!': 1415 case '!':
1417 left = arg_num_eval(arg->op.left); 1416 left = arg_num_eval(arg->op.left);
1418 right = arg_num_eval(arg->op.right); 1417 right = arg_num_eval(arg->op.right);
1419 1418
1420 switch (arg->op.op[1]) { 1419 switch (arg->op.op[1]) {
1421 case '=': 1420 case '=':
1422 val = left != right; 1421 val = left != right;
1423 break; 1422 break;
1424 default: 1423 default:
1425 die("unknown op '%s'", arg->op.op); 1424 die("unknown op '%s'", arg->op.op);
1426 } 1425 }
1427 break; 1426 break;
1428 default: 1427 default:
1429 die("unknown op '%s'", arg->op.op); 1428 die("unknown op '%s'", arg->op.op);
1430 } 1429 }
1431 break; 1430 break;
1432 1431
1433 case PRINT_NULL: 1432 case PRINT_NULL:
1434 case PRINT_FIELD ... PRINT_SYMBOL: 1433 case PRINT_FIELD ... PRINT_SYMBOL:
1435 case PRINT_STRING: 1434 case PRINT_STRING:
1436 default: 1435 default:
1437 die("invalid eval type %d", arg->type); 1436 die("invalid eval type %d", arg->type);
1438 1437
1439 } 1438 }
1440 return val; 1439 return val;
1441 } 1440 }
1442 1441
1443 static char *arg_eval (struct print_arg *arg) 1442 static char *arg_eval (struct print_arg *arg)
1444 { 1443 {
1445 long long val; 1444 long long val;
1446 static char buf[20]; 1445 static char buf[20];
1447 1446
1448 switch (arg->type) { 1447 switch (arg->type) {
1449 case PRINT_ATOM: 1448 case PRINT_ATOM:
1450 return arg->atom.atom; 1449 return arg->atom.atom;
1451 case PRINT_TYPE: 1450 case PRINT_TYPE:
1452 return arg_eval(arg->typecast.item); 1451 return arg_eval(arg->typecast.item);
1453 case PRINT_OP: 1452 case PRINT_OP:
1454 val = arg_num_eval(arg); 1453 val = arg_num_eval(arg);
1455 sprintf(buf, "%lld", val); 1454 sprintf(buf, "%lld", val);
1456 return buf; 1455 return buf;
1457 1456
1458 case PRINT_NULL: 1457 case PRINT_NULL:
1459 case PRINT_FIELD ... PRINT_SYMBOL: 1458 case PRINT_FIELD ... PRINT_SYMBOL:
1460 case PRINT_STRING: 1459 case PRINT_STRING:
1461 default: 1460 default:
1462 die("invalid eval type %d", arg->type); 1461 die("invalid eval type %d", arg->type);
1463 break; 1462 break;
1464 } 1463 }
1465 1464
1466 return NULL; 1465 return NULL;
1467 } 1466 }
1468 1467
1469 static enum event_type 1468 static enum event_type
1470 process_fields(struct event *event, struct print_flag_sym **list, char **tok) 1469 process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1471 { 1470 {
1472 enum event_type type; 1471 enum event_type type;
1473 struct print_arg *arg = NULL; 1472 struct print_arg *arg = NULL;
1474 struct print_flag_sym *field; 1473 struct print_flag_sym *field;
1475 char *token = NULL; 1474 char *token = NULL;
1476 char *value; 1475 char *value;
1477 1476
1478 do { 1477 do {
1479 free_token(token); 1478 free_token(token);
1480 type = read_token_item(&token); 1479 type = read_token_item(&token);
1481 if (test_type_token(type, token, EVENT_OP, "{")) 1480 if (test_type_token(type, token, EVENT_OP, "{"))
1482 break; 1481 break;
1483 1482
1484 arg = malloc_or_die(sizeof(*arg)); 1483 arg = malloc_or_die(sizeof(*arg));
1485 1484
1486 free_token(token); 1485 free_token(token);
1487 type = process_arg(event, arg, &token); 1486 type = process_arg(event, arg, &token);
1488 if (test_type_token(type, token, EVENT_DELIM, ",")) 1487 if (test_type_token(type, token, EVENT_DELIM, ","))
1489 goto out_free; 1488 goto out_free;
1490 1489
1491 field = malloc_or_die(sizeof(*field)); 1490 field = malloc_or_die(sizeof(*field));
1492 memset(field, 0, sizeof(*field)); 1491 memset(field, 0, sizeof(*field));
1493 1492
1494 value = arg_eval(arg); 1493 value = arg_eval(arg);
1495 field->value = strdup(value); 1494 field->value = strdup(value);
1496 1495
1497 free_token(token); 1496 free_token(token);
1498 type = process_arg(event, arg, &token); 1497 type = process_arg(event, arg, &token);
1499 if (test_type_token(type, token, EVENT_OP, "}")) 1498 if (test_type_token(type, token, EVENT_OP, "}"))
1500 goto out_free; 1499 goto out_free;
1501 1500
1502 value = arg_eval(arg); 1501 value = arg_eval(arg);
1503 field->str = strdup(value); 1502 field->str = strdup(value);
1504 free_arg(arg); 1503 free_arg(arg);
1505 arg = NULL; 1504 arg = NULL;
1506 1505
1507 *list = field; 1506 *list = field;
1508 list = &field->next; 1507 list = &field->next;
1509 1508
1510 free_token(token); 1509 free_token(token);
1511 type = read_token_item(&token); 1510 type = read_token_item(&token);
1512 } while (type == EVENT_DELIM && strcmp(token, ",") == 0); 1511 } while (type == EVENT_DELIM && strcmp(token, ",") == 0);
1513 1512
1514 *tok = token; 1513 *tok = token;
1515 return type; 1514 return type;
1516 1515
1517 out_free: 1516 out_free:
1518 free_arg(arg); 1517 free_arg(arg);
1519 free_token(token); 1518 free_token(token);
1520 1519
1521 return EVENT_ERROR; 1520 return EVENT_ERROR;
1522 } 1521 }
1523 1522
1524 static enum event_type 1523 static enum event_type
1525 process_flags(struct event *event, struct print_arg *arg, char **tok) 1524 process_flags(struct event *event, struct print_arg *arg, char **tok)
1526 { 1525 {
1527 struct print_arg *field; 1526 struct print_arg *field;
1528 enum event_type type; 1527 enum event_type type;
1529 char *token; 1528 char *token;
1530 1529
1531 memset(arg, 0, sizeof(*arg)); 1530 memset(arg, 0, sizeof(*arg));
1532 arg->type = PRINT_FLAGS; 1531 arg->type = PRINT_FLAGS;
1533 1532
1534 if (read_expected_item(EVENT_DELIM, "(") < 0) 1533 if (read_expected_item(EVENT_DELIM, "(") < 0)
1535 return EVENT_ERROR; 1534 return EVENT_ERROR;
1536 1535
1537 field = malloc_or_die(sizeof(*field)); 1536 field = malloc_or_die(sizeof(*field));
1538 1537
1539 type = process_arg(event, field, &token); 1538 type = process_arg(event, field, &token);
1540 while (type == EVENT_OP) 1539 while (type == EVENT_OP)
1541 type = process_op(event, field, &token); 1540 type = process_op(event, field, &token);
1542 if (test_type_token(type, token, EVENT_DELIM, ",")) 1541 if (test_type_token(type, token, EVENT_DELIM, ","))
1543 goto out_free; 1542 goto out_free;
1544 1543
1545 arg->flags.field = field; 1544 arg->flags.field = field;
1546 1545
1547 type = read_token_item(&token); 1546 type = read_token_item(&token);
1548 if (event_item_type(type)) { 1547 if (event_item_type(type)) {
1549 arg->flags.delim = token; 1548 arg->flags.delim = token;
1550 type = read_token_item(&token); 1549 type = read_token_item(&token);
1551 } 1550 }
1552 1551
1553 if (test_type_token(type, token, EVENT_DELIM, ",")) 1552 if (test_type_token(type, token, EVENT_DELIM, ","))
1554 goto out_free; 1553 goto out_free;
1555 1554
1556 type = process_fields(event, &arg->flags.flags, &token); 1555 type = process_fields(event, &arg->flags.flags, &token);
1557 if (test_type_token(type, token, EVENT_DELIM, ")")) 1556 if (test_type_token(type, token, EVENT_DELIM, ")"))
1558 goto out_free; 1557 goto out_free;
1559 1558
1560 free_token(token); 1559 free_token(token);
1561 type = read_token_item(tok); 1560 type = read_token_item(tok);
1562 return type; 1561 return type;
1563 1562
1564 out_free: 1563 out_free:
1565 free_token(token); 1564 free_token(token);
1566 return EVENT_ERROR; 1565 return EVENT_ERROR;
1567 } 1566 }
1568 1567
1569 static enum event_type 1568 static enum event_type
1570 process_symbols(struct event *event, struct print_arg *arg, char **tok) 1569 process_symbols(struct event *event, struct print_arg *arg, char **tok)
1571 { 1570 {
1572 struct print_arg *field; 1571 struct print_arg *field;
1573 enum event_type type; 1572 enum event_type type;
1574 char *token; 1573 char *token;
1575 1574
1576 memset(arg, 0, sizeof(*arg)); 1575 memset(arg, 0, sizeof(*arg));
1577 arg->type = PRINT_SYMBOL; 1576 arg->type = PRINT_SYMBOL;
1578 1577
1579 if (read_expected_item(EVENT_DELIM, "(") < 0) 1578 if (read_expected_item(EVENT_DELIM, "(") < 0)
1580 return EVENT_ERROR; 1579 return EVENT_ERROR;
1581 1580
1582 field = malloc_or_die(sizeof(*field)); 1581 field = malloc_or_die(sizeof(*field));
1583 1582
1584 type = process_arg(event, field, &token); 1583 type = process_arg(event, field, &token);
1585 if (test_type_token(type, token, EVENT_DELIM, ",")) 1584 if (test_type_token(type, token, EVENT_DELIM, ","))
1586 goto out_free; 1585 goto out_free;
1587 1586
1588 arg->symbol.field = field; 1587 arg->symbol.field = field;
1589 1588
1590 type = process_fields(event, &arg->symbol.symbols, &token); 1589 type = process_fields(event, &arg->symbol.symbols, &token);
1591 if (test_type_token(type, token, EVENT_DELIM, ")")) 1590 if (test_type_token(type, token, EVENT_DELIM, ")"))
1592 goto out_free; 1591 goto out_free;
1593 1592
1594 free_token(token); 1593 free_token(token);
1595 type = read_token_item(tok); 1594 type = read_token_item(tok);
1596 return type; 1595 return type;
1597 1596
1598 out_free: 1597 out_free:
1599 free_token(token); 1598 free_token(token);
1600 return EVENT_ERROR; 1599 return EVENT_ERROR;
1601 } 1600 }
1602 1601
1603 static enum event_type 1602 static enum event_type
1604 process_paren(struct event *event, struct print_arg *arg, char **tok) 1603 process_paren(struct event *event, struct print_arg *arg, char **tok)
1605 { 1604 {
1606 struct print_arg *item_arg; 1605 struct print_arg *item_arg;
1607 enum event_type type; 1606 enum event_type type;
1608 char *token; 1607 char *token;
1609 1608
1610 type = process_arg(event, arg, &token); 1609 type = process_arg(event, arg, &token);
1611 1610
1612 if (type == EVENT_ERROR) 1611 if (type == EVENT_ERROR)
1613 return EVENT_ERROR; 1612 return EVENT_ERROR;
1614 1613
1615 if (type == EVENT_OP) 1614 if (type == EVENT_OP)
1616 type = process_op(event, arg, &token); 1615 type = process_op(event, arg, &token);
1617 1616
1618 if (type == EVENT_ERROR) 1617 if (type == EVENT_ERROR)
1619 return EVENT_ERROR; 1618 return EVENT_ERROR;
1620 1619
1621 if (test_type_token(type, token, EVENT_DELIM, ")")) { 1620 if (test_type_token(type, token, EVENT_DELIM, ")")) {
1622 free_token(token); 1621 free_token(token);
1623 return EVENT_ERROR; 1622 return EVENT_ERROR;
1624 } 1623 }
1625 1624
1626 free_token(token); 1625 free_token(token);
1627 type = read_token_item(&token); 1626 type = read_token_item(&token);
1628 1627
1629 /* 1628 /*
1630 * If the next token is an item or another open paren, then 1629 * If the next token is an item or another open paren, then
1631 * this was a typecast. 1630 * this was a typecast.
1632 */ 1631 */
1633 if (event_item_type(type) || 1632 if (event_item_type(type) ||
1634 (type == EVENT_DELIM && strcmp(token, "(") == 0)) { 1633 (type == EVENT_DELIM && strcmp(token, "(") == 0)) {
1635 1634
1636 /* make this a typecast and contine */ 1635 /* make this a typecast and contine */
1637 1636
1638 /* prevous must be an atom */ 1637 /* prevous must be an atom */
1639 if (arg->type != PRINT_ATOM) 1638 if (arg->type != PRINT_ATOM)
1640 die("previous needed to be PRINT_ATOM"); 1639 die("previous needed to be PRINT_ATOM");
1641 1640
1642 item_arg = malloc_or_die(sizeof(*item_arg)); 1641 item_arg = malloc_or_die(sizeof(*item_arg));
1643 1642
1644 arg->type = PRINT_TYPE; 1643 arg->type = PRINT_TYPE;
1645 arg->typecast.type = arg->atom.atom; 1644 arg->typecast.type = arg->atom.atom;
1646 arg->typecast.item = item_arg; 1645 arg->typecast.item = item_arg;
1647 type = process_arg_token(event, item_arg, &token, type); 1646 type = process_arg_token(event, item_arg, &token, type);
1648 1647
1649 } 1648 }
1650 1649
1651 *tok = token; 1650 *tok = token;
1652 return type; 1651 return type;
1653 } 1652 }
1654 1653
1655 1654
1656 static enum event_type 1655 static enum event_type
1657 process_str(struct event *event __unused, struct print_arg *arg, char **tok) 1656 process_str(struct event *event __unused, struct print_arg *arg, char **tok)
1658 { 1657 {
1659 enum event_type type; 1658 enum event_type type;
1660 char *token; 1659 char *token;
1661 1660
1662 if (read_expected(EVENT_DELIM, "(") < 0) 1661 if (read_expected(EVENT_DELIM, "(") < 0)
1663 return EVENT_ERROR; 1662 return EVENT_ERROR;
1664 1663
1665 if (read_expect_type(EVENT_ITEM, &token) < 0) 1664 if (read_expect_type(EVENT_ITEM, &token) < 0)
1666 goto fail; 1665 goto fail;
1667 1666
1668 arg->type = PRINT_STRING; 1667 arg->type = PRINT_STRING;
1669 arg->string.string = token; 1668 arg->string.string = token;
1670 arg->string.offset = -1; 1669 arg->string.offset = -1;
1671 1670
1672 if (read_expected(EVENT_DELIM, ")") < 0) 1671 if (read_expected(EVENT_DELIM, ")") < 0)
1673 return EVENT_ERROR; 1672 return EVENT_ERROR;
1674 1673
1675 type = read_token(&token); 1674 type = read_token(&token);
1676 *tok = token; 1675 *tok = token;
1677 1676
1678 return type; 1677 return type;
1679 fail: 1678 fail:
1680 free_token(token); 1679 free_token(token);
1681 return EVENT_ERROR; 1680 return EVENT_ERROR;
1682 } 1681 }
1683 1682
1684 enum event_type 1683 enum event_type
1685 process_arg_token(struct event *event, struct print_arg *arg, 1684 process_arg_token(struct event *event, struct print_arg *arg,
1686 char **tok, enum event_type type) 1685 char **tok, enum event_type type)
1687 { 1686 {
1688 char *token; 1687 char *token;
1689 char *atom; 1688 char *atom;
1690 1689
1691 token = *tok; 1690 token = *tok;
1692 1691
1693 switch (type) { 1692 switch (type) {
1694 case EVENT_ITEM: 1693 case EVENT_ITEM:
1695 if (strcmp(token, "REC") == 0) { 1694 if (strcmp(token, "REC") == 0) {
1696 free_token(token); 1695 free_token(token);
1697 type = process_entry(event, arg, &token); 1696 type = process_entry(event, arg, &token);
1698 } else if (strcmp(token, "__print_flags") == 0) { 1697 } else if (strcmp(token, "__print_flags") == 0) {
1699 free_token(token); 1698 free_token(token);
1700 is_flag_field = 1; 1699 is_flag_field = 1;
1701 type = process_flags(event, arg, &token); 1700 type = process_flags(event, arg, &token);
1702 } else if (strcmp(token, "__print_symbolic") == 0) { 1701 } else if (strcmp(token, "__print_symbolic") == 0) {
1703 free_token(token); 1702 free_token(token);
1704 is_symbolic_field = 1; 1703 is_symbolic_field = 1;
1705 type = process_symbols(event, arg, &token); 1704 type = process_symbols(event, arg, &token);
1706 } else if (strcmp(token, "__get_str") == 0) { 1705 } else if (strcmp(token, "__get_str") == 0) {
1707 free_token(token); 1706 free_token(token);
1708 type = process_str(event, arg, &token); 1707 type = process_str(event, arg, &token);
1709 } else { 1708 } else {
1710 atom = token; 1709 atom = token;
1711 /* test the next token */ 1710 /* test the next token */
1712 type = read_token_item(&token); 1711 type = read_token_item(&token);
1713 1712
1714 /* atoms can be more than one token long */ 1713 /* atoms can be more than one token long */
1715 while (type == EVENT_ITEM) { 1714 while (type == EVENT_ITEM) {
1716 atom = realloc(atom, strlen(atom) + strlen(token) + 2); 1715 atom = realloc(atom, strlen(atom) + strlen(token) + 2);
1717 strcat(atom, " "); 1716 strcat(atom, " ");
1718 strcat(atom, token); 1717 strcat(atom, token);
1719 free_token(token); 1718 free_token(token);
1720 type = read_token_item(&token); 1719 type = read_token_item(&token);
1721 } 1720 }
1722 1721
1723 /* todo, test for function */ 1722 /* todo, test for function */
1724 1723
1725 arg->type = PRINT_ATOM; 1724 arg->type = PRINT_ATOM;
1726 arg->atom.atom = atom; 1725 arg->atom.atom = atom;
1727 } 1726 }
1728 break; 1727 break;
1729 case EVENT_DQUOTE: 1728 case EVENT_DQUOTE:
1730 case EVENT_SQUOTE: 1729 case EVENT_SQUOTE:
1731 arg->type = PRINT_ATOM; 1730 arg->type = PRINT_ATOM;
1732 arg->atom.atom = token; 1731 arg->atom.atom = token;
1733 type = read_token_item(&token); 1732 type = read_token_item(&token);
1734 break; 1733 break;
1735 case EVENT_DELIM: 1734 case EVENT_DELIM:
1736 if (strcmp(token, "(") == 0) { 1735 if (strcmp(token, "(") == 0) {
1737 free_token(token); 1736 free_token(token);
1738 type = process_paren(event, arg, &token); 1737 type = process_paren(event, arg, &token);
1739 break; 1738 break;
1740 } 1739 }
1741 case EVENT_OP: 1740 case EVENT_OP:
1742 /* handle single ops */ 1741 /* handle single ops */
1743 arg->type = PRINT_OP; 1742 arg->type = PRINT_OP;
1744 arg->op.op = token; 1743 arg->op.op = token;
1745 arg->op.left = NULL; 1744 arg->op.left = NULL;
1746 type = process_op(event, arg, &token); 1745 type = process_op(event, arg, &token);
1747 1746
1748 break; 1747 break;
1749 1748
1750 case EVENT_ERROR ... EVENT_NEWLINE: 1749 case EVENT_ERROR ... EVENT_NEWLINE:
1751 default: 1750 default:
1752 die("unexpected type %d", type); 1751 die("unexpected type %d", type);
1753 } 1752 }
1754 *tok = token; 1753 *tok = token;
1755 1754
1756 return type; 1755 return type;
1757 } 1756 }
1758 1757
1759 static int event_read_print_args(struct event *event, struct print_arg **list) 1758 static int event_read_print_args(struct event *event, struct print_arg **list)
1760 { 1759 {
1761 enum event_type type = EVENT_ERROR; 1760 enum event_type type = EVENT_ERROR;
1762 struct print_arg *arg; 1761 struct print_arg *arg;
1763 char *token; 1762 char *token;
1764 int args = 0; 1763 int args = 0;
1765 1764
1766 do { 1765 do {
1767 if (type == EVENT_NEWLINE) { 1766 if (type == EVENT_NEWLINE) {
1768 free_token(token); 1767 free_token(token);
1769 type = read_token_item(&token); 1768 type = read_token_item(&token);
1770 continue; 1769 continue;
1771 } 1770 }
1772 1771
1773 arg = malloc_or_die(sizeof(*arg)); 1772 arg = malloc_or_die(sizeof(*arg));
1774 memset(arg, 0, sizeof(*arg)); 1773 memset(arg, 0, sizeof(*arg));
1775 1774
1776 type = process_arg(event, arg, &token); 1775 type = process_arg(event, arg, &token);
1777 1776
1778 if (type == EVENT_ERROR) { 1777 if (type == EVENT_ERROR) {
1779 free_arg(arg); 1778 free_arg(arg);
1780 return -1; 1779 return -1;
1781 } 1780 }
1782 1781
1783 *list = arg; 1782 *list = arg;
1784 args++; 1783 args++;
1785 1784
1786 if (type == EVENT_OP) { 1785 if (type == EVENT_OP) {
1787 type = process_op(event, arg, &token); 1786 type = process_op(event, arg, &token);
1788 list = &arg->next; 1787 list = &arg->next;
1789 continue; 1788 continue;
1790 } 1789 }
1791 1790
1792 if (type == EVENT_DELIM && strcmp(token, ",") == 0) { 1791 if (type == EVENT_DELIM && strcmp(token, ",") == 0) {
1793 free_token(token); 1792 free_token(token);
1794 *list = arg; 1793 *list = arg;
1795 list = &arg->next; 1794 list = &arg->next;
1796 continue; 1795 continue;
1797 } 1796 }
1798 break; 1797 break;
1799 } while (type != EVENT_NONE); 1798 } while (type != EVENT_NONE);
1800 1799
1801 if (type != EVENT_NONE) 1800 if (type != EVENT_NONE)
1802 free_token(token); 1801 free_token(token);
1803 1802
1804 return args; 1803 return args;
1805 } 1804 }
1806 1805
1807 static int event_read_print(struct event *event) 1806 static int event_read_print(struct event *event)
1808 { 1807 {
1809 enum event_type type; 1808 enum event_type type;
1810 char *token; 1809 char *token;
1811 int ret; 1810 int ret;
1812 1811
1813 if (read_expected_item(EVENT_ITEM, "print") < 0) 1812 if (read_expected_item(EVENT_ITEM, "print") < 0)
1814 return -1; 1813 return -1;
1815 1814
1816 if (read_expected(EVENT_ITEM, "fmt") < 0) 1815 if (read_expected(EVENT_ITEM, "fmt") < 0)
1817 return -1; 1816 return -1;
1818 1817
1819 if (read_expected(EVENT_OP, ":") < 0) 1818 if (read_expected(EVENT_OP, ":") < 0)
1820 return -1; 1819 return -1;
1821 1820
1822 if (read_expect_type(EVENT_DQUOTE, &token) < 0) 1821 if (read_expect_type(EVENT_DQUOTE, &token) < 0)
1823 goto fail; 1822 goto fail;
1824 1823
1825 concat: 1824 concat:
1826 event->print_fmt.format = token; 1825 event->print_fmt.format = token;
1827 event->print_fmt.args = NULL; 1826 event->print_fmt.args = NULL;
1828 1827
1829 /* ok to have no arg */ 1828 /* ok to have no arg */
1830 type = read_token_item(&token); 1829 type = read_token_item(&token);
1831 1830
1832 if (type == EVENT_NONE) 1831 if (type == EVENT_NONE)
1833 return 0; 1832 return 0;
1834 1833
1835 /* Handle concatination of print lines */ 1834 /* Handle concatination of print lines */
1836 if (type == EVENT_DQUOTE) { 1835 if (type == EVENT_DQUOTE) {
1837 char *cat; 1836 char *cat;
1838 1837
1839 cat = malloc_or_die(strlen(event->print_fmt.format) + 1838 cat = malloc_or_die(strlen(event->print_fmt.format) +
1840 strlen(token) + 1); 1839 strlen(token) + 1);
1841 strcpy(cat, event->print_fmt.format); 1840 strcpy(cat, event->print_fmt.format);
1842 strcat(cat, token); 1841 strcat(cat, token);
1843 free_token(token); 1842 free_token(token);
1844 free_token(event->print_fmt.format); 1843 free_token(event->print_fmt.format);
1845 event->print_fmt.format = NULL; 1844 event->print_fmt.format = NULL;
1846 token = cat; 1845 token = cat;
1847 goto concat; 1846 goto concat;
1848 } 1847 }
1849 1848
1850 if (test_type_token(type, token, EVENT_DELIM, ",")) 1849 if (test_type_token(type, token, EVENT_DELIM, ","))
1851 goto fail; 1850 goto fail;
1852 1851
1853 free_token(token); 1852 free_token(token);
1854 1853
1855 ret = event_read_print_args(event, &event->print_fmt.args); 1854 ret = event_read_print_args(event, &event->print_fmt.args);
1856 if (ret < 0) 1855 if (ret < 0)
1857 return -1; 1856 return -1;
1858 1857
1859 return ret; 1858 return ret;
1860 1859
1861 fail: 1860 fail:
1862 free_token(token); 1861 free_token(token);
1863 return -1; 1862 return -1;
1864 } 1863 }
1865 1864
1866 static struct format_field * 1865 static struct format_field *
1867 find_common_field(struct event *event, const char *name) 1866 find_common_field(struct event *event, const char *name)
1868 { 1867 {
1869 struct format_field *format; 1868 struct format_field *format;
1870 1869
1871 for (format = event->format.common_fields; 1870 for (format = event->format.common_fields;
1872 format; format = format->next) { 1871 format; format = format->next) {
1873 if (strcmp(format->name, name) == 0) 1872 if (strcmp(format->name, name) == 0)
1874 break; 1873 break;
1875 } 1874 }
1876 1875
1877 return format; 1876 return format;
1878 } 1877 }
1879 1878
1880 static struct format_field * 1879 static struct format_field *
1881 find_field(struct event *event, const char *name) 1880 find_field(struct event *event, const char *name)
1882 { 1881 {
1883 struct format_field *format; 1882 struct format_field *format;
1884 1883
1885 for (format = event->format.fields; 1884 for (format = event->format.fields;
1886 format; format = format->next) { 1885 format; format = format->next) {
1887 if (strcmp(format->name, name) == 0) 1886 if (strcmp(format->name, name) == 0)
1888 break; 1887 break;
1889 } 1888 }
1890 1889
1891 return format; 1890 return format;
1892 } 1891 }
1893 1892
1894 static struct format_field * 1893 static struct format_field *
1895 find_any_field(struct event *event, const char *name) 1894 find_any_field(struct event *event, const char *name)
1896 { 1895 {
1897 struct format_field *format; 1896 struct format_field *format;
1898 1897
1899 format = find_common_field(event, name); 1898 format = find_common_field(event, name);
1900 if (format) 1899 if (format)
1901 return format; 1900 return format;
1902 return find_field(event, name); 1901 return find_field(event, name);
1903 } 1902 }
1904 1903
1905 unsigned long long read_size(void *ptr, int size) 1904 unsigned long long read_size(void *ptr, int size)
1906 { 1905 {
1907 switch (size) { 1906 switch (size) {
1908 case 1: 1907 case 1:
1909 return *(unsigned char *)ptr; 1908 return *(unsigned char *)ptr;
1910 case 2: 1909 case 2:
1911 return data2host2(ptr); 1910 return data2host2(ptr);
1912 case 4: 1911 case 4:
1913 return data2host4(ptr); 1912 return data2host4(ptr);
1914 case 8: 1913 case 8:
1915 return data2host8(ptr); 1914 return data2host8(ptr);
1916 default: 1915 default:
1917 /* BUG! */ 1916 /* BUG! */
1918 return 0; 1917 return 0;
1919 } 1918 }
1920 } 1919 }
1921 1920
1922 unsigned long long 1921 unsigned long long
1923 raw_field_value(struct event *event, const char *name, void *data) 1922 raw_field_value(struct event *event, const char *name, void *data)
1924 { 1923 {
1925 struct format_field *field; 1924 struct format_field *field;
1926 1925
1927 field = find_any_field(event, name); 1926 field = find_any_field(event, name);
1928 if (!field) 1927 if (!field)
1929 return 0ULL; 1928 return 0ULL;
1930 1929
1931 return read_size(data + field->offset, field->size); 1930 return read_size(data + field->offset, field->size);
1932 } 1931 }
1933 1932
1934 void *raw_field_ptr(struct event *event, const char *name, void *data) 1933 void *raw_field_ptr(struct event *event, const char *name, void *data)
1935 { 1934 {
1936 struct format_field *field; 1935 struct format_field *field;
1937 1936
1938 field = find_any_field(event, name); 1937 field = find_any_field(event, name);
1939 if (!field) 1938 if (!field)
1940 return NULL; 1939 return NULL;
1941 1940
1942 if (field->flags & FIELD_IS_DYNAMIC) { 1941 if (field->flags & FIELD_IS_DYNAMIC) {
1943 int offset; 1942 int offset;
1944 1943
1945 offset = *(int *)(data + field->offset); 1944 offset = *(int *)(data + field->offset);
1946 offset &= 0xffff; 1945 offset &= 0xffff;
1947 1946
1948 return data + offset; 1947 return data + offset;
1949 } 1948 }
1950 1949
1951 return data + field->offset; 1950 return data + field->offset;
1952 } 1951 }
1953 1952
1954 static int get_common_info(const char *type, int *offset, int *size) 1953 static int get_common_info(const char *type, int *offset, int *size)
1955 { 1954 {
1956 struct event *event; 1955 struct event *event;
1957 struct format_field *field; 1956 struct format_field *field;
1958 1957
1959 /* 1958 /*
1960 * All events should have the same common elements. 1959 * All events should have the same common elements.
1961 * Pick any event to find where the type is; 1960 * Pick any event to find where the type is;
1962 */ 1961 */
1963 if (!event_list) 1962 if (!event_list)
1964 die("no event_list!"); 1963 die("no event_list!");
1965 1964
1966 event = event_list; 1965 event = event_list;
1967 field = find_common_field(event, type); 1966 field = find_common_field(event, type);
1968 if (!field) 1967 if (!field)
1969 die("field '%s' not found", type); 1968 die("field '%s' not found", type);
1970 1969
1971 *offset = field->offset; 1970 *offset = field->offset;
1972 *size = field->size; 1971 *size = field->size;
1973 1972
1974 return 0; 1973 return 0;
1975 } 1974 }
1976 1975
1977 static int __parse_common(void *data, int *size, int *offset, 1976 static int __parse_common(void *data, int *size, int *offset,
1978 const char *name) 1977 const char *name)
1979 { 1978 {
1980 int ret; 1979 int ret;
1981 1980
1982 if (!*size) { 1981 if (!*size) {
1983 ret = get_common_info(name, offset, size); 1982 ret = get_common_info(name, offset, size);
1984 if (ret < 0) 1983 if (ret < 0)
1985 return ret; 1984 return ret;
1986 } 1985 }
1987 return read_size(data + *offset, *size); 1986 return read_size(data + *offset, *size);
1988 } 1987 }
1989 1988
1990 int trace_parse_common_type(void *data) 1989 int trace_parse_common_type(void *data)
1991 { 1990 {
1992 static int type_offset; 1991 static int type_offset;
1993 static int type_size; 1992 static int type_size;
1994 1993
1995 return __parse_common(data, &type_size, &type_offset, 1994 return __parse_common(data, &type_size, &type_offset,
1996 "common_type"); 1995 "common_type");
1997 } 1996 }
1998 1997
1999 int trace_parse_common_pid(void *data) 1998 int trace_parse_common_pid(void *data)
2000 { 1999 {
2001 static int pid_offset; 2000 static int pid_offset;
2002 static int pid_size; 2001 static int pid_size;
2003 2002
2004 return __parse_common(data, &pid_size, &pid_offset, 2003 return __parse_common(data, &pid_size, &pid_offset,
2005 "common_pid"); 2004 "common_pid");
2006 } 2005 }
2007 2006
2008 int parse_common_pc(void *data) 2007 int parse_common_pc(void *data)
2009 { 2008 {
2010 static int pc_offset; 2009 static int pc_offset;
2011 static int pc_size; 2010 static int pc_size;
2012 2011
2013 return __parse_common(data, &pc_size, &pc_offset, 2012 return __parse_common(data, &pc_size, &pc_offset,
2014 "common_preempt_count"); 2013 "common_preempt_count");
2015 } 2014 }
2016 2015
2017 int parse_common_flags(void *data) 2016 int parse_common_flags(void *data)
2018 { 2017 {
2019 static int flags_offset; 2018 static int flags_offset;
2020 static int flags_size; 2019 static int flags_size;
2021 2020
2022 return __parse_common(data, &flags_size, &flags_offset, 2021 return __parse_common(data, &flags_size, &flags_offset,
2023 "common_flags"); 2022 "common_flags");
2024 } 2023 }
2025 2024
2026 int parse_common_lock_depth(void *data) 2025 int parse_common_lock_depth(void *data)
2027 { 2026 {
2028 static int ld_offset; 2027 static int ld_offset;
2029 static int ld_size; 2028 static int ld_size;
2030 int ret; 2029 int ret;
2031 2030
2032 ret = __parse_common(data, &ld_size, &ld_offset, 2031 ret = __parse_common(data, &ld_size, &ld_offset,
2033 "common_lock_depth"); 2032 "common_lock_depth");
2034 if (ret < 0) 2033 if (ret < 0)
2035 return -1; 2034 return -1;
2036 2035
2037 return ret; 2036 return ret;
2038 } 2037 }
2039 2038
2040 struct event *trace_find_event(int id) 2039 struct event *trace_find_event(int id)
2041 { 2040 {
2042 struct event *event; 2041 struct event *event;
2043 2042
2044 for (event = event_list; event; event = event->next) { 2043 for (event = event_list; event; event = event->next) {
2045 if (event->id == id) 2044 if (event->id == id)
2046 break; 2045 break;
2047 } 2046 }
2048 return event; 2047 return event;
2049 } 2048 }
2050 2049
2051 struct event *trace_find_next_event(struct event *event) 2050 struct event *trace_find_next_event(struct event *event)
2052 { 2051 {
2053 if (!event) 2052 if (!event)
2054 return event_list; 2053 return event_list;
2055 2054
2056 return event->next; 2055 return event->next;
2057 } 2056 }
2058 2057
2059 static unsigned long long eval_num_arg(void *data, int size, 2058 static unsigned long long eval_num_arg(void *data, int size,
2060 struct event *event, struct print_arg *arg) 2059 struct event *event, struct print_arg *arg)
2061 { 2060 {
2062 unsigned long long val = 0; 2061 unsigned long long val = 0;
2063 unsigned long long left, right; 2062 unsigned long long left, right;
2064 struct print_arg *larg; 2063 struct print_arg *larg;
2065 2064
2066 switch (arg->type) { 2065 switch (arg->type) {
2067 case PRINT_NULL: 2066 case PRINT_NULL:
2068 /* ?? */ 2067 /* ?? */
2069 return 0; 2068 return 0;
2070 case PRINT_ATOM: 2069 case PRINT_ATOM:
2071 return strtoull(arg->atom.atom, NULL, 0); 2070 return strtoull(arg->atom.atom, NULL, 0);
2072 case PRINT_FIELD: 2071 case PRINT_FIELD:
2073 if (!arg->field.field) { 2072 if (!arg->field.field) {
2074 arg->field.field = find_any_field(event, arg->field.name); 2073 arg->field.field = find_any_field(event, arg->field.name);
2075 if (!arg->field.field) 2074 if (!arg->field.field)
2076 die("field %s not found", arg->field.name); 2075 die("field %s not found", arg->field.name);
2077 } 2076 }
2078 /* must be a number */ 2077 /* must be a number */
2079 val = read_size(data + arg->field.field->offset, 2078 val = read_size(data + arg->field.field->offset,
2080 arg->field.field->size); 2079 arg->field.field->size);
2081 break; 2080 break;
2082 case PRINT_FLAGS: 2081 case PRINT_FLAGS:
2083 case PRINT_SYMBOL: 2082 case PRINT_SYMBOL:
2084 break; 2083 break;
2085 case PRINT_TYPE: 2084 case PRINT_TYPE:
2086 return eval_num_arg(data, size, event, arg->typecast.item); 2085 return eval_num_arg(data, size, event, arg->typecast.item);
2087 case PRINT_STRING: 2086 case PRINT_STRING:
2088 return 0; 2087 return 0;
2089 break; 2088 break;
2090 case PRINT_OP: 2089 case PRINT_OP:
2091 if (strcmp(arg->op.op, "[") == 0) { 2090 if (strcmp(arg->op.op, "[") == 0) {
2092 /* 2091 /*
2093 * Arrays are special, since we don't want 2092 * Arrays are special, since we don't want
2094 * to read the arg as is. 2093 * to read the arg as is.
2095 */ 2094 */
2096 if (arg->op.left->type != PRINT_FIELD) 2095 if (arg->op.left->type != PRINT_FIELD)
2097 goto default_op; /* oops, all bets off */ 2096 goto default_op; /* oops, all bets off */
2098 larg = arg->op.left; 2097 larg = arg->op.left;
2099 if (!larg->field.field) { 2098 if (!larg->field.field) {
2100 larg->field.field = 2099 larg->field.field =
2101 find_any_field(event, larg->field.name); 2100 find_any_field(event, larg->field.name);
2102 if (!larg->field.field) 2101 if (!larg->field.field)
2103 die("field %s not found", larg->field.name); 2102 die("field %s not found", larg->field.name);
2104 } 2103 }
2105 right = eval_num_arg(data, size, event, arg->op.right); 2104 right = eval_num_arg(data, size, event, arg->op.right);
2106 val = read_size(data + larg->field.field->offset + 2105 val = read_size(data + larg->field.field->offset +
2107 right * long_size, long_size); 2106 right * long_size, long_size);
2108 break; 2107 break;
2109 } 2108 }
2110 default_op: 2109 default_op:
2111 left = eval_num_arg(data, size, event, arg->op.left); 2110 left = eval_num_arg(data, size, event, arg->op.left);
2112 right = eval_num_arg(data, size, event, arg->op.right); 2111 right = eval_num_arg(data, size, event, arg->op.right);
2113 switch (arg->op.op[0]) { 2112 switch (arg->op.op[0]) {
2114 case '|': 2113 case '|':
2115 if (arg->op.op[1]) 2114 if (arg->op.op[1])
2116 val = left || right; 2115 val = left || right;
2117 else 2116 else
2118 val = left | right; 2117 val = left | right;
2119 break; 2118 break;
2120 case '&': 2119 case '&':
2121 if (arg->op.op[1]) 2120 if (arg->op.op[1])
2122 val = left && right; 2121 val = left && right;
2123 else 2122 else
2124 val = left & right; 2123 val = left & right;
2125 break; 2124 break;
2126 case '<': 2125 case '<':
2127 switch (arg->op.op[1]) { 2126 switch (arg->op.op[1]) {
2128 case 0: 2127 case 0:
2129 val = left < right; 2128 val = left < right;
2130 break; 2129 break;
2131 case '<': 2130 case '<':
2132 val = left << right; 2131 val = left << right;
2133 break; 2132 break;
2134 case '=': 2133 case '=':
2135 val = left <= right; 2134 val = left <= right;
2136 break; 2135 break;
2137 default: 2136 default:
2138 die("unknown op '%s'", arg->op.op); 2137 die("unknown op '%s'", arg->op.op);
2139 } 2138 }
2140 break; 2139 break;
2141 case '>': 2140 case '>':
2142 switch (arg->op.op[1]) { 2141 switch (arg->op.op[1]) {
2143 case 0: 2142 case 0:
2144 val = left > right; 2143 val = left > right;
2145 break; 2144 break;
2146 case '>': 2145 case '>':
2147 val = left >> right; 2146 val = left >> right;
2148 break; 2147 break;
2149 case '=': 2148 case '=':
2150 val = left >= right; 2149 val = left >= right;
2151 break; 2150 break;
2152 default: 2151 default:
2153 die("unknown op '%s'", arg->op.op); 2152 die("unknown op '%s'", arg->op.op);
2154 } 2153 }
2155 break; 2154 break;
2156 case '=': 2155 case '=':
2157 if (arg->op.op[1] != '=') 2156 if (arg->op.op[1] != '=')
2158 die("unknown op '%s'", arg->op.op); 2157 die("unknown op '%s'", arg->op.op);
2159 val = left == right; 2158 val = left == right;
2160 break; 2159 break;
2161 case '-': 2160 case '-':
2162 val = left - right; 2161 val = left - right;
2163 break; 2162 break;
2164 case '+': 2163 case '+':
2165 val = left + right; 2164 val = left + right;
2166 break; 2165 break;
2167 default: 2166 default:
2168 die("unknown op '%s'", arg->op.op); 2167 die("unknown op '%s'", arg->op.op);
2169 } 2168 }
2170 break; 2169 break;
2171 default: /* not sure what to do there */ 2170 default: /* not sure what to do there */
2172 return 0; 2171 return 0;
2173 } 2172 }
2174 return val; 2173 return val;
2175 } 2174 }
2176 2175
2177 struct flag { 2176 struct flag {
2178 const char *name; 2177 const char *name;
2179 unsigned long long value; 2178 unsigned long long value;
2180 }; 2179 };
2181 2180
2182 static const struct flag flags[] = { 2181 static const struct flag flags[] = {
2183 { "HI_SOFTIRQ", 0 }, 2182 { "HI_SOFTIRQ", 0 },
2184 { "TIMER_SOFTIRQ", 1 }, 2183 { "TIMER_SOFTIRQ", 1 },
2185 { "NET_TX_SOFTIRQ", 2 }, 2184 { "NET_TX_SOFTIRQ", 2 },
2186 { "NET_RX_SOFTIRQ", 3 }, 2185 { "NET_RX_SOFTIRQ", 3 },
2187 { "BLOCK_SOFTIRQ", 4 }, 2186 { "BLOCK_SOFTIRQ", 4 },
2188 { "BLOCK_IOPOLL_SOFTIRQ", 5 }, 2187 { "BLOCK_IOPOLL_SOFTIRQ", 5 },
2189 { "TASKLET_SOFTIRQ", 6 }, 2188 { "TASKLET_SOFTIRQ", 6 },
2190 { "SCHED_SOFTIRQ", 7 }, 2189 { "SCHED_SOFTIRQ", 7 },
2191 { "HRTIMER_SOFTIRQ", 8 }, 2190 { "HRTIMER_SOFTIRQ", 8 },
2192 { "RCU_SOFTIRQ", 9 }, 2191 { "RCU_SOFTIRQ", 9 },
2193 2192
2194 { "HRTIMER_NORESTART", 0 }, 2193 { "HRTIMER_NORESTART", 0 },
2195 { "HRTIMER_RESTART", 1 }, 2194 { "HRTIMER_RESTART", 1 },
2196 }; 2195 };
2197 2196
2198 unsigned long long eval_flag(const char *flag) 2197 unsigned long long eval_flag(const char *flag)
2199 { 2198 {
2200 int i; 2199 int i;
2201 2200
2202 /* 2201 /*
2203 * Some flags in the format files do not get converted. 2202 * Some flags in the format files do not get converted.
2204 * If the flag is not numeric, see if it is something that 2203 * If the flag is not numeric, see if it is something that
2205 * we already know about. 2204 * we already know about.
2206 */ 2205 */
2207 if (isdigit(flag[0])) 2206 if (isdigit(flag[0]))
2208 return strtoull(flag, NULL, 0); 2207 return strtoull(flag, NULL, 0);
2209 2208
2210 for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++) 2209 for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
2211 if (strcmp(flags[i].name, flag) == 0) 2210 if (strcmp(flags[i].name, flag) == 0)
2212 return flags[i].value; 2211 return flags[i].value;
2213 2212
2214 return 0; 2213 return 0;
2215 } 2214 }
2216 2215
2217 static void print_str_arg(void *data, int size, 2216 static void print_str_arg(void *data, int size,
2218 struct event *event, struct print_arg *arg) 2217 struct event *event, struct print_arg *arg)
2219 { 2218 {
2220 struct print_flag_sym *flag; 2219 struct print_flag_sym *flag;
2221 unsigned long long val, fval; 2220 unsigned long long val, fval;
2222 char *str; 2221 char *str;
2223 int print; 2222 int print;
2224 2223
2225 switch (arg->type) { 2224 switch (arg->type) {
2226 case PRINT_NULL: 2225 case PRINT_NULL:
2227 /* ?? */ 2226 /* ?? */
2228 return; 2227 return;
2229 case PRINT_ATOM: 2228 case PRINT_ATOM:
2230 printf("%s", arg->atom.atom); 2229 printf("%s", arg->atom.atom);
2231 return; 2230 return;
2232 case PRINT_FIELD: 2231 case PRINT_FIELD:
2233 if (!arg->field.field) { 2232 if (!arg->field.field) {
2234 arg->field.field = find_any_field(event, arg->field.name); 2233 arg->field.field = find_any_field(event, arg->field.name);
2235 if (!arg->field.field) 2234 if (!arg->field.field)
2236 die("field %s not found", arg->field.name); 2235 die("field %s not found", arg->field.name);
2237 } 2236 }
2238 str = malloc_or_die(arg->field.field->size + 1); 2237 str = malloc_or_die(arg->field.field->size + 1);
2239 memcpy(str, data + arg->field.field->offset, 2238 memcpy(str, data + arg->field.field->offset,
2240 arg->field.field->size); 2239 arg->field.field->size);
2241 str[arg->field.field->size] = 0; 2240 str[arg->field.field->size] = 0;
2242 printf("%s", str); 2241 printf("%s", str);
2243 free(str); 2242 free(str);
2244 break; 2243 break;
2245 case PRINT_FLAGS: 2244 case PRINT_FLAGS:
2246 val = eval_num_arg(data, size, event, arg->flags.field); 2245 val = eval_num_arg(data, size, event, arg->flags.field);
2247 print = 0; 2246 print = 0;
2248 for (flag = arg->flags.flags; flag; flag = flag->next) { 2247 for (flag = arg->flags.flags; flag; flag = flag->next) {
2249 fval = eval_flag(flag->value); 2248 fval = eval_flag(flag->value);
2250 if (!val && !fval) { 2249 if (!val && !fval) {
2251 printf("%s", flag->str); 2250 printf("%s", flag->str);
2252 break; 2251 break;
2253 } 2252 }
2254 if (fval && (val & fval) == fval) { 2253 if (fval && (val & fval) == fval) {
2255 if (print && arg->flags.delim) 2254 if (print && arg->flags.delim)
2256 printf("%s", arg->flags.delim); 2255 printf("%s", arg->flags.delim);
2257 printf("%s", flag->str); 2256 printf("%s", flag->str);
2258 print = 1; 2257 print = 1;
2259 val &= ~fval; 2258 val &= ~fval;
2260 } 2259 }
2261 } 2260 }
2262 break; 2261 break;
2263 case PRINT_SYMBOL: 2262 case PRINT_SYMBOL:
2264 val = eval_num_arg(data, size, event, arg->symbol.field); 2263 val = eval_num_arg(data, size, event, arg->symbol.field);
2265 for (flag = arg->symbol.symbols; flag; flag = flag->next) { 2264 for (flag = arg->symbol.symbols; flag; flag = flag->next) {
2266 fval = eval_flag(flag->value); 2265 fval = eval_flag(flag->value);
2267 if (val == fval) { 2266 if (val == fval) {
2268 printf("%s", flag->str); 2267 printf("%s", flag->str);
2269 break; 2268 break;
2270 } 2269 }
2271 } 2270 }
2272 break; 2271 break;
2273 2272
2274 case PRINT_TYPE: 2273 case PRINT_TYPE:
2275 break; 2274 break;
2276 case PRINT_STRING: { 2275 case PRINT_STRING: {
2277 int str_offset; 2276 int str_offset;
2278 2277
2279 if (arg->string.offset == -1) { 2278 if (arg->string.offset == -1) {
2280 struct format_field *f; 2279 struct format_field *f;
2281 2280
2282 f = find_any_field(event, arg->string.string); 2281 f = find_any_field(event, arg->string.string);
2283 arg->string.offset = f->offset; 2282 arg->string.offset = f->offset;
2284 } 2283 }
2285 str_offset = *(int *)(data + arg->string.offset); 2284 str_offset = *(int *)(data + arg->string.offset);
2286 str_offset &= 0xffff; 2285 str_offset &= 0xffff;
2287 printf("%s", ((char *)data) + str_offset); 2286 printf("%s", ((char *)data) + str_offset);
2288 break; 2287 break;
2289 } 2288 }
2290 case PRINT_OP: 2289 case PRINT_OP:
2291 /* 2290 /*
2292 * The only op for string should be ? : 2291 * The only op for string should be ? :
2293 */ 2292 */
2294 if (arg->op.op[0] != '?') 2293 if (arg->op.op[0] != '?')
2295 return; 2294 return;
2296 val = eval_num_arg(data, size, event, arg->op.left); 2295 val = eval_num_arg(data, size, event, arg->op.left);
2297 if (val) 2296 if (val)
2298 print_str_arg(data, size, event, arg->op.right->op.left); 2297 print_str_arg(data, size, event, arg->op.right->op.left);
2299 else 2298 else
2300 print_str_arg(data, size, event, arg->op.right->op.right); 2299 print_str_arg(data, size, event, arg->op.right->op.right);
2301 break; 2300 break;
2302 default: 2301 default:
2303 /* well... */ 2302 /* well... */
2304 break; 2303 break;
2305 } 2304 }
2306 } 2305 }
2307 2306
2308 static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event *event) 2307 static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event *event)
2309 { 2308 {
2310 static struct format_field *field, *ip_field; 2309 static struct format_field *field, *ip_field;
2311 struct print_arg *args, *arg, **next; 2310 struct print_arg *args, *arg, **next;
2312 unsigned long long ip, val; 2311 unsigned long long ip, val;
2313 char *ptr; 2312 char *ptr;
2314 void *bptr; 2313 void *bptr;
2315 2314
2316 if (!field) { 2315 if (!field) {
2317 field = find_field(event, "buf"); 2316 field = find_field(event, "buf");
2318 if (!field) 2317 if (!field)
2319 die("can't find buffer field for binary printk"); 2318 die("can't find buffer field for binary printk");
2320 ip_field = find_field(event, "ip"); 2319 ip_field = find_field(event, "ip");
2321 if (!ip_field) 2320 if (!ip_field)
2322 die("can't find ip field for binary printk"); 2321 die("can't find ip field for binary printk");
2323 } 2322 }
2324 2323
2325 ip = read_size(data + ip_field->offset, ip_field->size); 2324 ip = read_size(data + ip_field->offset, ip_field->size);
2326 2325
2327 /* 2326 /*
2328 * The first arg is the IP pointer. 2327 * The first arg is the IP pointer.
2329 */ 2328 */
2330 args = malloc_or_die(sizeof(*args)); 2329 args = malloc_or_die(sizeof(*args));
2331 arg = args; 2330 arg = args;
2332 arg->next = NULL; 2331 arg->next = NULL;
2333 next = &arg->next; 2332 next = &arg->next;
2334 2333
2335 arg->type = PRINT_ATOM; 2334 arg->type = PRINT_ATOM;
2336 arg->atom.atom = malloc_or_die(32); 2335 arg->atom.atom = malloc_or_die(32);
2337 sprintf(arg->atom.atom, "%lld", ip); 2336 sprintf(arg->atom.atom, "%lld", ip);
2338 2337
2339 /* skip the first "%pf : " */ 2338 /* skip the first "%pf : " */
2340 for (ptr = fmt + 6, bptr = data + field->offset; 2339 for (ptr = fmt + 6, bptr = data + field->offset;
2341 bptr < data + size && *ptr; ptr++) { 2340 bptr < data + size && *ptr; ptr++) {
2342 int ls = 0; 2341 int ls = 0;
2343 2342
2344 if (*ptr == '%') { 2343 if (*ptr == '%') {
2345 process_again: 2344 process_again:
2346 ptr++; 2345 ptr++;
2347 switch (*ptr) { 2346 switch (*ptr) {
2348 case '%': 2347 case '%':
2349 break; 2348 break;
2350 case 'l': 2349 case 'l':
2351 ls++; 2350 ls++;
2352 goto process_again; 2351 goto process_again;
2353 case 'L': 2352 case 'L':
2354 ls = 2; 2353 ls = 2;
2355 goto process_again; 2354 goto process_again;
2356 case '0' ... '9': 2355 case '0' ... '9':
2357 goto process_again; 2356 goto process_again;
2358 case 'p': 2357 case 'p':
2359 ls = 1; 2358 ls = 1;
2360 /* fall through */ 2359 /* fall through */
2361 case 'd': 2360 case 'd':
2362 case 'u': 2361 case 'u':
2363 case 'x': 2362 case 'x':
2364 case 'i': 2363 case 'i':
2365 /* the pointers are always 4 bytes aligned */ 2364 /* the pointers are always 4 bytes aligned */
2366 bptr = (void *)(((unsigned long)bptr + 3) & 2365 bptr = (void *)(((unsigned long)bptr + 3) &
2367 ~3); 2366 ~3);
2368 switch (ls) { 2367 switch (ls) {
2369 case 0: 2368 case 0:
2370 case 1: 2369 case 1:
2371 ls = long_size; 2370 ls = long_size;
2372 break; 2371 break;
2373 case 2: 2372 case 2:
2374 ls = 8; 2373 ls = 8;
2375 default: 2374 default:
2376 break; 2375 break;
2377 } 2376 }
2378 val = read_size(bptr, ls); 2377 val = read_size(bptr, ls);
2379 bptr += ls; 2378 bptr += ls;
2380 arg = malloc_or_die(sizeof(*arg)); 2379 arg = malloc_or_die(sizeof(*arg));
2381 arg->next = NULL; 2380 arg->next = NULL;
2382 arg->type = PRINT_ATOM; 2381 arg->type = PRINT_ATOM;
2383 arg->atom.atom = malloc_or_die(32); 2382 arg->atom.atom = malloc_or_die(32);
2384 sprintf(arg->atom.atom, "%lld", val); 2383 sprintf(arg->atom.atom, "%lld", val);
2385 *next = arg; 2384 *next = arg;
2386 next = &arg->next; 2385 next = &arg->next;
2387 break; 2386 break;
2388 case 's': 2387 case 's':
2389 arg = malloc_or_die(sizeof(*arg)); 2388 arg = malloc_or_die(sizeof(*arg));
2390 arg->next = NULL; 2389 arg->next = NULL;
2391 arg->type = PRINT_STRING; 2390 arg->type = PRINT_STRING;
2392 arg->string.string = strdup(bptr); 2391 arg->string.string = strdup(bptr);
2393 bptr += strlen(bptr) + 1; 2392 bptr += strlen(bptr) + 1;
2394 *next = arg; 2393 *next = arg;
2395 next = &arg->next; 2394 next = &arg->next;
2396 default: 2395 default:
2397 break; 2396 break;
2398 } 2397 }
2399 } 2398 }
2400 } 2399 }
2401 2400
2402 return args; 2401 return args;
2403 } 2402 }
2404 2403
2405 static void free_args(struct print_arg *args) 2404 static void free_args(struct print_arg *args)
2406 { 2405 {
2407 struct print_arg *next; 2406 struct print_arg *next;
2408 2407
2409 while (args) { 2408 while (args) {
2410 next = args->next; 2409 next = args->next;
2411 2410
2412 if (args->type == PRINT_ATOM) 2411 if (args->type == PRINT_ATOM)
2413 free(args->atom.atom); 2412 free(args->atom.atom);
2414 else 2413 else
2415 free(args->string.string); 2414 free(args->string.string);
2416 free(args); 2415 free(args);
2417 args = next; 2416 args = next;
2418 } 2417 }
2419 } 2418 }
2420 2419
2421 static char *get_bprint_format(void *data, int size __unused, struct event *event) 2420 static char *get_bprint_format(void *data, int size __unused, struct event *event)
2422 { 2421 {
2423 unsigned long long addr; 2422 unsigned long long addr;
2424 static struct format_field *field; 2423 static struct format_field *field;
2425 struct printk_map *printk; 2424 struct printk_map *printk;
2426 char *format; 2425 char *format;
2427 char *p; 2426 char *p;
2428 2427
2429 if (!field) { 2428 if (!field) {
2430 field = find_field(event, "fmt"); 2429 field = find_field(event, "fmt");
2431 if (!field) 2430 if (!field)
2432 die("can't find format field for binary printk"); 2431 die("can't find format field for binary printk");
2433 printf("field->offset = %d size=%d\n", field->offset, field->size); 2432 printf("field->offset = %d size=%d\n", field->offset, field->size);
2434 } 2433 }
2435 2434
2436 addr = read_size(data + field->offset, field->size); 2435 addr = read_size(data + field->offset, field->size);
2437 2436
2438 printk = find_printk(addr); 2437 printk = find_printk(addr);
2439 if (!printk) { 2438 if (!printk) {
2440 format = malloc_or_die(45); 2439 format = malloc_or_die(45);
2441 sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n", 2440 sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n",
2442 addr); 2441 addr);
2443 return format; 2442 return format;
2444 } 2443 }
2445 2444
2446 p = printk->printk; 2445 p = printk->printk;
2447 /* Remove any quotes. */ 2446 /* Remove any quotes. */
2448 if (*p == '"') 2447 if (*p == '"')
2449 p++; 2448 p++;
2450 format = malloc_or_die(strlen(p) + 10); 2449 format = malloc_or_die(strlen(p) + 10);
2451 sprintf(format, "%s : %s", "%pf", p); 2450 sprintf(format, "%s : %s", "%pf", p);
2452 /* remove ending quotes and new line since we will add one too */ 2451 /* remove ending quotes and new line since we will add one too */
2453 p = format + strlen(format) - 1; 2452 p = format + strlen(format) - 1;
2454 if (*p == '"') 2453 if (*p == '"')
2455 *p = 0; 2454 *p = 0;
2456 2455
2457 p -= 2; 2456 p -= 2;
2458 if (strcmp(p, "\\n") == 0) 2457 if (strcmp(p, "\\n") == 0)
2459 *p = 0; 2458 *p = 0;
2460 2459
2461 return format; 2460 return format;
2462 } 2461 }
2463 2462
2464 static void pretty_print(void *data, int size, struct event *event) 2463 static void pretty_print(void *data, int size, struct event *event)
2465 { 2464 {
2466 struct print_fmt *print_fmt = &event->print_fmt; 2465 struct print_fmt *print_fmt = &event->print_fmt;
2467 struct print_arg *arg = print_fmt->args; 2466 struct print_arg *arg = print_fmt->args;
2468 struct print_arg *args = NULL; 2467 struct print_arg *args = NULL;
2469 const char *ptr = print_fmt->format; 2468 const char *ptr = print_fmt->format;
2470 unsigned long long val; 2469 unsigned long long val;
2471 struct func_map *func; 2470 struct func_map *func;
2472 const char *saveptr; 2471 const char *saveptr;
2473 char *bprint_fmt = NULL; 2472 char *bprint_fmt = NULL;
2474 char format[32]; 2473 char format[32];
2475 int show_func; 2474 int show_func;
2476 int len; 2475 int len;
2477 int ls; 2476 int ls;
2478 2477
2479 if (event->flags & EVENT_FL_ISFUNC) 2478 if (event->flags & EVENT_FL_ISFUNC)
2480 ptr = " %pF <-- %pF"; 2479 ptr = " %pF <-- %pF";
2481 2480
2482 if (event->flags & EVENT_FL_ISBPRINT) { 2481 if (event->flags & EVENT_FL_ISBPRINT) {
2483 bprint_fmt = get_bprint_format(data, size, event); 2482 bprint_fmt = get_bprint_format(data, size, event);
2484 args = make_bprint_args(bprint_fmt, data, size, event); 2483 args = make_bprint_args(bprint_fmt, data, size, event);
2485 arg = args; 2484 arg = args;
2486 ptr = bprint_fmt; 2485 ptr = bprint_fmt;
2487 } 2486 }
2488 2487
2489 for (; *ptr; ptr++) { 2488 for (; *ptr; ptr++) {
2490 ls = 0; 2489 ls = 0;
2491 if (*ptr == '\\') { 2490 if (*ptr == '\\') {
2492 ptr++; 2491 ptr++;
2493 switch (*ptr) { 2492 switch (*ptr) {
2494 case 'n': 2493 case 'n':
2495 printf("\n"); 2494 printf("\n");
2496 break; 2495 break;
2497 case 't': 2496 case 't':
2498 printf("\t"); 2497 printf("\t");
2499 break; 2498 break;
2500 case 'r': 2499 case 'r':
2501 printf("\r"); 2500 printf("\r");
2502 break; 2501 break;
2503 case '\\': 2502 case '\\':
2504 printf("\\"); 2503 printf("\\");
2505 break; 2504 break;
2506 default: 2505 default:
2507 printf("%c", *ptr); 2506 printf("%c", *ptr);
2508 break; 2507 break;
2509 } 2508 }
2510 2509
2511 } else if (*ptr == '%') { 2510 } else if (*ptr == '%') {
2512 saveptr = ptr; 2511 saveptr = ptr;
2513 show_func = 0; 2512 show_func = 0;
2514 cont_process: 2513 cont_process:
2515 ptr++; 2514 ptr++;
2516 switch (*ptr) { 2515 switch (*ptr) {
2517 case '%': 2516 case '%':
2518 printf("%%"); 2517 printf("%%");
2519 break; 2518 break;
2520 case 'l': 2519 case 'l':
2521 ls++; 2520 ls++;
2522 goto cont_process; 2521 goto cont_process;
2523 case 'L': 2522 case 'L':
2524 ls = 2; 2523 ls = 2;
2525 goto cont_process; 2524 goto cont_process;
2526 case 'z': 2525 case 'z':
2527 case 'Z': 2526 case 'Z':
2528 case '0' ... '9': 2527 case '0' ... '9':
2529 goto cont_process; 2528 goto cont_process;
2530 case 'p': 2529 case 'p':
2531 if (long_size == 4) 2530 if (long_size == 4)
2532 ls = 1; 2531 ls = 1;
2533 else 2532 else
2534 ls = 2; 2533 ls = 2;
2535 2534
2536 if (*(ptr+1) == 'F' || 2535 if (*(ptr+1) == 'F' ||
2537 *(ptr+1) == 'f') { 2536 *(ptr+1) == 'f') {
2538 ptr++; 2537 ptr++;
2539 show_func = *ptr; 2538 show_func = *ptr;
2540 } 2539 }
2541 2540
2542 /* fall through */ 2541 /* fall through */
2543 case 'd': 2542 case 'd':
2544 case 'i': 2543 case 'i':
2545 case 'x': 2544 case 'x':
2546 case 'X': 2545 case 'X':
2547 case 'u': 2546 case 'u':
2548 if (!arg) 2547 if (!arg)
2549 die("no argument match"); 2548 die("no argument match");
2550 2549
2551 len = ((unsigned long)ptr + 1) - 2550 len = ((unsigned long)ptr + 1) -
2552 (unsigned long)saveptr; 2551 (unsigned long)saveptr;
2553 2552
2554 /* should never happen */ 2553 /* should never happen */
2555 if (len > 32) 2554 if (len > 32)
2556 die("bad format!"); 2555 die("bad format!");
2557 2556
2558 memcpy(format, saveptr, len); 2557 memcpy(format, saveptr, len);
2559 format[len] = 0; 2558 format[len] = 0;
2560 2559
2561 val = eval_num_arg(data, size, event, arg); 2560 val = eval_num_arg(data, size, event, arg);
2562 arg = arg->next; 2561 arg = arg->next;
2563 2562
2564 if (show_func) { 2563 if (show_func) {
2565 func = find_func(val); 2564 func = find_func(val);
2566 if (func) { 2565 if (func) {
2567 printf("%s", func->func); 2566 printf("%s", func->func);
2568 if (show_func == 'F') 2567 if (show_func == 'F')
2569 printf("+0x%llx", 2568 printf("+0x%llx",
2570 val - func->addr); 2569 val - func->addr);
2571 break; 2570 break;
2572 } 2571 }
2573 } 2572 }
2574 switch (ls) { 2573 switch (ls) {
2575 case 0: 2574 case 0:
2576 printf(format, (int)val); 2575 printf(format, (int)val);
2577 break; 2576 break;
2578 case 1: 2577 case 1:
2579 printf(format, (long)val); 2578 printf(format, (long)val);
2580 break; 2579 break;
2581 case 2: 2580 case 2:
2582 printf(format, (long long)val); 2581 printf(format, (long long)val);
2583 break; 2582 break;
2584 default: 2583 default:
2585 die("bad count (%d)", ls); 2584 die("bad count (%d)", ls);
2586 } 2585 }
2587 break; 2586 break;
2588 case 's': 2587 case 's':
2589 if (!arg) 2588 if (!arg)
2590 die("no matching argument"); 2589 die("no matching argument");
2591 2590
2592 print_str_arg(data, size, event, arg); 2591 print_str_arg(data, size, event, arg);
2593 arg = arg->next; 2592 arg = arg->next;
2594 break; 2593 break;
2595 default: 2594 default:
2596 printf(">%c<", *ptr); 2595 printf(">%c<", *ptr);
2597 2596
2598 } 2597 }
2599 } else 2598 } else
2600 printf("%c", *ptr); 2599 printf("%c", *ptr);
2601 } 2600 }
2602 2601
2603 if (args) { 2602 if (args) {
2604 free_args(args); 2603 free_args(args);
2605 free(bprint_fmt); 2604 free(bprint_fmt);
2606 } 2605 }
2607 } 2606 }
2608 2607
2609 static inline int log10_cpu(int nb) 2608 static inline int log10_cpu(int nb)
2610 { 2609 {
2611 if (nb / 100) 2610 if (nb / 100)
2612 return 3; 2611 return 3;
2613 if (nb / 10) 2612 if (nb / 10)
2614 return 2; 2613 return 2;
2615 return 1; 2614 return 1;
2616 } 2615 }
2617 2616
2618 static void print_lat_fmt(void *data, int size __unused) 2617 static void print_lat_fmt(void *data, int size __unused)
2619 { 2618 {
2620 unsigned int lat_flags; 2619 unsigned int lat_flags;
2621 unsigned int pc; 2620 unsigned int pc;
2622 int lock_depth; 2621 int lock_depth;
2623 int hardirq; 2622 int hardirq;
2624 int softirq; 2623 int softirq;
2625 2624
2626 lat_flags = parse_common_flags(data); 2625 lat_flags = parse_common_flags(data);
2627 pc = parse_common_pc(data); 2626 pc = parse_common_pc(data);
2628 lock_depth = parse_common_lock_depth(data); 2627 lock_depth = parse_common_lock_depth(data);
2629 2628
2630 hardirq = lat_flags & TRACE_FLAG_HARDIRQ; 2629 hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
2631 softirq = lat_flags & TRACE_FLAG_SOFTIRQ; 2630 softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
2632 2631
2633 printf("%c%c%c", 2632 printf("%c%c%c",
2634 (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' : 2633 (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
2635 (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 2634 (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
2636 'X' : '.', 2635 'X' : '.',
2637 (lat_flags & TRACE_FLAG_NEED_RESCHED) ? 2636 (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
2638 'N' : '.', 2637 'N' : '.',
2639 (hardirq && softirq) ? 'H' : 2638 (hardirq && softirq) ? 'H' :
2640 hardirq ? 'h' : softirq ? 's' : '.'); 2639 hardirq ? 'h' : softirq ? 's' : '.');
2641 2640
2642 if (pc) 2641 if (pc)
2643 printf("%x", pc); 2642 printf("%x", pc);
2644 else 2643 else
2645 printf("."); 2644 printf(".");
2646 2645
2647 if (lock_depth < 0) 2646 if (lock_depth < 0)
2648 printf(". "); 2647 printf(". ");
2649 else 2648 else
2650 printf("%d ", lock_depth); 2649 printf("%d ", lock_depth);
2651 } 2650 }
2652 2651
2653 #define TRACE_GRAPH_INDENT 2 2652 #define TRACE_GRAPH_INDENT 2
2654 2653
2655 static struct record * 2654 static struct record *
2656 get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func, 2655 get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func,
2657 struct record *next) 2656 struct record *next)
2658 { 2657 {
2659 struct format_field *field; 2658 struct format_field *field;
2660 struct event *event; 2659 struct event *event;
2661 unsigned long val; 2660 unsigned long val;
2662 int type; 2661 int type;
2663 int pid; 2662 int pid;
2664 2663
2665 type = trace_parse_common_type(next->data); 2664 type = trace_parse_common_type(next->data);
2666 event = trace_find_event(type); 2665 event = trace_find_event(type);
2667 if (!event) 2666 if (!event)
2668 return NULL; 2667 return NULL;
2669 2668
2670 if (!(event->flags & EVENT_FL_ISFUNCRET)) 2669 if (!(event->flags & EVENT_FL_ISFUNCRET))
2671 return NULL; 2670 return NULL;
2672 2671
2673 pid = trace_parse_common_pid(next->data); 2672 pid = trace_parse_common_pid(next->data);
2674 field = find_field(event, "func"); 2673 field = find_field(event, "func");
2675 if (!field) 2674 if (!field)
2676 die("function return does not have field func"); 2675 die("function return does not have field func");
2677 2676
2678 val = read_size(next->data + field->offset, field->size); 2677 val = read_size(next->data + field->offset, field->size);
2679 2678
2680 if (cur_pid != pid || cur_func != val) 2679 if (cur_pid != pid || cur_func != val)
2681 return NULL; 2680 return NULL;
2682 2681
2683 /* this is a leaf, now advance the iterator */ 2682 /* this is a leaf, now advance the iterator */
2684 return trace_read_data(cpu); 2683 return trace_read_data(cpu);
2685 } 2684 }
2686 2685
2687 /* Signal a overhead of time execution to the output */ 2686 /* Signal a overhead of time execution to the output */
2688 static void print_graph_overhead(unsigned long long duration) 2687 static void print_graph_overhead(unsigned long long duration)
2689 { 2688 {
2690 /* Non nested entry or return */ 2689 /* Non nested entry or return */
2691 if (duration == ~0ULL) 2690 if (duration == ~0ULL)
2692 return (void)printf(" "); 2691 return (void)printf(" ");
2693 2692
2694 /* Duration exceeded 100 msecs */ 2693 /* Duration exceeded 100 msecs */
2695 if (duration > 100000ULL) 2694 if (duration > 100000ULL)
2696 return (void)printf("! "); 2695 return (void)printf("! ");
2697 2696
2698 /* Duration exceeded 10 msecs */ 2697 /* Duration exceeded 10 msecs */
2699 if (duration > 10000ULL) 2698 if (duration > 10000ULL)
2700 return (void)printf("+ "); 2699 return (void)printf("+ ");
2701 2700
2702 printf(" "); 2701 printf(" ");
2703 } 2702 }
2704 2703
2705 static void print_graph_duration(unsigned long long duration) 2704 static void print_graph_duration(unsigned long long duration)
2706 { 2705 {
2707 unsigned long usecs = duration / 1000; 2706 unsigned long usecs = duration / 1000;
2708 unsigned long nsecs_rem = duration % 1000; 2707 unsigned long nsecs_rem = duration % 1000;
2709 /* log10(ULONG_MAX) + '\0' */ 2708 /* log10(ULONG_MAX) + '\0' */
2710 char msecs_str[21]; 2709 char msecs_str[21];
2711 char nsecs_str[5]; 2710 char nsecs_str[5];
2712 int len; 2711 int len;
2713 int i; 2712 int i;
2714 2713
2715 sprintf(msecs_str, "%lu", usecs); 2714 sprintf(msecs_str, "%lu", usecs);
2716 2715
2717 /* Print msecs */ 2716 /* Print msecs */
2718 len = printf("%lu", usecs); 2717 len = printf("%lu", usecs);
2719 2718
2720 /* Print nsecs (we don't want to exceed 7 numbers) */ 2719 /* Print nsecs (we don't want to exceed 7 numbers) */
2721 if (len < 7) { 2720 if (len < 7) {
2722 snprintf(nsecs_str, 8 - len, "%03lu", nsecs_rem); 2721 snprintf(nsecs_str, 8 - len, "%03lu", nsecs_rem);
2723 len += printf(".%s", nsecs_str); 2722 len += printf(".%s", nsecs_str);
2724 } 2723 }
2725 2724
2726 printf(" us "); 2725 printf(" us ");
2727 2726
2728 /* Print remaining spaces to fit the row's width */ 2727 /* Print remaining spaces to fit the row's width */
2729 for (i = len; i < 7; i++) 2728 for (i = len; i < 7; i++)
2730 printf(" "); 2729 printf(" ");
2731 2730
2732 printf("| "); 2731 printf("| ");
2733 } 2732 }
2734 2733
2735 static void 2734 static void
2736 print_graph_entry_leaf(struct event *event, void *data, struct record *ret_rec) 2735 print_graph_entry_leaf(struct event *event, void *data, struct record *ret_rec)
2737 { 2736 {
2738 unsigned long long rettime, calltime; 2737 unsigned long long rettime, calltime;
2739 unsigned long long duration, depth; 2738 unsigned long long duration, depth;
2740 unsigned long long val; 2739 unsigned long long val;
2741 struct format_field *field; 2740 struct format_field *field;
2742 struct func_map *func; 2741 struct func_map *func;
2743 struct event *ret_event; 2742 struct event *ret_event;
2744 int type; 2743 int type;
2745 int i; 2744 int i;
2746 2745
2747 type = trace_parse_common_type(ret_rec->data); 2746 type = trace_parse_common_type(ret_rec->data);
2748 ret_event = trace_find_event(type); 2747 ret_event = trace_find_event(type);
2749 2748
2750 field = find_field(ret_event, "rettime"); 2749 field = find_field(ret_event, "rettime");
2751 if (!field) 2750 if (!field)
2752 die("can't find rettime in return graph"); 2751 die("can't find rettime in return graph");
2753 rettime = read_size(ret_rec->data + field->offset, field->size); 2752 rettime = read_size(ret_rec->data + field->offset, field->size);
2754 2753
2755 field = find_field(ret_event, "calltime"); 2754 field = find_field(ret_event, "calltime");
2756 if (!field) 2755 if (!field)
2757 die("can't find rettime in return graph"); 2756 die("can't find rettime in return graph");
2758 calltime = read_size(ret_rec->data + field->offset, field->size); 2757 calltime = read_size(ret_rec->data + field->offset, field->size);
2759 2758
2760 duration = rettime - calltime; 2759 duration = rettime - calltime;
2761 2760
2762 /* Overhead */ 2761 /* Overhead */
2763 print_graph_overhead(duration); 2762 print_graph_overhead(duration);
2764 2763
2765 /* Duration */ 2764 /* Duration */
2766 print_graph_duration(duration); 2765 print_graph_duration(duration);
2767 2766
2768 field = find_field(event, "depth"); 2767 field = find_field(event, "depth");
2769 if (!field) 2768 if (!field)
2770 die("can't find depth in entry graph"); 2769 die("can't find depth in entry graph");
2771 depth = read_size(data + field->offset, field->size); 2770 depth = read_size(data + field->offset, field->size);
2772 2771
2773 /* Function */ 2772 /* Function */
2774 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++) 2773 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2775 printf(" "); 2774 printf(" ");
2776 2775
2777 field = find_field(event, "func"); 2776 field = find_field(event, "func");
2778 if (!field) 2777 if (!field)
2779 die("can't find func in entry graph"); 2778 die("can't find func in entry graph");
2780 val = read_size(data + field->offset, field->size); 2779 val = read_size(data + field->offset, field->size);
2781 func = find_func(val); 2780 func = find_func(val);
2782 2781
2783 if (func) 2782 if (func)
2784 printf("%s();", func->func); 2783 printf("%s();", func->func);
2785 else 2784 else
2786 printf("%llx();", val); 2785 printf("%llx();", val);
2787 } 2786 }
2788 2787
2789 static void print_graph_nested(struct event *event, void *data) 2788 static void print_graph_nested(struct event *event, void *data)
2790 { 2789 {
2791 struct format_field *field; 2790 struct format_field *field;
2792 unsigned long long depth; 2791 unsigned long long depth;
2793 unsigned long long val; 2792 unsigned long long val;
2794 struct func_map *func; 2793 struct func_map *func;
2795 int i; 2794 int i;
2796 2795
2797 /* No overhead */ 2796 /* No overhead */
2798 print_graph_overhead(-1); 2797 print_graph_overhead(-1);
2799 2798
2800 /* No time */ 2799 /* No time */
2801 printf(" | "); 2800 printf(" | ");
2802 2801
2803 field = find_field(event, "depth"); 2802 field = find_field(event, "depth");
2804 if (!field) 2803 if (!field)
2805 die("can't find depth in entry graph"); 2804 die("can't find depth in entry graph");
2806 depth = read_size(data + field->offset, field->size); 2805 depth = read_size(data + field->offset, field->size);
2807 2806
2808 /* Function */ 2807 /* Function */
2809 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++) 2808 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2810 printf(" "); 2809 printf(" ");
2811 2810
2812 field = find_field(event, "func"); 2811 field = find_field(event, "func");
2813 if (!field) 2812 if (!field)
2814 die("can't find func in entry graph"); 2813 die("can't find func in entry graph");
2815 val = read_size(data + field->offset, field->size); 2814 val = read_size(data + field->offset, field->size);
2816 func = find_func(val); 2815 func = find_func(val);
2817 2816
2818 if (func) 2817 if (func)
2819 printf("%s() {", func->func); 2818 printf("%s() {", func->func);
2820 else 2819 else
2821 printf("%llx() {", val); 2820 printf("%llx() {", val);
2822 } 2821 }
2823 2822
2824 static void 2823 static void
2825 pretty_print_func_ent(void *data, int size, struct event *event, 2824 pretty_print_func_ent(void *data, int size, struct event *event,
2826 int cpu, int pid) 2825 int cpu, int pid)
2827 { 2826 {
2828 struct format_field *field; 2827 struct format_field *field;
2829 struct record *rec; 2828 struct record *rec;
2830 void *copy_data; 2829 void *copy_data;
2831 unsigned long val; 2830 unsigned long val;
2832 2831
2833 if (latency_format) { 2832 if (latency_format) {
2834 print_lat_fmt(data, size); 2833 print_lat_fmt(data, size);
2835 printf(" | "); 2834 printf(" | ");
2836 } 2835 }
2837 2836
2838 field = find_field(event, "func"); 2837 field = find_field(event, "func");
2839 if (!field) 2838 if (!field)
2840 die("function entry does not have func field"); 2839 die("function entry does not have func field");
2841 2840
2842 val = read_size(data + field->offset, field->size); 2841 val = read_size(data + field->offset, field->size);
2843 2842
2844 /* 2843 /*
2845 * peek_data may unmap the data pointer. Copy it first. 2844 * peek_data may unmap the data pointer. Copy it first.
2846 */ 2845 */
2847 copy_data = malloc_or_die(size); 2846 copy_data = malloc_or_die(size);
2848 memcpy(copy_data, data, size); 2847 memcpy(copy_data, data, size);
2849 data = copy_data; 2848 data = copy_data;
2850 2849
2851 rec = trace_peek_data(cpu); 2850 rec = trace_peek_data(cpu);
2852 if (rec) { 2851 if (rec) {
2853 rec = get_return_for_leaf(cpu, pid, val, rec); 2852 rec = get_return_for_leaf(cpu, pid, val, rec);
2854 if (rec) { 2853 if (rec) {
2855 print_graph_entry_leaf(event, data, rec); 2854 print_graph_entry_leaf(event, data, rec);
2856 goto out_free; 2855 goto out_free;
2857 } 2856 }
2858 } 2857 }
2859 print_graph_nested(event, data); 2858 print_graph_nested(event, data);
2860 out_free: 2859 out_free:
2861 free(data); 2860 free(data);
2862 } 2861 }
2863 2862
2864 static void 2863 static void
2865 pretty_print_func_ret(void *data, int size __unused, struct event *event) 2864 pretty_print_func_ret(void *data, int size __unused, struct event *event)
2866 { 2865 {
2867 unsigned long long rettime, calltime; 2866 unsigned long long rettime, calltime;
2868 unsigned long long duration, depth; 2867 unsigned long long duration, depth;
2869 struct format_field *field; 2868 struct format_field *field;
2870 int i; 2869 int i;
2871 2870
2872 if (latency_format) { 2871 if (latency_format) {
2873 print_lat_fmt(data, size); 2872 print_lat_fmt(data, size);
2874 printf(" | "); 2873 printf(" | ");
2875 } 2874 }
2876 2875
2877 field = find_field(event, "rettime"); 2876 field = find_field(event, "rettime");
2878 if (!field) 2877 if (!field)
2879 die("can't find rettime in return graph"); 2878 die("can't find rettime in return graph");
2880 rettime = read_size(data + field->offset, field->size); 2879 rettime = read_size(data + field->offset, field->size);
2881 2880
2882 field = find_field(event, "calltime"); 2881 field = find_field(event, "calltime");
2883 if (!field) 2882 if (!field)
2884 die("can't find calltime in return graph"); 2883 die("can't find calltime in return graph");
2885 calltime = read_size(data + field->offset, field->size); 2884 calltime = read_size(data + field->offset, field->size);
2886 2885
2887 duration = rettime - calltime; 2886 duration = rettime - calltime;
2888 2887
2889 /* Overhead */ 2888 /* Overhead */
2890 print_graph_overhead(duration); 2889 print_graph_overhead(duration);
2891 2890
2892 /* Duration */ 2891 /* Duration */
2893 print_graph_duration(duration); 2892 print_graph_duration(duration);
2894 2893
2895 field = find_field(event, "depth"); 2894 field = find_field(event, "depth");
2896 if (!field) 2895 if (!field)
2897 die("can't find depth in entry graph"); 2896 die("can't find depth in entry graph");
2898 depth = read_size(data + field->offset, field->size); 2897 depth = read_size(data + field->offset, field->size);
2899 2898
2900 /* Function */ 2899 /* Function */
2901 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++) 2900 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2902 printf(" "); 2901 printf(" ");
2903 2902
2904 printf("}"); 2903 printf("}");
2905 } 2904 }
2906 2905
2907 static void 2906 static void
2908 pretty_print_func_graph(void *data, int size, struct event *event, 2907 pretty_print_func_graph(void *data, int size, struct event *event,
2909 int cpu, int pid) 2908 int cpu, int pid)
2910 { 2909 {
2911 if (event->flags & EVENT_FL_ISFUNCENT) 2910 if (event->flags & EVENT_FL_ISFUNCENT)
2912 pretty_print_func_ent(data, size, event, cpu, pid); 2911 pretty_print_func_ent(data, size, event, cpu, pid);
2913 else if (event->flags & EVENT_FL_ISFUNCRET) 2912 else if (event->flags & EVENT_FL_ISFUNCRET)
2914 pretty_print_func_ret(data, size, event); 2913 pretty_print_func_ret(data, size, event);
2915 printf("\n"); 2914 printf("\n");
2916 } 2915 }
2917 2916
2918 void print_trace_event(int cpu, void *data, int size) 2917 void print_trace_event(int cpu, void *data, int size)
2919 { 2918 {
2920 struct event *event; 2919 struct event *event;
2921 int type; 2920 int type;
2922 int pid; 2921 int pid;
2923 2922
2924 type = trace_parse_common_type(data); 2923 type = trace_parse_common_type(data);
2925 2924
2926 event = trace_find_event(type); 2925 event = trace_find_event(type);
2927 if (!event) { 2926 if (!event) {
2928 warning("ug! no event found for type %d", type); 2927 warning("ug! no event found for type %d", type);
2929 return; 2928 return;
2930 } 2929 }
2931 2930
2932 pid = trace_parse_common_pid(data); 2931 pid = trace_parse_common_pid(data);
2933 2932
2934 if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET)) 2933 if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET))
2935 return pretty_print_func_graph(data, size, event, cpu, pid); 2934 return pretty_print_func_graph(data, size, event, cpu, pid);
2936 2935
2937 if (latency_format) 2936 if (latency_format)
2938 print_lat_fmt(data, size); 2937 print_lat_fmt(data, size);
2939 2938
2940 if (event->flags & EVENT_FL_FAILED) { 2939 if (event->flags & EVENT_FL_FAILED) {
2941 printf("EVENT '%s' FAILED TO PARSE\n", 2940 printf("EVENT '%s' FAILED TO PARSE\n",
2942 event->name); 2941 event->name);
2943 return; 2942 return;
2944 } 2943 }
2945 2944
2946 pretty_print(data, size, event); 2945 pretty_print(data, size, event);
2947 } 2946 }
2948 2947
2949 static void print_fields(struct print_flag_sym *field) 2948 static void print_fields(struct print_flag_sym *field)
2950 { 2949 {
2951 printf("{ %s, %s }", field->value, field->str); 2950 printf("{ %s, %s }", field->value, field->str);
2952 if (field->next) { 2951 if (field->next) {
2953 printf(", "); 2952 printf(", ");
2954 print_fields(field->next); 2953 print_fields(field->next);
2955 } 2954 }
2956 } 2955 }
2957 2956
2958 static void print_args(struct print_arg *args) 2957 static void print_args(struct print_arg *args)
2959 { 2958 {
2960 int print_paren = 1; 2959 int print_paren = 1;
2961 2960
2962 switch (args->type) { 2961 switch (args->type) {
2963 case PRINT_NULL: 2962 case PRINT_NULL:
2964 printf("null"); 2963 printf("null");
2965 break; 2964 break;
2966 case PRINT_ATOM: 2965 case PRINT_ATOM:
2967 printf("%s", args->atom.atom); 2966 printf("%s", args->atom.atom);
2968 break; 2967 break;
2969 case PRINT_FIELD: 2968 case PRINT_FIELD:
2970 printf("REC->%s", args->field.name); 2969 printf("REC->%s", args->field.name);
2971 break; 2970 break;
2972 case PRINT_FLAGS: 2971 case PRINT_FLAGS:
2973 printf("__print_flags("); 2972 printf("__print_flags(");
2974 print_args(args->flags.field); 2973 print_args(args->flags.field);
2975 printf(", %s, ", args->flags.delim); 2974 printf(", %s, ", args->flags.delim);
2976 print_fields(args->flags.flags); 2975 print_fields(args->flags.flags);
2977 printf(")"); 2976 printf(")");
2978 break; 2977 break;
2979 case PRINT_SYMBOL: 2978 case PRINT_SYMBOL:
2980 printf("__print_symbolic("); 2979 printf("__print_symbolic(");
2981 print_args(args->symbol.field); 2980 print_args(args->symbol.field);
2982 printf(", "); 2981 printf(", ");
2983 print_fields(args->symbol.symbols); 2982 print_fields(args->symbol.symbols);
2984 printf(")"); 2983 printf(")");
2985 break; 2984 break;
2986 case PRINT_STRING: 2985 case PRINT_STRING:
2987 printf("__get_str(%s)", args->string.string); 2986 printf("__get_str(%s)", args->string.string);
2988 break; 2987 break;
2989 case PRINT_TYPE: 2988 case PRINT_TYPE:
2990 printf("(%s)", args->typecast.type); 2989 printf("(%s)", args->typecast.type);
2991 print_args(args->typecast.item); 2990 print_args(args->typecast.item);
2992 break; 2991 break;
2993 case PRINT_OP: 2992 case PRINT_OP:
2994 if (strcmp(args->op.op, ":") == 0) 2993 if (strcmp(args->op.op, ":") == 0)
2995 print_paren = 0; 2994 print_paren = 0;
2996 if (print_paren) 2995 if (print_paren)
2997 printf("("); 2996 printf("(");
2998 print_args(args->op.left); 2997 print_args(args->op.left);
2999 printf(" %s ", args->op.op); 2998 printf(" %s ", args->op.op);
3000 print_args(args->op.right); 2999 print_args(args->op.right);
3001 if (print_paren) 3000 if (print_paren)
3002 printf(")"); 3001 printf(")");
3003 break; 3002 break;
3004 default: 3003 default:
3005 /* we should warn... */ 3004 /* we should warn... */
3006 return; 3005 return;
3007 } 3006 }
3008 if (args->next) { 3007 if (args->next) {
3009 printf("\n"); 3008 printf("\n");
3010 print_args(args->next); 3009 print_args(args->next);
3011 } 3010 }
3012 } 3011 }
3013 3012
3014 int parse_ftrace_file(char *buf, unsigned long size) 3013 int parse_ftrace_file(char *buf, unsigned long size)
3015 { 3014 {
3016 struct format_field *field; 3015 struct format_field *field;
3017 struct print_arg *arg, **list; 3016 struct print_arg *arg, **list;
3018 struct event *event; 3017 struct event *event;
3019 int ret; 3018 int ret;
3020 3019
3021 init_input_buf(buf, size); 3020 init_input_buf(buf, size);
3022 3021
3023 event = alloc_event(); 3022 event = alloc_event();
3024 if (!event) 3023 if (!event)
3025 return -ENOMEM; 3024 return -ENOMEM;
3026 3025
3027 event->flags |= EVENT_FL_ISFTRACE; 3026 event->flags |= EVENT_FL_ISFTRACE;
3028 3027
3029 event->name = event_read_name(); 3028 event->name = event_read_name();
3030 if (!event->name) 3029 if (!event->name)
3031 die("failed to read ftrace event name"); 3030 die("failed to read ftrace event name");
3032 3031
3033 if (strcmp(event->name, "function") == 0) 3032 if (strcmp(event->name, "function") == 0)
3034 event->flags |= EVENT_FL_ISFUNC; 3033 event->flags |= EVENT_FL_ISFUNC;
3035 3034
3036 else if (strcmp(event->name, "funcgraph_entry") == 0) 3035 else if (strcmp(event->name, "funcgraph_entry") == 0)
3037 event->flags |= EVENT_FL_ISFUNCENT; 3036 event->flags |= EVENT_FL_ISFUNCENT;
3038 3037
3039 else if (strcmp(event->name, "funcgraph_exit") == 0) 3038 else if (strcmp(event->name, "funcgraph_exit") == 0)
3040 event->flags |= EVENT_FL_ISFUNCRET; 3039 event->flags |= EVENT_FL_ISFUNCRET;
3041 3040
3042 else if (strcmp(event->name, "bprint") == 0) 3041 else if (strcmp(event->name, "bprint") == 0)
3043 event->flags |= EVENT_FL_ISBPRINT; 3042 event->flags |= EVENT_FL_ISBPRINT;
3044 3043
3045 event->id = event_read_id(); 3044 event->id = event_read_id();
3046 if (event->id < 0) 3045 if (event->id < 0)
3047 die("failed to read ftrace event id"); 3046 die("failed to read ftrace event id");
3048 3047
3049 add_event(event); 3048 add_event(event);
3050 3049
3051 ret = event_read_format(event); 3050 ret = event_read_format(event);
3052 if (ret < 0) 3051 if (ret < 0)
3053 die("failed to read ftrace event format"); 3052 die("failed to read ftrace event format");
3054 3053
3055 ret = event_read_print(event); 3054 ret = event_read_print(event);
3056 if (ret < 0) 3055 if (ret < 0)
3057 die("failed to read ftrace event print fmt"); 3056 die("failed to read ftrace event print fmt");
3058 3057
3059 /* New ftrace handles args */ 3058 /* New ftrace handles args */
3060 if (ret > 0) 3059 if (ret > 0)
3061 return 0; 3060 return 0;
3062 /* 3061 /*
3063 * The arguments for ftrace files are parsed by the fields. 3062 * The arguments for ftrace files are parsed by the fields.
3064 * Set up the fields as their arguments. 3063 * Set up the fields as their arguments.
3065 */ 3064 */
3066 list = &event->print_fmt.args; 3065 list = &event->print_fmt.args;
3067 for (field = event->format.fields; field; field = field->next) { 3066 for (field = event->format.fields; field; field = field->next) {
3068 arg = malloc_or_die(sizeof(*arg)); 3067 arg = malloc_or_die(sizeof(*arg));
3069 memset(arg, 0, sizeof(*arg)); 3068 memset(arg, 0, sizeof(*arg));
3070 *list = arg; 3069 *list = arg;
3071 list = &arg->next; 3070 list = &arg->next;
3072 arg->type = PRINT_FIELD; 3071 arg->type = PRINT_FIELD;
3073 arg->field.name = field->name; 3072 arg->field.name = field->name;
3074 arg->field.field = field; 3073 arg->field.field = field;
3075 } 3074 }
3076 return 0; 3075 return 0;
3077 } 3076 }
3078 3077
3079 int parse_event_file(char *buf, unsigned long size, char *sys) 3078 int parse_event_file(char *buf, unsigned long size, char *sys)
3080 { 3079 {
3081 struct event *event; 3080 struct event *event;
3082 int ret; 3081 int ret;
3083 3082
3084 init_input_buf(buf, size); 3083 init_input_buf(buf, size);
3085 3084
3086 event = alloc_event(); 3085 event = alloc_event();
3087 if (!event) 3086 if (!event)
3088 return -ENOMEM; 3087 return -ENOMEM;
3089 3088
3090 event->name = event_read_name(); 3089 event->name = event_read_name();
3091 if (!event->name) 3090 if (!event->name)
3092 die("failed to read event name"); 3091 die("failed to read event name");
3093 3092
3094 event->id = event_read_id(); 3093 event->id = event_read_id();
3095 if (event->id < 0) 3094 if (event->id < 0)
3096 die("failed to read event id"); 3095 die("failed to read event id");
3097 3096
3098 ret = event_read_format(event); 3097 ret = event_read_format(event);
3099 if (ret < 0) { 3098 if (ret < 0) {
3100 warning("failed to read event format for %s", event->name); 3099 warning("failed to read event format for %s", event->name);
3101 goto event_failed; 3100 goto event_failed;
3102 } 3101 }
3103 3102
3104 ret = event_read_print(event); 3103 ret = event_read_print(event);
3105 if (ret < 0) { 3104 if (ret < 0) {
3106 warning("failed to read event print fmt for %s", event->name); 3105 warning("failed to read event print fmt for %s", event->name);
3107 goto event_failed; 3106 goto event_failed;
3108 } 3107 }
3109 3108
3110 event->system = strdup(sys); 3109 event->system = strdup(sys);
3111 3110
3112 #define PRINT_ARGS 0 3111 #define PRINT_ARGS 0
3113 if (PRINT_ARGS && event->print_fmt.args) 3112 if (PRINT_ARGS && event->print_fmt.args)
3114 print_args(event->print_fmt.args); 3113 print_args(event->print_fmt.args);
3115 3114
3116 add_event(event); 3115 add_event(event);
3117 return 0; 3116 return 0;
3118 3117
3119 event_failed: 3118 event_failed:
3120 event->flags |= EVENT_FL_FAILED; 3119 event->flags |= EVENT_FL_FAILED;
3121 /* still add it even if it failed */ 3120 /* still add it even if it failed */
3122 add_event(event); 3121 add_event(event);
3123 return -1; 3122 return -1;
3124 } 3123 }
3125 3124
3126 void parse_set_info(int nr_cpus, int long_sz) 3125 void parse_set_info(int nr_cpus, int long_sz)
3127 { 3126 {
3128 cpus = nr_cpus; 3127 cpus = nr_cpus;
3129 long_size = long_sz; 3128 long_size = long_sz;
3130 } 3129 }
3131 3130
3132 int common_pc(struct scripting_context *context) 3131 int common_pc(struct scripting_context *context)
3133 { 3132 {
3134 return parse_common_pc(context->event_data); 3133 return parse_common_pc(context->event_data);
3135 } 3134 }
3136 3135
3137 int common_flags(struct scripting_context *context) 3136 int common_flags(struct scripting_context *context)
3138 { 3137 {
3139 return parse_common_flags(context->event_data); 3138 return parse_common_flags(context->event_data);
3140 } 3139 }
3141 3140
3142 int common_lock_depth(struct scripting_context *context) 3141 int common_lock_depth(struct scripting_context *context)
3143 { 3142 {
3144 return parse_common_lock_depth(context->event_data); 3143 return parse_common_lock_depth(context->event_data);
3145 } 3144 }
3146 3145
tools/perf/util/ui/browsers/hists.c
1 #define _GNU_SOURCE
2 #include <stdio.h> 1 #include <stdio.h>
3 #undef _GNU_SOURCE
4 #include "../libslang.h" 2 #include "../libslang.h"
5 #include <stdlib.h> 3 #include <stdlib.h>
6 #include <string.h> 4 #include <string.h>
7 #include <newt.h> 5 #include <newt.h>
8 #include <linux/rbtree.h> 6 #include <linux/rbtree.h>
9 7
10 #include "../../evsel.h" 8 #include "../../evsel.h"
11 #include "../../evlist.h" 9 #include "../../evlist.h"
12 #include "../../hist.h" 10 #include "../../hist.h"
13 #include "../../pstack.h" 11 #include "../../pstack.h"
14 #include "../../sort.h" 12 #include "../../sort.h"
15 #include "../../util.h" 13 #include "../../util.h"
16 14
17 #include "../browser.h" 15 #include "../browser.h"
18 #include "../helpline.h" 16 #include "../helpline.h"
19 #include "../util.h" 17 #include "../util.h"
20 #include "../ui.h" 18 #include "../ui.h"
21 #include "map.h" 19 #include "map.h"
22 20
23 struct hist_browser { 21 struct hist_browser {
24 struct ui_browser b; 22 struct ui_browser b;
25 struct hists *hists; 23 struct hists *hists;
26 struct hist_entry *he_selection; 24 struct hist_entry *he_selection;
27 struct map_symbol *selection; 25 struct map_symbol *selection;
28 bool has_symbols; 26 bool has_symbols;
29 }; 27 };
30 28
31 static int hists__browser_title(struct hists *self, char *bf, size_t size, 29 static int hists__browser_title(struct hists *self, char *bf, size_t size,
32 const char *ev_name); 30 const char *ev_name);
33 31
34 static void hist_browser__refresh_dimensions(struct hist_browser *self) 32 static void hist_browser__refresh_dimensions(struct hist_browser *self)
35 { 33 {
36 /* 3 == +/- toggle symbol before actual hist_entry rendering */ 34 /* 3 == +/- toggle symbol before actual hist_entry rendering */
37 self->b.width = 3 + (hists__sort_list_width(self->hists) + 35 self->b.width = 3 + (hists__sort_list_width(self->hists) +
38 sizeof("[k]")); 36 sizeof("[k]"));
39 } 37 }
40 38
41 static void hist_browser__reset(struct hist_browser *self) 39 static void hist_browser__reset(struct hist_browser *self)
42 { 40 {
43 self->b.nr_entries = self->hists->nr_entries; 41 self->b.nr_entries = self->hists->nr_entries;
44 hist_browser__refresh_dimensions(self); 42 hist_browser__refresh_dimensions(self);
45 ui_browser__reset_index(&self->b); 43 ui_browser__reset_index(&self->b);
46 } 44 }
47 45
48 static char tree__folded_sign(bool unfolded) 46 static char tree__folded_sign(bool unfolded)
49 { 47 {
50 return unfolded ? '-' : '+'; 48 return unfolded ? '-' : '+';
51 } 49 }
52 50
53 static char map_symbol__folded(const struct map_symbol *self) 51 static char map_symbol__folded(const struct map_symbol *self)
54 { 52 {
55 return self->has_children ? tree__folded_sign(self->unfolded) : ' '; 53 return self->has_children ? tree__folded_sign(self->unfolded) : ' ';
56 } 54 }
57 55
58 static char hist_entry__folded(const struct hist_entry *self) 56 static char hist_entry__folded(const struct hist_entry *self)
59 { 57 {
60 return map_symbol__folded(&self->ms); 58 return map_symbol__folded(&self->ms);
61 } 59 }
62 60
63 static char callchain_list__folded(const struct callchain_list *self) 61 static char callchain_list__folded(const struct callchain_list *self)
64 { 62 {
65 return map_symbol__folded(&self->ms); 63 return map_symbol__folded(&self->ms);
66 } 64 }
67 65
68 static void map_symbol__set_folding(struct map_symbol *self, bool unfold) 66 static void map_symbol__set_folding(struct map_symbol *self, bool unfold)
69 { 67 {
70 self->unfolded = unfold ? self->has_children : false; 68 self->unfolded = unfold ? self->has_children : false;
71 } 69 }
72 70
73 static int callchain_node__count_rows_rb_tree(struct callchain_node *self) 71 static int callchain_node__count_rows_rb_tree(struct callchain_node *self)
74 { 72 {
75 int n = 0; 73 int n = 0;
76 struct rb_node *nd; 74 struct rb_node *nd;
77 75
78 for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) { 76 for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) {
79 struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node); 77 struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
80 struct callchain_list *chain; 78 struct callchain_list *chain;
81 char folded_sign = ' '; /* No children */ 79 char folded_sign = ' '; /* No children */
82 80
83 list_for_each_entry(chain, &child->val, list) { 81 list_for_each_entry(chain, &child->val, list) {
84 ++n; 82 ++n;
85 /* We need this because we may not have children */ 83 /* We need this because we may not have children */
86 folded_sign = callchain_list__folded(chain); 84 folded_sign = callchain_list__folded(chain);
87 if (folded_sign == '+') 85 if (folded_sign == '+')
88 break; 86 break;
89 } 87 }
90 88
91 if (folded_sign == '-') /* Have children and they're unfolded */ 89 if (folded_sign == '-') /* Have children and they're unfolded */
92 n += callchain_node__count_rows_rb_tree(child); 90 n += callchain_node__count_rows_rb_tree(child);
93 } 91 }
94 92
95 return n; 93 return n;
96 } 94 }
97 95
98 static int callchain_node__count_rows(struct callchain_node *node) 96 static int callchain_node__count_rows(struct callchain_node *node)
99 { 97 {
100 struct callchain_list *chain; 98 struct callchain_list *chain;
101 bool unfolded = false; 99 bool unfolded = false;
102 int n = 0; 100 int n = 0;
103 101
104 list_for_each_entry(chain, &node->val, list) { 102 list_for_each_entry(chain, &node->val, list) {
105 ++n; 103 ++n;
106 unfolded = chain->ms.unfolded; 104 unfolded = chain->ms.unfolded;
107 } 105 }
108 106
109 if (unfolded) 107 if (unfolded)
110 n += callchain_node__count_rows_rb_tree(node); 108 n += callchain_node__count_rows_rb_tree(node);
111 109
112 return n; 110 return n;
113 } 111 }
114 112
115 static int callchain__count_rows(struct rb_root *chain) 113 static int callchain__count_rows(struct rb_root *chain)
116 { 114 {
117 struct rb_node *nd; 115 struct rb_node *nd;
118 int n = 0; 116 int n = 0;
119 117
120 for (nd = rb_first(chain); nd; nd = rb_next(nd)) { 118 for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
121 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); 119 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
122 n += callchain_node__count_rows(node); 120 n += callchain_node__count_rows(node);
123 } 121 }
124 122
125 return n; 123 return n;
126 } 124 }
127 125
128 static bool map_symbol__toggle_fold(struct map_symbol *self) 126 static bool map_symbol__toggle_fold(struct map_symbol *self)
129 { 127 {
130 if (!self->has_children) 128 if (!self->has_children)
131 return false; 129 return false;
132 130
133 self->unfolded = !self->unfolded; 131 self->unfolded = !self->unfolded;
134 return true; 132 return true;
135 } 133 }
136 134
137 static void callchain_node__init_have_children_rb_tree(struct callchain_node *self) 135 static void callchain_node__init_have_children_rb_tree(struct callchain_node *self)
138 { 136 {
139 struct rb_node *nd = rb_first(&self->rb_root); 137 struct rb_node *nd = rb_first(&self->rb_root);
140 138
141 for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) { 139 for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) {
142 struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node); 140 struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
143 struct callchain_list *chain; 141 struct callchain_list *chain;
144 bool first = true; 142 bool first = true;
145 143
146 list_for_each_entry(chain, &child->val, list) { 144 list_for_each_entry(chain, &child->val, list) {
147 if (first) { 145 if (first) {
148 first = false; 146 first = false;
149 chain->ms.has_children = chain->list.next != &child->val || 147 chain->ms.has_children = chain->list.next != &child->val ||
150 !RB_EMPTY_ROOT(&child->rb_root); 148 !RB_EMPTY_ROOT(&child->rb_root);
151 } else 149 } else
152 chain->ms.has_children = chain->list.next == &child->val && 150 chain->ms.has_children = chain->list.next == &child->val &&
153 !RB_EMPTY_ROOT(&child->rb_root); 151 !RB_EMPTY_ROOT(&child->rb_root);
154 } 152 }
155 153
156 callchain_node__init_have_children_rb_tree(child); 154 callchain_node__init_have_children_rb_tree(child);
157 } 155 }
158 } 156 }
159 157
160 static void callchain_node__init_have_children(struct callchain_node *self) 158 static void callchain_node__init_have_children(struct callchain_node *self)
161 { 159 {
162 struct callchain_list *chain; 160 struct callchain_list *chain;
163 161
164 list_for_each_entry(chain, &self->val, list) 162 list_for_each_entry(chain, &self->val, list)
165 chain->ms.has_children = !RB_EMPTY_ROOT(&self->rb_root); 163 chain->ms.has_children = !RB_EMPTY_ROOT(&self->rb_root);
166 164
167 callchain_node__init_have_children_rb_tree(self); 165 callchain_node__init_have_children_rb_tree(self);
168 } 166 }
169 167
170 static void callchain__init_have_children(struct rb_root *self) 168 static void callchain__init_have_children(struct rb_root *self)
171 { 169 {
172 struct rb_node *nd; 170 struct rb_node *nd;
173 171
174 for (nd = rb_first(self); nd; nd = rb_next(nd)) { 172 for (nd = rb_first(self); nd; nd = rb_next(nd)) {
175 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); 173 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
176 callchain_node__init_have_children(node); 174 callchain_node__init_have_children(node);
177 } 175 }
178 } 176 }
179 177
180 static void hist_entry__init_have_children(struct hist_entry *self) 178 static void hist_entry__init_have_children(struct hist_entry *self)
181 { 179 {
182 if (!self->init_have_children) { 180 if (!self->init_have_children) {
183 self->ms.has_children = !RB_EMPTY_ROOT(&self->sorted_chain); 181 self->ms.has_children = !RB_EMPTY_ROOT(&self->sorted_chain);
184 callchain__init_have_children(&self->sorted_chain); 182 callchain__init_have_children(&self->sorted_chain);
185 self->init_have_children = true; 183 self->init_have_children = true;
186 } 184 }
187 } 185 }
188 186
189 static bool hist_browser__toggle_fold(struct hist_browser *self) 187 static bool hist_browser__toggle_fold(struct hist_browser *self)
190 { 188 {
191 if (map_symbol__toggle_fold(self->selection)) { 189 if (map_symbol__toggle_fold(self->selection)) {
192 struct hist_entry *he = self->he_selection; 190 struct hist_entry *he = self->he_selection;
193 191
194 hist_entry__init_have_children(he); 192 hist_entry__init_have_children(he);
195 self->hists->nr_entries -= he->nr_rows; 193 self->hists->nr_entries -= he->nr_rows;
196 194
197 if (he->ms.unfolded) 195 if (he->ms.unfolded)
198 he->nr_rows = callchain__count_rows(&he->sorted_chain); 196 he->nr_rows = callchain__count_rows(&he->sorted_chain);
199 else 197 else
200 he->nr_rows = 0; 198 he->nr_rows = 0;
201 self->hists->nr_entries += he->nr_rows; 199 self->hists->nr_entries += he->nr_rows;
202 self->b.nr_entries = self->hists->nr_entries; 200 self->b.nr_entries = self->hists->nr_entries;
203 201
204 return true; 202 return true;
205 } 203 }
206 204
207 /* If it doesn't have children, no toggling performed */ 205 /* If it doesn't have children, no toggling performed */
208 return false; 206 return false;
209 } 207 }
210 208
211 static int callchain_node__set_folding_rb_tree(struct callchain_node *self, bool unfold) 209 static int callchain_node__set_folding_rb_tree(struct callchain_node *self, bool unfold)
212 { 210 {
213 int n = 0; 211 int n = 0;
214 struct rb_node *nd; 212 struct rb_node *nd;
215 213
216 for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) { 214 for (nd = rb_first(&self->rb_root); nd; nd = rb_next(nd)) {
217 struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node); 215 struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
218 struct callchain_list *chain; 216 struct callchain_list *chain;
219 bool has_children = false; 217 bool has_children = false;
220 218
221 list_for_each_entry(chain, &child->val, list) { 219 list_for_each_entry(chain, &child->val, list) {
222 ++n; 220 ++n;
223 map_symbol__set_folding(&chain->ms, unfold); 221 map_symbol__set_folding(&chain->ms, unfold);
224 has_children = chain->ms.has_children; 222 has_children = chain->ms.has_children;
225 } 223 }
226 224
227 if (has_children) 225 if (has_children)
228 n += callchain_node__set_folding_rb_tree(child, unfold); 226 n += callchain_node__set_folding_rb_tree(child, unfold);
229 } 227 }
230 228
231 return n; 229 return n;
232 } 230 }
233 231
234 static int callchain_node__set_folding(struct callchain_node *node, bool unfold) 232 static int callchain_node__set_folding(struct callchain_node *node, bool unfold)
235 { 233 {
236 struct callchain_list *chain; 234 struct callchain_list *chain;
237 bool has_children = false; 235 bool has_children = false;
238 int n = 0; 236 int n = 0;
239 237
240 list_for_each_entry(chain, &node->val, list) { 238 list_for_each_entry(chain, &node->val, list) {
241 ++n; 239 ++n;
242 map_symbol__set_folding(&chain->ms, unfold); 240 map_symbol__set_folding(&chain->ms, unfold);
243 has_children = chain->ms.has_children; 241 has_children = chain->ms.has_children;
244 } 242 }
245 243
246 if (has_children) 244 if (has_children)
247 n += callchain_node__set_folding_rb_tree(node, unfold); 245 n += callchain_node__set_folding_rb_tree(node, unfold);
248 246
249 return n; 247 return n;
250 } 248 }
251 249
252 static int callchain__set_folding(struct rb_root *chain, bool unfold) 250 static int callchain__set_folding(struct rb_root *chain, bool unfold)
253 { 251 {
254 struct rb_node *nd; 252 struct rb_node *nd;
255 int n = 0; 253 int n = 0;
256 254
257 for (nd = rb_first(chain); nd; nd = rb_next(nd)) { 255 for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
258 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); 256 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
259 n += callchain_node__set_folding(node, unfold); 257 n += callchain_node__set_folding(node, unfold);
260 } 258 }
261 259
262 return n; 260 return n;
263 } 261 }
264 262
265 static void hist_entry__set_folding(struct hist_entry *self, bool unfold) 263 static void hist_entry__set_folding(struct hist_entry *self, bool unfold)
266 { 264 {
267 hist_entry__init_have_children(self); 265 hist_entry__init_have_children(self);
268 map_symbol__set_folding(&self->ms, unfold); 266 map_symbol__set_folding(&self->ms, unfold);
269 267
270 if (self->ms.has_children) { 268 if (self->ms.has_children) {
271 int n = callchain__set_folding(&self->sorted_chain, unfold); 269 int n = callchain__set_folding(&self->sorted_chain, unfold);
272 self->nr_rows = unfold ? n : 0; 270 self->nr_rows = unfold ? n : 0;
273 } else 271 } else
274 self->nr_rows = 0; 272 self->nr_rows = 0;
275 } 273 }
276 274
277 static void hists__set_folding(struct hists *self, bool unfold) 275 static void hists__set_folding(struct hists *self, bool unfold)
278 { 276 {
279 struct rb_node *nd; 277 struct rb_node *nd;
280 278
281 self->nr_entries = 0; 279 self->nr_entries = 0;
282 280
283 for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { 281 for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
284 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); 282 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
285 hist_entry__set_folding(he, unfold); 283 hist_entry__set_folding(he, unfold);
286 self->nr_entries += 1 + he->nr_rows; 284 self->nr_entries += 1 + he->nr_rows;
287 } 285 }
288 } 286 }
289 287
290 static void hist_browser__set_folding(struct hist_browser *self, bool unfold) 288 static void hist_browser__set_folding(struct hist_browser *self, bool unfold)
291 { 289 {
292 hists__set_folding(self->hists, unfold); 290 hists__set_folding(self->hists, unfold);
293 self->b.nr_entries = self->hists->nr_entries; 291 self->b.nr_entries = self->hists->nr_entries;
294 /* Go to the start, we may be way after valid entries after a collapse */ 292 /* Go to the start, we may be way after valid entries after a collapse */
295 ui_browser__reset_index(&self->b); 293 ui_browser__reset_index(&self->b);
296 } 294 }
297 295
298 static void ui_browser__warn_lost_events(struct ui_browser *browser) 296 static void ui_browser__warn_lost_events(struct ui_browser *browser)
299 { 297 {
300 ui_browser__warning(browser, 4, 298 ui_browser__warning(browser, 4,
301 "Events are being lost, check IO/CPU overload!\n\n" 299 "Events are being lost, check IO/CPU overload!\n\n"
302 "You may want to run 'perf' using a RT scheduler policy:\n\n" 300 "You may want to run 'perf' using a RT scheduler policy:\n\n"
303 " perf top -r 80\n\n" 301 " perf top -r 80\n\n"
304 "Or reduce the sampling frequency."); 302 "Or reduce the sampling frequency.");
305 } 303 }
306 304
307 static int hist_browser__run(struct hist_browser *self, const char *ev_name, 305 static int hist_browser__run(struct hist_browser *self, const char *ev_name,
308 void(*timer)(void *arg), void *arg, int delay_secs) 306 void(*timer)(void *arg), void *arg, int delay_secs)
309 { 307 {
310 int key; 308 int key;
311 char title[160]; 309 char title[160];
312 310
313 self->b.entries = &self->hists->entries; 311 self->b.entries = &self->hists->entries;
314 self->b.nr_entries = self->hists->nr_entries; 312 self->b.nr_entries = self->hists->nr_entries;
315 313
316 hist_browser__refresh_dimensions(self); 314 hist_browser__refresh_dimensions(self);
317 hists__browser_title(self->hists, title, sizeof(title), ev_name); 315 hists__browser_title(self->hists, title, sizeof(title), ev_name);
318 316
319 if (ui_browser__show(&self->b, title, 317 if (ui_browser__show(&self->b, title,
320 "Press '?' for help on key bindings") < 0) 318 "Press '?' for help on key bindings") < 0)
321 return -1; 319 return -1;
322 320
323 while (1) { 321 while (1) {
324 key = ui_browser__run(&self->b, delay_secs); 322 key = ui_browser__run(&self->b, delay_secs);
325 323
326 switch (key) { 324 switch (key) {
327 case K_TIMER: 325 case K_TIMER:
328 timer(arg); 326 timer(arg);
329 ui_browser__update_nr_entries(&self->b, self->hists->nr_entries); 327 ui_browser__update_nr_entries(&self->b, self->hists->nr_entries);
330 328
331 if (self->hists->stats.nr_lost_warned != 329 if (self->hists->stats.nr_lost_warned !=
332 self->hists->stats.nr_events[PERF_RECORD_LOST]) { 330 self->hists->stats.nr_events[PERF_RECORD_LOST]) {
333 self->hists->stats.nr_lost_warned = 331 self->hists->stats.nr_lost_warned =
334 self->hists->stats.nr_events[PERF_RECORD_LOST]; 332 self->hists->stats.nr_events[PERF_RECORD_LOST];
335 ui_browser__warn_lost_events(&self->b); 333 ui_browser__warn_lost_events(&self->b);
336 } 334 }
337 335
338 hists__browser_title(self->hists, title, sizeof(title), ev_name); 336 hists__browser_title(self->hists, title, sizeof(title), ev_name);
339 ui_browser__show_title(&self->b, title); 337 ui_browser__show_title(&self->b, title);
340 continue; 338 continue;
341 case 'D': { /* Debug */ 339 case 'D': { /* Debug */
342 static int seq; 340 static int seq;
343 struct hist_entry *h = rb_entry(self->b.top, 341 struct hist_entry *h = rb_entry(self->b.top,
344 struct hist_entry, rb_node); 342 struct hist_entry, rb_node);
345 ui_helpline__pop(); 343 ui_helpline__pop();
346 ui_helpline__fpush("%d: nr_ent=(%d,%d), height=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", 344 ui_helpline__fpush("%d: nr_ent=(%d,%d), height=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
347 seq++, self->b.nr_entries, 345 seq++, self->b.nr_entries,
348 self->hists->nr_entries, 346 self->hists->nr_entries,
349 self->b.height, 347 self->b.height,
350 self->b.index, 348 self->b.index,
351 self->b.top_idx, 349 self->b.top_idx,
352 h->row_offset, h->nr_rows); 350 h->row_offset, h->nr_rows);
353 } 351 }
354 break; 352 break;
355 case 'C': 353 case 'C':
356 /* Collapse the whole world. */ 354 /* Collapse the whole world. */
357 hist_browser__set_folding(self, false); 355 hist_browser__set_folding(self, false);
358 break; 356 break;
359 case 'E': 357 case 'E':
360 /* Expand the whole world. */ 358 /* Expand the whole world. */
361 hist_browser__set_folding(self, true); 359 hist_browser__set_folding(self, true);
362 break; 360 break;
363 case K_ENTER: 361 case K_ENTER:
364 if (hist_browser__toggle_fold(self)) 362 if (hist_browser__toggle_fold(self))
365 break; 363 break;
366 /* fall thru */ 364 /* fall thru */
367 default: 365 default:
368 goto out; 366 goto out;
369 } 367 }
370 } 368 }
371 out: 369 out:
372 ui_browser__hide(&self->b); 370 ui_browser__hide(&self->b);
373 return key; 371 return key;
374 } 372 }
375 373
376 static char *callchain_list__sym_name(struct callchain_list *self, 374 static char *callchain_list__sym_name(struct callchain_list *self,
377 char *bf, size_t bfsize) 375 char *bf, size_t bfsize)
378 { 376 {
379 if (self->ms.sym) 377 if (self->ms.sym)
380 return self->ms.sym->name; 378 return self->ms.sym->name;
381 379
382 snprintf(bf, bfsize, "%#" PRIx64, self->ip); 380 snprintf(bf, bfsize, "%#" PRIx64, self->ip);
383 return bf; 381 return bf;
384 } 382 }
385 383
386 #define LEVEL_OFFSET_STEP 3 384 #define LEVEL_OFFSET_STEP 3
387 385
388 static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *self, 386 static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *self,
389 struct callchain_node *chain_node, 387 struct callchain_node *chain_node,
390 u64 total, int level, 388 u64 total, int level,
391 unsigned short row, 389 unsigned short row,
392 off_t *row_offset, 390 off_t *row_offset,
393 bool *is_current_entry) 391 bool *is_current_entry)
394 { 392 {
395 struct rb_node *node; 393 struct rb_node *node;
396 int first_row = row, width, offset = level * LEVEL_OFFSET_STEP; 394 int first_row = row, width, offset = level * LEVEL_OFFSET_STEP;
397 u64 new_total, remaining; 395 u64 new_total, remaining;
398 396
399 if (callchain_param.mode == CHAIN_GRAPH_REL) 397 if (callchain_param.mode == CHAIN_GRAPH_REL)
400 new_total = chain_node->children_hit; 398 new_total = chain_node->children_hit;
401 else 399 else
402 new_total = total; 400 new_total = total;
403 401
404 remaining = new_total; 402 remaining = new_total;
405 node = rb_first(&chain_node->rb_root); 403 node = rb_first(&chain_node->rb_root);
406 while (node) { 404 while (node) {
407 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); 405 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
408 struct rb_node *next = rb_next(node); 406 struct rb_node *next = rb_next(node);
409 u64 cumul = callchain_cumul_hits(child); 407 u64 cumul = callchain_cumul_hits(child);
410 struct callchain_list *chain; 408 struct callchain_list *chain;
411 char folded_sign = ' '; 409 char folded_sign = ' ';
412 int first = true; 410 int first = true;
413 int extra_offset = 0; 411 int extra_offset = 0;
414 412
415 remaining -= cumul; 413 remaining -= cumul;
416 414
417 list_for_each_entry(chain, &child->val, list) { 415 list_for_each_entry(chain, &child->val, list) {
418 char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str; 416 char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str;
419 const char *str; 417 const char *str;
420 int color; 418 int color;
421 bool was_first = first; 419 bool was_first = first;
422 420
423 if (first) 421 if (first)
424 first = false; 422 first = false;
425 else 423 else
426 extra_offset = LEVEL_OFFSET_STEP; 424 extra_offset = LEVEL_OFFSET_STEP;
427 425
428 folded_sign = callchain_list__folded(chain); 426 folded_sign = callchain_list__folded(chain);
429 if (*row_offset != 0) { 427 if (*row_offset != 0) {
430 --*row_offset; 428 --*row_offset;
431 goto do_next; 429 goto do_next;
432 } 430 }
433 431
434 alloc_str = NULL; 432 alloc_str = NULL;
435 str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); 433 str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
436 if (was_first) { 434 if (was_first) {
437 double percent = cumul * 100.0 / new_total; 435 double percent = cumul * 100.0 / new_total;
438 436
439 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0) 437 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
440 str = "Not enough memory!"; 438 str = "Not enough memory!";
441 else 439 else
442 str = alloc_str; 440 str = alloc_str;
443 } 441 }
444 442
445 color = HE_COLORSET_NORMAL; 443 color = HE_COLORSET_NORMAL;
446 width = self->b.width - (offset + extra_offset + 2); 444 width = self->b.width - (offset + extra_offset + 2);
447 if (ui_browser__is_current_entry(&self->b, row)) { 445 if (ui_browser__is_current_entry(&self->b, row)) {
448 self->selection = &chain->ms; 446 self->selection = &chain->ms;
449 color = HE_COLORSET_SELECTED; 447 color = HE_COLORSET_SELECTED;
450 *is_current_entry = true; 448 *is_current_entry = true;
451 } 449 }
452 450
453 ui_browser__set_color(&self->b, color); 451 ui_browser__set_color(&self->b, color);
454 ui_browser__gotorc(&self->b, row, 0); 452 ui_browser__gotorc(&self->b, row, 0);
455 slsmg_write_nstring(" ", offset + extra_offset); 453 slsmg_write_nstring(" ", offset + extra_offset);
456 slsmg_printf("%c ", folded_sign); 454 slsmg_printf("%c ", folded_sign);
457 slsmg_write_nstring(str, width); 455 slsmg_write_nstring(str, width);
458 free(alloc_str); 456 free(alloc_str);
459 457
460 if (++row == self->b.height) 458 if (++row == self->b.height)
461 goto out; 459 goto out;
462 do_next: 460 do_next:
463 if (folded_sign == '+') 461 if (folded_sign == '+')
464 break; 462 break;
465 } 463 }
466 464
467 if (folded_sign == '-') { 465 if (folded_sign == '-') {
468 const int new_level = level + (extra_offset ? 2 : 1); 466 const int new_level = level + (extra_offset ? 2 : 1);
469 row += hist_browser__show_callchain_node_rb_tree(self, child, new_total, 467 row += hist_browser__show_callchain_node_rb_tree(self, child, new_total,
470 new_level, row, row_offset, 468 new_level, row, row_offset,
471 is_current_entry); 469 is_current_entry);
472 } 470 }
473 if (row == self->b.height) 471 if (row == self->b.height)
474 goto out; 472 goto out;
475 node = next; 473 node = next;
476 } 474 }
477 out: 475 out:
478 return row - first_row; 476 return row - first_row;
479 } 477 }
480 478
481 static int hist_browser__show_callchain_node(struct hist_browser *self, 479 static int hist_browser__show_callchain_node(struct hist_browser *self,
482 struct callchain_node *node, 480 struct callchain_node *node,
483 int level, unsigned short row, 481 int level, unsigned short row,
484 off_t *row_offset, 482 off_t *row_offset,
485 bool *is_current_entry) 483 bool *is_current_entry)
486 { 484 {
487 struct callchain_list *chain; 485 struct callchain_list *chain;
488 int first_row = row, 486 int first_row = row,
489 offset = level * LEVEL_OFFSET_STEP, 487 offset = level * LEVEL_OFFSET_STEP,
490 width = self->b.width - offset; 488 width = self->b.width - offset;
491 char folded_sign = ' '; 489 char folded_sign = ' ';
492 490
493 list_for_each_entry(chain, &node->val, list) { 491 list_for_each_entry(chain, &node->val, list) {
494 char ipstr[BITS_PER_LONG / 4 + 1], *s; 492 char ipstr[BITS_PER_LONG / 4 + 1], *s;
495 int color; 493 int color;
496 494
497 folded_sign = callchain_list__folded(chain); 495 folded_sign = callchain_list__folded(chain);
498 496
499 if (*row_offset != 0) { 497 if (*row_offset != 0) {
500 --*row_offset; 498 --*row_offset;
501 continue; 499 continue;
502 } 500 }
503 501
504 color = HE_COLORSET_NORMAL; 502 color = HE_COLORSET_NORMAL;
505 if (ui_browser__is_current_entry(&self->b, row)) { 503 if (ui_browser__is_current_entry(&self->b, row)) {
506 self->selection = &chain->ms; 504 self->selection = &chain->ms;
507 color = HE_COLORSET_SELECTED; 505 color = HE_COLORSET_SELECTED;
508 *is_current_entry = true; 506 *is_current_entry = true;
509 } 507 }
510 508
511 s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); 509 s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
512 ui_browser__gotorc(&self->b, row, 0); 510 ui_browser__gotorc(&self->b, row, 0);
513 ui_browser__set_color(&self->b, color); 511 ui_browser__set_color(&self->b, color);
514 slsmg_write_nstring(" ", offset); 512 slsmg_write_nstring(" ", offset);
515 slsmg_printf("%c ", folded_sign); 513 slsmg_printf("%c ", folded_sign);
516 slsmg_write_nstring(s, width - 2); 514 slsmg_write_nstring(s, width - 2);
517 515
518 if (++row == self->b.height) 516 if (++row == self->b.height)
519 goto out; 517 goto out;
520 } 518 }
521 519
522 if (folded_sign == '-') 520 if (folded_sign == '-')
523 row += hist_browser__show_callchain_node_rb_tree(self, node, 521 row += hist_browser__show_callchain_node_rb_tree(self, node,
524 self->hists->stats.total_period, 522 self->hists->stats.total_period,
525 level + 1, row, 523 level + 1, row,
526 row_offset, 524 row_offset,
527 is_current_entry); 525 is_current_entry);
528 out: 526 out:
529 return row - first_row; 527 return row - first_row;
530 } 528 }
531 529
532 static int hist_browser__show_callchain(struct hist_browser *self, 530 static int hist_browser__show_callchain(struct hist_browser *self,
533 struct rb_root *chain, 531 struct rb_root *chain,
534 int level, unsigned short row, 532 int level, unsigned short row,
535 off_t *row_offset, 533 off_t *row_offset,
536 bool *is_current_entry) 534 bool *is_current_entry)
537 { 535 {
538 struct rb_node *nd; 536 struct rb_node *nd;
539 int first_row = row; 537 int first_row = row;
540 538
541 for (nd = rb_first(chain); nd; nd = rb_next(nd)) { 539 for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
542 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); 540 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
543 541
544 row += hist_browser__show_callchain_node(self, node, level, 542 row += hist_browser__show_callchain_node(self, node, level,
545 row, row_offset, 543 row, row_offset,
546 is_current_entry); 544 is_current_entry);
547 if (row == self->b.height) 545 if (row == self->b.height)
548 break; 546 break;
549 } 547 }
550 548
551 return row - first_row; 549 return row - first_row;
552 } 550 }
553 551
554 static int hist_browser__show_entry(struct hist_browser *self, 552 static int hist_browser__show_entry(struct hist_browser *self,
555 struct hist_entry *entry, 553 struct hist_entry *entry,
556 unsigned short row) 554 unsigned short row)
557 { 555 {
558 char s[256]; 556 char s[256];
559 double percent; 557 double percent;
560 int printed = 0; 558 int printed = 0;
561 int width = self->b.width - 6; /* The percentage */ 559 int width = self->b.width - 6; /* The percentage */
562 char folded_sign = ' '; 560 char folded_sign = ' ';
563 bool current_entry = ui_browser__is_current_entry(&self->b, row); 561 bool current_entry = ui_browser__is_current_entry(&self->b, row);
564 off_t row_offset = entry->row_offset; 562 off_t row_offset = entry->row_offset;
565 563
566 if (current_entry) { 564 if (current_entry) {
567 self->he_selection = entry; 565 self->he_selection = entry;
568 self->selection = &entry->ms; 566 self->selection = &entry->ms;
569 } 567 }
570 568
571 if (symbol_conf.use_callchain) { 569 if (symbol_conf.use_callchain) {
572 hist_entry__init_have_children(entry); 570 hist_entry__init_have_children(entry);
573 folded_sign = hist_entry__folded(entry); 571 folded_sign = hist_entry__folded(entry);
574 } 572 }
575 573
576 if (row_offset == 0) { 574 if (row_offset == 0) {
577 hist_entry__snprintf(entry, s, sizeof(s), self->hists); 575 hist_entry__snprintf(entry, s, sizeof(s), self->hists);
578 percent = (entry->period * 100.0) / self->hists->stats.total_period; 576 percent = (entry->period * 100.0) / self->hists->stats.total_period;
579 577
580 ui_browser__set_percent_color(&self->b, percent, current_entry); 578 ui_browser__set_percent_color(&self->b, percent, current_entry);
581 ui_browser__gotorc(&self->b, row, 0); 579 ui_browser__gotorc(&self->b, row, 0);
582 if (symbol_conf.use_callchain) { 580 if (symbol_conf.use_callchain) {
583 slsmg_printf("%c ", folded_sign); 581 slsmg_printf("%c ", folded_sign);
584 width -= 2; 582 width -= 2;
585 } 583 }
586 584
587 slsmg_printf(" %5.2f%%", percent); 585 slsmg_printf(" %5.2f%%", percent);
588 586
589 /* The scroll bar isn't being used */ 587 /* The scroll bar isn't being used */
590 if (!self->b.navkeypressed) 588 if (!self->b.navkeypressed)
591 width += 1; 589 width += 1;
592 590
593 if (!current_entry || !self->b.navkeypressed) 591 if (!current_entry || !self->b.navkeypressed)
594 ui_browser__set_color(&self->b, HE_COLORSET_NORMAL); 592 ui_browser__set_color(&self->b, HE_COLORSET_NORMAL);
595 593
596 if (symbol_conf.show_nr_samples) { 594 if (symbol_conf.show_nr_samples) {
597 slsmg_printf(" %11u", entry->nr_events); 595 slsmg_printf(" %11u", entry->nr_events);
598 width -= 12; 596 width -= 12;
599 } 597 }
600 598
601 if (symbol_conf.show_total_period) { 599 if (symbol_conf.show_total_period) {
602 slsmg_printf(" %12" PRIu64, entry->period); 600 slsmg_printf(" %12" PRIu64, entry->period);
603 width -= 13; 601 width -= 13;
604 } 602 }
605 603
606 slsmg_write_nstring(s, width); 604 slsmg_write_nstring(s, width);
607 ++row; 605 ++row;
608 ++printed; 606 ++printed;
609 } else 607 } else
610 --row_offset; 608 --row_offset;
611 609
612 if (folded_sign == '-' && row != self->b.height) { 610 if (folded_sign == '-' && row != self->b.height) {
613 printed += hist_browser__show_callchain(self, &entry->sorted_chain, 611 printed += hist_browser__show_callchain(self, &entry->sorted_chain,
614 1, row, &row_offset, 612 1, row, &row_offset,
615 &current_entry); 613 &current_entry);
616 if (current_entry) 614 if (current_entry)
617 self->he_selection = entry; 615 self->he_selection = entry;
618 } 616 }
619 617
620 return printed; 618 return printed;
621 } 619 }
622 620
623 static void ui_browser__hists_init_top(struct ui_browser *browser) 621 static void ui_browser__hists_init_top(struct ui_browser *browser)
624 { 622 {
625 if (browser->top == NULL) { 623 if (browser->top == NULL) {
626 struct hist_browser *hb; 624 struct hist_browser *hb;
627 625
628 hb = container_of(browser, struct hist_browser, b); 626 hb = container_of(browser, struct hist_browser, b);
629 browser->top = rb_first(&hb->hists->entries); 627 browser->top = rb_first(&hb->hists->entries);
630 } 628 }
631 } 629 }
632 630
633 static unsigned int hist_browser__refresh(struct ui_browser *self) 631 static unsigned int hist_browser__refresh(struct ui_browser *self)
634 { 632 {
635 unsigned row = 0; 633 unsigned row = 0;
636 struct rb_node *nd; 634 struct rb_node *nd;
637 struct hist_browser *hb = container_of(self, struct hist_browser, b); 635 struct hist_browser *hb = container_of(self, struct hist_browser, b);
638 636
639 ui_browser__hists_init_top(self); 637 ui_browser__hists_init_top(self);
640 638
641 for (nd = self->top; nd; nd = rb_next(nd)) { 639 for (nd = self->top; nd; nd = rb_next(nd)) {
642 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 640 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
643 641
644 if (h->filtered) 642 if (h->filtered)
645 continue; 643 continue;
646 644
647 row += hist_browser__show_entry(hb, h, row); 645 row += hist_browser__show_entry(hb, h, row);
648 if (row == self->height) 646 if (row == self->height)
649 break; 647 break;
650 } 648 }
651 649
652 return row; 650 return row;
653 } 651 }
654 652
655 static struct rb_node *hists__filter_entries(struct rb_node *nd) 653 static struct rb_node *hists__filter_entries(struct rb_node *nd)
656 { 654 {
657 while (nd != NULL) { 655 while (nd != NULL) {
658 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 656 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
659 if (!h->filtered) 657 if (!h->filtered)
660 return nd; 658 return nd;
661 659
662 nd = rb_next(nd); 660 nd = rb_next(nd);
663 } 661 }
664 662
665 return NULL; 663 return NULL;
666 } 664 }
667 665
668 static struct rb_node *hists__filter_prev_entries(struct rb_node *nd) 666 static struct rb_node *hists__filter_prev_entries(struct rb_node *nd)
669 { 667 {
670 while (nd != NULL) { 668 while (nd != NULL) {
671 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 669 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
672 if (!h->filtered) 670 if (!h->filtered)
673 return nd; 671 return nd;
674 672
675 nd = rb_prev(nd); 673 nd = rb_prev(nd);
676 } 674 }
677 675
678 return NULL; 676 return NULL;
679 } 677 }
680 678
681 static void ui_browser__hists_seek(struct ui_browser *self, 679 static void ui_browser__hists_seek(struct ui_browser *self,
682 off_t offset, int whence) 680 off_t offset, int whence)
683 { 681 {
684 struct hist_entry *h; 682 struct hist_entry *h;
685 struct rb_node *nd; 683 struct rb_node *nd;
686 bool first = true; 684 bool first = true;
687 685
688 if (self->nr_entries == 0) 686 if (self->nr_entries == 0)
689 return; 687 return;
690 688
691 ui_browser__hists_init_top(self); 689 ui_browser__hists_init_top(self);
692 690
693 switch (whence) { 691 switch (whence) {
694 case SEEK_SET: 692 case SEEK_SET:
695 nd = hists__filter_entries(rb_first(self->entries)); 693 nd = hists__filter_entries(rb_first(self->entries));
696 break; 694 break;
697 case SEEK_CUR: 695 case SEEK_CUR:
698 nd = self->top; 696 nd = self->top;
699 goto do_offset; 697 goto do_offset;
700 case SEEK_END: 698 case SEEK_END:
701 nd = hists__filter_prev_entries(rb_last(self->entries)); 699 nd = hists__filter_prev_entries(rb_last(self->entries));
702 first = false; 700 first = false;
703 break; 701 break;
704 default: 702 default:
705 return; 703 return;
706 } 704 }
707 705
708 /* 706 /*
709 * Moves not relative to the first visible entry invalidates its 707 * Moves not relative to the first visible entry invalidates its
710 * row_offset: 708 * row_offset:
711 */ 709 */
712 h = rb_entry(self->top, struct hist_entry, rb_node); 710 h = rb_entry(self->top, struct hist_entry, rb_node);
713 h->row_offset = 0; 711 h->row_offset = 0;
714 712
715 /* 713 /*
716 * Here we have to check if nd is expanded (+), if it is we can't go 714 * Here we have to check if nd is expanded (+), if it is we can't go
717 * the next top level hist_entry, instead we must compute an offset of 715 * the next top level hist_entry, instead we must compute an offset of
718 * what _not_ to show and not change the first visible entry. 716 * what _not_ to show and not change the first visible entry.
719 * 717 *
720 * This offset increments when we are going from top to bottom and 718 * This offset increments when we are going from top to bottom and
721 * decreases when we're going from bottom to top. 719 * decreases when we're going from bottom to top.
722 * 720 *
723 * As we don't have backpointers to the top level in the callchains 721 * As we don't have backpointers to the top level in the callchains
724 * structure, we need to always print the whole hist_entry callchain, 722 * structure, we need to always print the whole hist_entry callchain,
725 * skipping the first ones that are before the first visible entry 723 * skipping the first ones that are before the first visible entry
726 * and stop when we printed enough lines to fill the screen. 724 * and stop when we printed enough lines to fill the screen.
727 */ 725 */
728 do_offset: 726 do_offset:
729 if (offset > 0) { 727 if (offset > 0) {
730 do { 728 do {
731 h = rb_entry(nd, struct hist_entry, rb_node); 729 h = rb_entry(nd, struct hist_entry, rb_node);
732 if (h->ms.unfolded) { 730 if (h->ms.unfolded) {
733 u16 remaining = h->nr_rows - h->row_offset; 731 u16 remaining = h->nr_rows - h->row_offset;
734 if (offset > remaining) { 732 if (offset > remaining) {
735 offset -= remaining; 733 offset -= remaining;
736 h->row_offset = 0; 734 h->row_offset = 0;
737 } else { 735 } else {
738 h->row_offset += offset; 736 h->row_offset += offset;
739 offset = 0; 737 offset = 0;
740 self->top = nd; 738 self->top = nd;
741 break; 739 break;
742 } 740 }
743 } 741 }
744 nd = hists__filter_entries(rb_next(nd)); 742 nd = hists__filter_entries(rb_next(nd));
745 if (nd == NULL) 743 if (nd == NULL)
746 break; 744 break;
747 --offset; 745 --offset;
748 self->top = nd; 746 self->top = nd;
749 } while (offset != 0); 747 } while (offset != 0);
750 } else if (offset < 0) { 748 } else if (offset < 0) {
751 while (1) { 749 while (1) {
752 h = rb_entry(nd, struct hist_entry, rb_node); 750 h = rb_entry(nd, struct hist_entry, rb_node);
753 if (h->ms.unfolded) { 751 if (h->ms.unfolded) {
754 if (first) { 752 if (first) {
755 if (-offset > h->row_offset) { 753 if (-offset > h->row_offset) {
756 offset += h->row_offset; 754 offset += h->row_offset;
757 h->row_offset = 0; 755 h->row_offset = 0;
758 } else { 756 } else {
759 h->row_offset += offset; 757 h->row_offset += offset;
760 offset = 0; 758 offset = 0;
761 self->top = nd; 759 self->top = nd;
762 break; 760 break;
763 } 761 }
764 } else { 762 } else {
765 if (-offset > h->nr_rows) { 763 if (-offset > h->nr_rows) {
766 offset += h->nr_rows; 764 offset += h->nr_rows;
767 h->row_offset = 0; 765 h->row_offset = 0;
768 } else { 766 } else {
769 h->row_offset = h->nr_rows + offset; 767 h->row_offset = h->nr_rows + offset;
770 offset = 0; 768 offset = 0;
771 self->top = nd; 769 self->top = nd;
772 break; 770 break;
773 } 771 }
774 } 772 }
775 } 773 }
776 774
777 nd = hists__filter_prev_entries(rb_prev(nd)); 775 nd = hists__filter_prev_entries(rb_prev(nd));
778 if (nd == NULL) 776 if (nd == NULL)
779 break; 777 break;
780 ++offset; 778 ++offset;
781 self->top = nd; 779 self->top = nd;
782 if (offset == 0) { 780 if (offset == 0) {
783 /* 781 /*
784 * Last unfiltered hist_entry, check if it is 782 * Last unfiltered hist_entry, check if it is
785 * unfolded, if it is then we should have 783 * unfolded, if it is then we should have
786 * row_offset at its last entry. 784 * row_offset at its last entry.
787 */ 785 */
788 h = rb_entry(nd, struct hist_entry, rb_node); 786 h = rb_entry(nd, struct hist_entry, rb_node);
789 if (h->ms.unfolded) 787 if (h->ms.unfolded)
790 h->row_offset = h->nr_rows; 788 h->row_offset = h->nr_rows;
791 break; 789 break;
792 } 790 }
793 first = false; 791 first = false;
794 } 792 }
795 } else { 793 } else {
796 self->top = nd; 794 self->top = nd;
797 h = rb_entry(nd, struct hist_entry, rb_node); 795 h = rb_entry(nd, struct hist_entry, rb_node);
798 h->row_offset = 0; 796 h->row_offset = 0;
799 } 797 }
800 } 798 }
801 799
802 static struct hist_browser *hist_browser__new(struct hists *hists) 800 static struct hist_browser *hist_browser__new(struct hists *hists)
803 { 801 {
804 struct hist_browser *self = zalloc(sizeof(*self)); 802 struct hist_browser *self = zalloc(sizeof(*self));
805 803
806 if (self) { 804 if (self) {
807 self->hists = hists; 805 self->hists = hists;
808 self->b.refresh = hist_browser__refresh; 806 self->b.refresh = hist_browser__refresh;
809 self->b.seek = ui_browser__hists_seek; 807 self->b.seek = ui_browser__hists_seek;
810 self->b.use_navkeypressed = true, 808 self->b.use_navkeypressed = true,
811 self->has_symbols = sort_sym.list.next != NULL; 809 self->has_symbols = sort_sym.list.next != NULL;
812 } 810 }
813 811
814 return self; 812 return self;
815 } 813 }
816 814
817 static void hist_browser__delete(struct hist_browser *self) 815 static void hist_browser__delete(struct hist_browser *self)
818 { 816 {
819 free(self); 817 free(self);
820 } 818 }
821 819
822 static struct hist_entry *hist_browser__selected_entry(struct hist_browser *self) 820 static struct hist_entry *hist_browser__selected_entry(struct hist_browser *self)
823 { 821 {
824 return self->he_selection; 822 return self->he_selection;
825 } 823 }
826 824
827 static struct thread *hist_browser__selected_thread(struct hist_browser *self) 825 static struct thread *hist_browser__selected_thread(struct hist_browser *self)
828 { 826 {
829 return self->he_selection->thread; 827 return self->he_selection->thread;
830 } 828 }
831 829
832 static int hists__browser_title(struct hists *self, char *bf, size_t size, 830 static int hists__browser_title(struct hists *self, char *bf, size_t size,
833 const char *ev_name) 831 const char *ev_name)
834 { 832 {
835 char unit; 833 char unit;
836 int printed; 834 int printed;
837 const struct dso *dso = self->dso_filter; 835 const struct dso *dso = self->dso_filter;
838 const struct thread *thread = self->thread_filter; 836 const struct thread *thread = self->thread_filter;
839 unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE]; 837 unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE];
840 838
841 nr_events = convert_unit(nr_events, &unit); 839 nr_events = convert_unit(nr_events, &unit);
842 printed = snprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name); 840 printed = snprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name);
843 841
844 if (thread) 842 if (thread)
845 printed += snprintf(bf + printed, size - printed, 843 printed += snprintf(bf + printed, size - printed,
846 ", Thread: %s(%d)", 844 ", Thread: %s(%d)",
847 (thread->comm_set ? thread->comm : ""), 845 (thread->comm_set ? thread->comm : ""),
848 thread->pid); 846 thread->pid);
849 if (dso) 847 if (dso)
850 printed += snprintf(bf + printed, size - printed, 848 printed += snprintf(bf + printed, size - printed,
851 ", DSO: %s", dso->short_name); 849 ", DSO: %s", dso->short_name);
852 return printed; 850 return printed;
853 } 851 }
854 852
855 static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, 853 static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
856 const char *helpline, const char *ev_name, 854 const char *helpline, const char *ev_name,
857 bool left_exits, 855 bool left_exits,
858 void(*timer)(void *arg), void *arg, 856 void(*timer)(void *arg), void *arg,
859 int delay_secs) 857 int delay_secs)
860 { 858 {
861 struct hists *self = &evsel->hists; 859 struct hists *self = &evsel->hists;
862 struct hist_browser *browser = hist_browser__new(self); 860 struct hist_browser *browser = hist_browser__new(self);
863 struct pstack *fstack; 861 struct pstack *fstack;
864 int key = -1; 862 int key = -1;
865 863
866 if (browser == NULL) 864 if (browser == NULL)
867 return -1; 865 return -1;
868 866
869 fstack = pstack__new(2); 867 fstack = pstack__new(2);
870 if (fstack == NULL) 868 if (fstack == NULL)
871 goto out; 869 goto out;
872 870
873 ui_helpline__push(helpline); 871 ui_helpline__push(helpline);
874 872
875 while (1) { 873 while (1) {
876 const struct thread *thread = NULL; 874 const struct thread *thread = NULL;
877 const struct dso *dso = NULL; 875 const struct dso *dso = NULL;
878 char *options[16]; 876 char *options[16];
879 int nr_options = 0, choice = 0, i, 877 int nr_options = 0, choice = 0, i,
880 annotate = -2, zoom_dso = -2, zoom_thread = -2, 878 annotate = -2, zoom_dso = -2, zoom_thread = -2,
881 browse_map = -2; 879 browse_map = -2;
882 880
883 key = hist_browser__run(browser, ev_name, timer, arg, delay_secs); 881 key = hist_browser__run(browser, ev_name, timer, arg, delay_secs);
884 882
885 if (browser->he_selection != NULL) { 883 if (browser->he_selection != NULL) {
886 thread = hist_browser__selected_thread(browser); 884 thread = hist_browser__selected_thread(browser);
887 dso = browser->selection->map ? browser->selection->map->dso : NULL; 885 dso = browser->selection->map ? browser->selection->map->dso : NULL;
888 } 886 }
889 887
890 switch (key) { 888 switch (key) {
891 case K_TAB: 889 case K_TAB:
892 case K_UNTAB: 890 case K_UNTAB:
893 if (nr_events == 1) 891 if (nr_events == 1)
894 continue; 892 continue;
895 /* 893 /*
896 * Exit the browser, let hists__browser_tree 894 * Exit the browser, let hists__browser_tree
897 * go to the next or previous 895 * go to the next or previous
898 */ 896 */
899 goto out_free_stack; 897 goto out_free_stack;
900 case 'a': 898 case 'a':
901 if (!browser->has_symbols) { 899 if (!browser->has_symbols) {
902 ui_browser__warning(&browser->b, delay_secs * 2, 900 ui_browser__warning(&browser->b, delay_secs * 2,
903 "Annotation is only available for symbolic views, " 901 "Annotation is only available for symbolic views, "
904 "include \"sym\" in --sort to use it."); 902 "include \"sym\" in --sort to use it.");
905 continue; 903 continue;
906 } 904 }
907 905
908 if (browser->selection == NULL || 906 if (browser->selection == NULL ||
909 browser->selection->sym == NULL || 907 browser->selection->sym == NULL ||
910 browser->selection->map->dso->annotate_warned) 908 browser->selection->map->dso->annotate_warned)
911 continue; 909 continue;
912 goto do_annotate; 910 goto do_annotate;
913 case 'd': 911 case 'd':
914 goto zoom_dso; 912 goto zoom_dso;
915 case 't': 913 case 't':
916 goto zoom_thread; 914 goto zoom_thread;
917 case K_F1: 915 case K_F1:
918 case 'h': 916 case 'h':
919 case '?': 917 case '?':
920 ui_browser__help_window(&browser->b, 918 ui_browser__help_window(&browser->b,
921 "h/?/F1 Show this window\n" 919 "h/?/F1 Show this window\n"
922 "UP/DOWN/PGUP\n" 920 "UP/DOWN/PGUP\n"
923 "PGDN/SPACE Navigate\n" 921 "PGDN/SPACE Navigate\n"
924 "q/ESC/CTRL+C Exit browser\n\n" 922 "q/ESC/CTRL+C Exit browser\n\n"
925 "For multiple event sessions:\n\n" 923 "For multiple event sessions:\n\n"
926 "TAB/UNTAB Switch events\n\n" 924 "TAB/UNTAB Switch events\n\n"
927 "For symbolic views (--sort has sym):\n\n" 925 "For symbolic views (--sort has sym):\n\n"
928 "-> Zoom into DSO/Threads & Annotate current symbol\n" 926 "-> Zoom into DSO/Threads & Annotate current symbol\n"
929 "<- Zoom out\n" 927 "<- Zoom out\n"
930 "a Annotate current symbol\n" 928 "a Annotate current symbol\n"
931 "C Collapse all callchains\n" 929 "C Collapse all callchains\n"
932 "E Expand all callchains\n" 930 "E Expand all callchains\n"
933 "d Zoom into current DSO\n" 931 "d Zoom into current DSO\n"
934 "t Zoom into current Thread"); 932 "t Zoom into current Thread");
935 continue; 933 continue;
936 case K_ENTER: 934 case K_ENTER:
937 case K_RIGHT: 935 case K_RIGHT:
938 /* menu */ 936 /* menu */
939 break; 937 break;
940 case K_LEFT: { 938 case K_LEFT: {
941 const void *top; 939 const void *top;
942 940
943 if (pstack__empty(fstack)) { 941 if (pstack__empty(fstack)) {
944 /* 942 /*
945 * Go back to the perf_evsel_menu__run or other user 943 * Go back to the perf_evsel_menu__run or other user
946 */ 944 */
947 if (left_exits) 945 if (left_exits)
948 goto out_free_stack; 946 goto out_free_stack;
949 continue; 947 continue;
950 } 948 }
951 top = pstack__pop(fstack); 949 top = pstack__pop(fstack);
952 if (top == &browser->hists->dso_filter) 950 if (top == &browser->hists->dso_filter)
953 goto zoom_out_dso; 951 goto zoom_out_dso;
954 if (top == &browser->hists->thread_filter) 952 if (top == &browser->hists->thread_filter)
955 goto zoom_out_thread; 953 goto zoom_out_thread;
956 continue; 954 continue;
957 } 955 }
958 case K_ESC: 956 case K_ESC:
959 if (!left_exits && 957 if (!left_exits &&
960 !ui_browser__dialog_yesno(&browser->b, 958 !ui_browser__dialog_yesno(&browser->b,
961 "Do you really want to exit?")) 959 "Do you really want to exit?"))
962 continue; 960 continue;
963 /* Fall thru */ 961 /* Fall thru */
964 case 'q': 962 case 'q':
965 case CTRL('c'): 963 case CTRL('c'):
966 goto out_free_stack; 964 goto out_free_stack;
967 default: 965 default:
968 continue; 966 continue;
969 } 967 }
970 968
971 if (!browser->has_symbols) 969 if (!browser->has_symbols)
972 goto add_exit_option; 970 goto add_exit_option;
973 971
974 if (browser->selection != NULL && 972 if (browser->selection != NULL &&
975 browser->selection->sym != NULL && 973 browser->selection->sym != NULL &&
976 !browser->selection->map->dso->annotate_warned && 974 !browser->selection->map->dso->annotate_warned &&
977 asprintf(&options[nr_options], "Annotate %s", 975 asprintf(&options[nr_options], "Annotate %s",
978 browser->selection->sym->name) > 0) 976 browser->selection->sym->name) > 0)
979 annotate = nr_options++; 977 annotate = nr_options++;
980 978
981 if (thread != NULL && 979 if (thread != NULL &&
982 asprintf(&options[nr_options], "Zoom %s %s(%d) thread", 980 asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
983 (browser->hists->thread_filter ? "out of" : "into"), 981 (browser->hists->thread_filter ? "out of" : "into"),
984 (thread->comm_set ? thread->comm : ""), 982 (thread->comm_set ? thread->comm : ""),
985 thread->pid) > 0) 983 thread->pid) > 0)
986 zoom_thread = nr_options++; 984 zoom_thread = nr_options++;
987 985
988 if (dso != NULL && 986 if (dso != NULL &&
989 asprintf(&options[nr_options], "Zoom %s %s DSO", 987 asprintf(&options[nr_options], "Zoom %s %s DSO",
990 (browser->hists->dso_filter ? "out of" : "into"), 988 (browser->hists->dso_filter ? "out of" : "into"),
991 (dso->kernel ? "the Kernel" : dso->short_name)) > 0) 989 (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
992 zoom_dso = nr_options++; 990 zoom_dso = nr_options++;
993 991
994 if (browser->selection != NULL && 992 if (browser->selection != NULL &&
995 browser->selection->map != NULL && 993 browser->selection->map != NULL &&
996 asprintf(&options[nr_options], "Browse map details") > 0) 994 asprintf(&options[nr_options], "Browse map details") > 0)
997 browse_map = nr_options++; 995 browse_map = nr_options++;
998 add_exit_option: 996 add_exit_option:
999 options[nr_options++] = (char *)"Exit"; 997 options[nr_options++] = (char *)"Exit";
1000 998
1001 choice = ui__popup_menu(nr_options, options); 999 choice = ui__popup_menu(nr_options, options);
1002 1000
1003 for (i = 0; i < nr_options - 1; ++i) 1001 for (i = 0; i < nr_options - 1; ++i)
1004 free(options[i]); 1002 free(options[i]);
1005 1003
1006 if (choice == nr_options - 1) 1004 if (choice == nr_options - 1)
1007 break; 1005 break;
1008 1006
1009 if (choice == -1) 1007 if (choice == -1)
1010 continue; 1008 continue;
1011 1009
1012 if (choice == annotate) { 1010 if (choice == annotate) {
1013 struct hist_entry *he; 1011 struct hist_entry *he;
1014 int err; 1012 int err;
1015 do_annotate: 1013 do_annotate:
1016 he = hist_browser__selected_entry(browser); 1014 he = hist_browser__selected_entry(browser);
1017 if (he == NULL) 1015 if (he == NULL)
1018 continue; 1016 continue;
1019 /* 1017 /*
1020 * Don't let this be freed, say, by hists__decay_entry. 1018 * Don't let this be freed, say, by hists__decay_entry.
1021 */ 1019 */
1022 he->used = true; 1020 he->used = true;
1023 err = hist_entry__tui_annotate(he, evsel->idx, 1021 err = hist_entry__tui_annotate(he, evsel->idx,
1024 timer, arg, delay_secs); 1022 timer, arg, delay_secs);
1025 he->used = false; 1023 he->used = false;
1026 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries); 1024 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
1027 if (err) 1025 if (err)
1028 ui_browser__handle_resize(&browser->b); 1026 ui_browser__handle_resize(&browser->b);
1029 } else if (choice == browse_map) 1027 } else if (choice == browse_map)
1030 map__browse(browser->selection->map); 1028 map__browse(browser->selection->map);
1031 else if (choice == zoom_dso) { 1029 else if (choice == zoom_dso) {
1032 zoom_dso: 1030 zoom_dso:
1033 if (browser->hists->dso_filter) { 1031 if (browser->hists->dso_filter) {
1034 pstack__remove(fstack, &browser->hists->dso_filter); 1032 pstack__remove(fstack, &browser->hists->dso_filter);
1035 zoom_out_dso: 1033 zoom_out_dso:
1036 ui_helpline__pop(); 1034 ui_helpline__pop();
1037 browser->hists->dso_filter = NULL; 1035 browser->hists->dso_filter = NULL;
1038 sort_dso.elide = false; 1036 sort_dso.elide = false;
1039 } else { 1037 } else {
1040 if (dso == NULL) 1038 if (dso == NULL)
1041 continue; 1039 continue;
1042 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"", 1040 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
1043 dso->kernel ? "the Kernel" : dso->short_name); 1041 dso->kernel ? "the Kernel" : dso->short_name);
1044 browser->hists->dso_filter = dso; 1042 browser->hists->dso_filter = dso;
1045 sort_dso.elide = true; 1043 sort_dso.elide = true;
1046 pstack__push(fstack, &browser->hists->dso_filter); 1044 pstack__push(fstack, &browser->hists->dso_filter);
1047 } 1045 }
1048 hists__filter_by_dso(self); 1046 hists__filter_by_dso(self);
1049 hist_browser__reset(browser); 1047 hist_browser__reset(browser);
1050 } else if (choice == zoom_thread) { 1048 } else if (choice == zoom_thread) {
1051 zoom_thread: 1049 zoom_thread:
1052 if (browser->hists->thread_filter) { 1050 if (browser->hists->thread_filter) {
1053 pstack__remove(fstack, &browser->hists->thread_filter); 1051 pstack__remove(fstack, &browser->hists->thread_filter);
1054 zoom_out_thread: 1052 zoom_out_thread:
1055 ui_helpline__pop(); 1053 ui_helpline__pop();
1056 browser->hists->thread_filter = NULL; 1054 browser->hists->thread_filter = NULL;
1057 sort_thread.elide = false; 1055 sort_thread.elide = false;
1058 } else { 1056 } else {
1059 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", 1057 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
1060 thread->comm_set ? thread->comm : "", 1058 thread->comm_set ? thread->comm : "",
1061 thread->pid); 1059 thread->pid);
1062 browser->hists->thread_filter = thread; 1060 browser->hists->thread_filter = thread;
1063 sort_thread.elide = true; 1061 sort_thread.elide = true;
1064 pstack__push(fstack, &browser->hists->thread_filter); 1062 pstack__push(fstack, &browser->hists->thread_filter);
1065 } 1063 }
1066 hists__filter_by_thread(self); 1064 hists__filter_by_thread(self);
1067 hist_browser__reset(browser); 1065 hist_browser__reset(browser);
1068 } 1066 }
1069 } 1067 }
1070 out_free_stack: 1068 out_free_stack:
1071 pstack__delete(fstack); 1069 pstack__delete(fstack);
1072 out: 1070 out:
1073 hist_browser__delete(browser); 1071 hist_browser__delete(browser);
1074 return key; 1072 return key;
1075 } 1073 }
1076 1074
1077 struct perf_evsel_menu { 1075 struct perf_evsel_menu {
1078 struct ui_browser b; 1076 struct ui_browser b;
1079 struct perf_evsel *selection; 1077 struct perf_evsel *selection;
1080 bool lost_events, lost_events_warned; 1078 bool lost_events, lost_events_warned;
1081 }; 1079 };
1082 1080
1083 static void perf_evsel_menu__write(struct ui_browser *browser, 1081 static void perf_evsel_menu__write(struct ui_browser *browser,
1084 void *entry, int row) 1082 void *entry, int row)
1085 { 1083 {
1086 struct perf_evsel_menu *menu = container_of(browser, 1084 struct perf_evsel_menu *menu = container_of(browser,
1087 struct perf_evsel_menu, b); 1085 struct perf_evsel_menu, b);
1088 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); 1086 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
1089 bool current_entry = ui_browser__is_current_entry(browser, row); 1087 bool current_entry = ui_browser__is_current_entry(browser, row);
1090 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1088 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
1091 const char *ev_name = event_name(evsel); 1089 const char *ev_name = event_name(evsel);
1092 char bf[256], unit; 1090 char bf[256], unit;
1093 const char *warn = " "; 1091 const char *warn = " ";
1094 size_t printed; 1092 size_t printed;
1095 1093
1096 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : 1094 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
1097 HE_COLORSET_NORMAL); 1095 HE_COLORSET_NORMAL);
1098 1096
1099 nr_events = convert_unit(nr_events, &unit); 1097 nr_events = convert_unit(nr_events, &unit);
1100 printed = snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events, 1098 printed = snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
1101 unit, unit == ' ' ? "" : " ", ev_name); 1099 unit, unit == ' ' ? "" : " ", ev_name);
1102 slsmg_printf("%s", bf); 1100 slsmg_printf("%s", bf);
1103 1101
1104 nr_events = evsel->hists.stats.nr_events[PERF_RECORD_LOST]; 1102 nr_events = evsel->hists.stats.nr_events[PERF_RECORD_LOST];
1105 if (nr_events != 0) { 1103 if (nr_events != 0) {
1106 menu->lost_events = true; 1104 menu->lost_events = true;
1107 if (!current_entry) 1105 if (!current_entry)
1108 ui_browser__set_color(browser, HE_COLORSET_TOP); 1106 ui_browser__set_color(browser, HE_COLORSET_TOP);
1109 nr_events = convert_unit(nr_events, &unit); 1107 nr_events = convert_unit(nr_events, &unit);
1110 snprintf(bf, sizeof(bf), ": %ld%c%schunks LOST!", nr_events, 1108 snprintf(bf, sizeof(bf), ": %ld%c%schunks LOST!", nr_events,
1111 unit, unit == ' ' ? "" : " "); 1109 unit, unit == ' ' ? "" : " ");
1112 warn = bf; 1110 warn = bf;
1113 } 1111 }
1114 1112
1115 slsmg_write_nstring(warn, browser->width - printed); 1113 slsmg_write_nstring(warn, browser->width - printed);
1116 1114
1117 if (current_entry) 1115 if (current_entry)
1118 menu->selection = evsel; 1116 menu->selection = evsel;
1119 } 1117 }
1120 1118
1121 static int perf_evsel_menu__run(struct perf_evsel_menu *menu, 1119 static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
1122 int nr_events, const char *help, 1120 int nr_events, const char *help,
1123 void(*timer)(void *arg), void *arg, int delay_secs) 1121 void(*timer)(void *arg), void *arg, int delay_secs)
1124 { 1122 {
1125 struct perf_evlist *evlist = menu->b.priv; 1123 struct perf_evlist *evlist = menu->b.priv;
1126 struct perf_evsel *pos; 1124 struct perf_evsel *pos;
1127 const char *ev_name, *title = "Available samples"; 1125 const char *ev_name, *title = "Available samples";
1128 int key; 1126 int key;
1129 1127
1130 if (ui_browser__show(&menu->b, title, 1128 if (ui_browser__show(&menu->b, title,
1131 "ESC: exit, ENTER|->: Browse histograms") < 0) 1129 "ESC: exit, ENTER|->: Browse histograms") < 0)
1132 return -1; 1130 return -1;
1133 1131
1134 while (1) { 1132 while (1) {
1135 key = ui_browser__run(&menu->b, delay_secs); 1133 key = ui_browser__run(&menu->b, delay_secs);
1136 1134
1137 switch (key) { 1135 switch (key) {
1138 case K_TIMER: 1136 case K_TIMER:
1139 timer(arg); 1137 timer(arg);
1140 1138
1141 if (!menu->lost_events_warned && menu->lost_events) { 1139 if (!menu->lost_events_warned && menu->lost_events) {
1142 ui_browser__warn_lost_events(&menu->b); 1140 ui_browser__warn_lost_events(&menu->b);
1143 menu->lost_events_warned = true; 1141 menu->lost_events_warned = true;
1144 } 1142 }
1145 continue; 1143 continue;
1146 case K_RIGHT: 1144 case K_RIGHT:
1147 case K_ENTER: 1145 case K_ENTER:
1148 if (!menu->selection) 1146 if (!menu->selection)
1149 continue; 1147 continue;
1150 pos = menu->selection; 1148 pos = menu->selection;
1151 browse_hists: 1149 browse_hists:
1152 perf_evlist__set_selected(evlist, pos); 1150 perf_evlist__set_selected(evlist, pos);
1153 /* 1151 /*
1154 * Give the calling tool a chance to populate the non 1152 * Give the calling tool a chance to populate the non
1155 * default evsel resorted hists tree. 1153 * default evsel resorted hists tree.
1156 */ 1154 */
1157 if (timer) 1155 if (timer)
1158 timer(arg); 1156 timer(arg);
1159 ev_name = event_name(pos); 1157 ev_name = event_name(pos);
1160 key = perf_evsel__hists_browse(pos, nr_events, help, 1158 key = perf_evsel__hists_browse(pos, nr_events, help,
1161 ev_name, true, timer, 1159 ev_name, true, timer,
1162 arg, delay_secs); 1160 arg, delay_secs);
1163 ui_browser__show_title(&menu->b, title); 1161 ui_browser__show_title(&menu->b, title);
1164 switch (key) { 1162 switch (key) {
1165 case K_TAB: 1163 case K_TAB:
1166 if (pos->node.next == &evlist->entries) 1164 if (pos->node.next == &evlist->entries)
1167 pos = list_entry(evlist->entries.next, struct perf_evsel, node); 1165 pos = list_entry(evlist->entries.next, struct perf_evsel, node);
1168 else 1166 else
1169 pos = list_entry(pos->node.next, struct perf_evsel, node); 1167 pos = list_entry(pos->node.next, struct perf_evsel, node);
1170 goto browse_hists; 1168 goto browse_hists;
1171 case K_UNTAB: 1169 case K_UNTAB:
1172 if (pos->node.prev == &evlist->entries) 1170 if (pos->node.prev == &evlist->entries)
1173 pos = list_entry(evlist->entries.prev, struct perf_evsel, node); 1171 pos = list_entry(evlist->entries.prev, struct perf_evsel, node);
1174 else 1172 else
1175 pos = list_entry(pos->node.prev, struct perf_evsel, node); 1173 pos = list_entry(pos->node.prev, struct perf_evsel, node);
1176 goto browse_hists; 1174 goto browse_hists;
1177 case K_ESC: 1175 case K_ESC:
1178 if (!ui_browser__dialog_yesno(&menu->b, 1176 if (!ui_browser__dialog_yesno(&menu->b,
1179 "Do you really want to exit?")) 1177 "Do you really want to exit?"))
1180 continue; 1178 continue;
1181 /* Fall thru */ 1179 /* Fall thru */
1182 case 'q': 1180 case 'q':
1183 case CTRL('c'): 1181 case CTRL('c'):
1184 goto out; 1182 goto out;
1185 default: 1183 default:
1186 continue; 1184 continue;
1187 } 1185 }
1188 case K_LEFT: 1186 case K_LEFT:
1189 continue; 1187 continue;
1190 case K_ESC: 1188 case K_ESC:
1191 if (!ui_browser__dialog_yesno(&menu->b, 1189 if (!ui_browser__dialog_yesno(&menu->b,
1192 "Do you really want to exit?")) 1190 "Do you really want to exit?"))
1193 continue; 1191 continue;
1194 /* Fall thru */ 1192 /* Fall thru */
1195 case 'q': 1193 case 'q':
1196 case CTRL('c'): 1194 case CTRL('c'):
1197 goto out; 1195 goto out;
1198 default: 1196 default:
1199 continue; 1197 continue;
1200 } 1198 }
1201 } 1199 }
1202 1200
1203 out: 1201 out:
1204 ui_browser__hide(&menu->b); 1202 ui_browser__hide(&menu->b);
1205 return key; 1203 return key;
1206 } 1204 }
1207 1205
1208 static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, 1206 static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
1209 const char *help, 1207 const char *help,
1210 void(*timer)(void *arg), void *arg, 1208 void(*timer)(void *arg), void *arg,
1211 int delay_secs) 1209 int delay_secs)
1212 { 1210 {
1213 struct perf_evsel *pos; 1211 struct perf_evsel *pos;
1214 struct perf_evsel_menu menu = { 1212 struct perf_evsel_menu menu = {
1215 .b = { 1213 .b = {
1216 .entries = &evlist->entries, 1214 .entries = &evlist->entries,
1217 .refresh = ui_browser__list_head_refresh, 1215 .refresh = ui_browser__list_head_refresh,
1218 .seek = ui_browser__list_head_seek, 1216 .seek = ui_browser__list_head_seek,
1219 .write = perf_evsel_menu__write, 1217 .write = perf_evsel_menu__write,
1220 .nr_entries = evlist->nr_entries, 1218 .nr_entries = evlist->nr_entries,
1221 .priv = evlist, 1219 .priv = evlist,
1222 }, 1220 },
1223 }; 1221 };
1224 1222
1225 ui_helpline__push("Press ESC to exit"); 1223 ui_helpline__push("Press ESC to exit");
1226 1224
1227 list_for_each_entry(pos, &evlist->entries, node) { 1225 list_for_each_entry(pos, &evlist->entries, node) {
1228 const char *ev_name = event_name(pos); 1226 const char *ev_name = event_name(pos);
1229 size_t line_len = strlen(ev_name) + 7; 1227 size_t line_len = strlen(ev_name) + 7;
1230 1228
1231 if (menu.b.width < line_len) 1229 if (menu.b.width < line_len)
1232 menu.b.width = line_len; 1230 menu.b.width = line_len;
1233 /* 1231 /*
1234 * Cache the evsel name, tracepoints have a _high_ cost per 1232 * Cache the evsel name, tracepoints have a _high_ cost per
1235 * event_name() call. 1233 * event_name() call.
1236 */ 1234 */
1237 if (pos->name == NULL) 1235 if (pos->name == NULL)
1238 pos->name = strdup(ev_name); 1236 pos->name = strdup(ev_name);
1239 } 1237 }
1240 1238
1241 return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer, 1239 return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer,
1242 arg, delay_secs); 1240 arg, delay_secs);
1243 } 1241 }
1244 1242
1245 int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 1243 int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
1246 void(*timer)(void *arg), void *arg, 1244 void(*timer)(void *arg), void *arg,
1247 int delay_secs) 1245 int delay_secs)
1248 { 1246 {
1249 1247
1250 if (evlist->nr_entries == 1) { 1248 if (evlist->nr_entries == 1) {
1251 struct perf_evsel *first = list_entry(evlist->entries.next, 1249 struct perf_evsel *first = list_entry(evlist->entries.next,
1252 struct perf_evsel, node); 1250 struct perf_evsel, node);
1253 const char *ev_name = event_name(first); 1251 const char *ev_name = event_name(first);
1254 return perf_evsel__hists_browse(first, evlist->nr_entries, help, 1252 return perf_evsel__hists_browse(first, evlist->nr_entries, help,
1255 ev_name, false, timer, arg, 1253 ev_name, false, timer, arg,
1256 delay_secs); 1254 delay_secs);
1257 } 1255 }
1258 1256
1259 return __perf_evlist__tui_browse_hists(evlist, help, 1257 return __perf_evlist__tui_browse_hists(evlist, help,
1260 timer, arg, delay_secs); 1258 timer, arg, delay_secs);
1261 } 1259 }
1262 1260
tools/perf/util/ui/helpline.c
1 #define _GNU_SOURCE
2 #include <stdio.h> 1 #include <stdio.h>
3 #include <stdlib.h> 2 #include <stdlib.h>
4 #include <string.h> 3 #include <string.h>
5 4
6 #include "../debug.h" 5 #include "../debug.h"
7 #include "helpline.h" 6 #include "helpline.h"
8 #include "ui.h" 7 #include "ui.h"
9 #include "libslang.h" 8 #include "libslang.h"
10 9
11 void ui_helpline__pop(void) 10 void ui_helpline__pop(void)
12 { 11 {
13 } 12 }
14 13
15 char ui_helpline__current[512]; 14 char ui_helpline__current[512];
16 15
17 void ui_helpline__push(const char *msg) 16 void ui_helpline__push(const char *msg)
18 { 17 {
19 const size_t sz = sizeof(ui_helpline__current); 18 const size_t sz = sizeof(ui_helpline__current);
20 19
21 SLsmg_gotorc(SLtt_Screen_Rows - 1, 0); 20 SLsmg_gotorc(SLtt_Screen_Rows - 1, 0);
22 SLsmg_set_color(0); 21 SLsmg_set_color(0);
23 SLsmg_write_nstring((char *)msg, SLtt_Screen_Cols); 22 SLsmg_write_nstring((char *)msg, SLtt_Screen_Cols);
24 SLsmg_refresh(); 23 SLsmg_refresh();
25 strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0'; 24 strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0';
26 } 25 }
27 26
28 void ui_helpline__vpush(const char *fmt, va_list ap) 27 void ui_helpline__vpush(const char *fmt, va_list ap)
29 { 28 {
30 char *s; 29 char *s;
31 30
32 if (vasprintf(&s, fmt, ap) < 0) 31 if (vasprintf(&s, fmt, ap) < 0)
33 vfprintf(stderr, fmt, ap); 32 vfprintf(stderr, fmt, ap);
34 else { 33 else {
35 ui_helpline__push(s); 34 ui_helpline__push(s);
36 free(s); 35 free(s);
37 } 36 }
38 } 37 }
39 38
40 void ui_helpline__fpush(const char *fmt, ...) 39 void ui_helpline__fpush(const char *fmt, ...)
41 { 40 {
42 va_list ap; 41 va_list ap;
43 42
44 va_start(ap, fmt); 43 va_start(ap, fmt);
45 ui_helpline__vpush(fmt, ap); 44 ui_helpline__vpush(fmt, ap);
46 va_end(ap); 45 va_end(ap);
47 } 46 }
48 47
49 void ui_helpline__puts(const char *msg) 48 void ui_helpline__puts(const char *msg)
50 { 49 {
51 ui_helpline__pop(); 50 ui_helpline__pop();
52 ui_helpline__push(msg); 51 ui_helpline__push(msg);
53 } 52 }
54 53
55 void ui_helpline__init(void) 54 void ui_helpline__init(void)
56 { 55 {
57 ui_helpline__puts(" "); 56 ui_helpline__puts(" ");
58 } 57 }
59 58
60 char ui_helpline__last_msg[1024]; 59 char ui_helpline__last_msg[1024];
61 60
62 int ui_helpline__show_help(const char *format, va_list ap) 61 int ui_helpline__show_help(const char *format, va_list ap)
63 { 62 {
64 int ret; 63 int ret;
65 static int backlog; 64 static int backlog;
66 65
67 pthread_mutex_lock(&ui__lock); 66 pthread_mutex_lock(&ui__lock);
68 ret = vsnprintf(ui_helpline__last_msg + backlog, 67 ret = vsnprintf(ui_helpline__last_msg + backlog,
69 sizeof(ui_helpline__last_msg) - backlog, format, ap); 68 sizeof(ui_helpline__last_msg) - backlog, format, ap);
70 backlog += ret; 69 backlog += ret;
71 70
72 if (ui_helpline__last_msg[backlog - 1] == '\n') { 71 if (ui_helpline__last_msg[backlog - 1] == '\n') {
73 ui_helpline__puts(ui_helpline__last_msg); 72 ui_helpline__puts(ui_helpline__last_msg);
74 SLsmg_refresh(); 73 SLsmg_refresh();
75 backlog = 0; 74 backlog = 0;
76 } 75 }
77 pthread_mutex_unlock(&ui__lock); 76 pthread_mutex_unlock(&ui__lock);
78 77
79 return ret; 78 return ret;
80 } 79 }
81 80
tools/perf/util/util.h
1 #ifndef GIT_COMPAT_UTIL_H 1 #ifndef GIT_COMPAT_UTIL_H
2 #define GIT_COMPAT_UTIL_H 2 #define GIT_COMPAT_UTIL_H
3 3
4 #define _FILE_OFFSET_BITS 64 4 #define _FILE_OFFSET_BITS 64
5 5
6 #ifndef FLEX_ARRAY 6 #ifndef FLEX_ARRAY
7 /* 7 /*
8 * See if our compiler is known to support flexible array members. 8 * See if our compiler is known to support flexible array members.
9 */ 9 */
10 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) 10 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
11 # define FLEX_ARRAY /* empty */ 11 # define FLEX_ARRAY /* empty */
12 #elif defined(__GNUC__) 12 #elif defined(__GNUC__)
13 # if (__GNUC__ >= 3) 13 # if (__GNUC__ >= 3)
14 # define FLEX_ARRAY /* empty */ 14 # define FLEX_ARRAY /* empty */
15 # else 15 # else
16 # define FLEX_ARRAY 0 /* older GNU extension */ 16 # define FLEX_ARRAY 0 /* older GNU extension */
17 # endif 17 # endif
18 #endif 18 #endif
19 19
20 /* 20 /*
21 * Otherwise, default to safer but a bit wasteful traditional style 21 * Otherwise, default to safer but a bit wasteful traditional style
22 */ 22 */
23 #ifndef FLEX_ARRAY 23 #ifndef FLEX_ARRAY
24 # define FLEX_ARRAY 1 24 # define FLEX_ARRAY 1
25 #endif 25 #endif
26 #endif 26 #endif
27 27
28 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) 28 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
29 29
30 #ifdef __GNUC__ 30 #ifdef __GNUC__
31 #define TYPEOF(x) (__typeof__(x)) 31 #define TYPEOF(x) (__typeof__(x))
32 #else 32 #else
33 #define TYPEOF(x) 33 #define TYPEOF(x)
34 #endif 34 #endif
35 35
36 #define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (sizeof(x) * 8 - (bits)))) 36 #define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (sizeof(x) * 8 - (bits))))
37 #define HAS_MULTI_BITS(i) ((i) & ((i) - 1)) /* checks if an integer has more than 1 bit set */ 37 #define HAS_MULTI_BITS(i) ((i) & ((i) - 1)) /* checks if an integer has more than 1 bit set */
38 38
39 /* Approximation of the length of the decimal representation of this type. */ 39 /* Approximation of the length of the decimal representation of this type. */
40 #define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) 40 #define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
41 41
42 #define _ALL_SOURCE 1 42 #define _ALL_SOURCE 1
43 #define _GNU_SOURCE 1
44 #define _BSD_SOURCE 1 43 #define _BSD_SOURCE 1
45 #define HAS_BOOL 44 #define HAS_BOOL
46 45
47 #include <unistd.h> 46 #include <unistd.h>
48 #include <stdio.h> 47 #include <stdio.h>
49 #include <sys/stat.h> 48 #include <sys/stat.h>
50 #include <sys/statfs.h> 49 #include <sys/statfs.h>
51 #include <fcntl.h> 50 #include <fcntl.h>
52 #include <stdbool.h> 51 #include <stdbool.h>
53 #include <stddef.h> 52 #include <stddef.h>
54 #include <stdlib.h> 53 #include <stdlib.h>
55 #include <stdarg.h> 54 #include <stdarg.h>
56 #include <string.h> 55 #include <string.h>
57 #include <errno.h> 56 #include <errno.h>
58 #include <limits.h> 57 #include <limits.h>
59 #include <sys/param.h> 58 #include <sys/param.h>
60 #include <sys/types.h> 59 #include <sys/types.h>
61 #include <dirent.h> 60 #include <dirent.h>
62 #include <sys/time.h> 61 #include <sys/time.h>
63 #include <time.h> 62 #include <time.h>
64 #include <signal.h> 63 #include <signal.h>
65 #include <fnmatch.h> 64 #include <fnmatch.h>
66 #include <assert.h> 65 #include <assert.h>
67 #include <regex.h> 66 #include <regex.h>
68 #include <utime.h> 67 #include <utime.h>
69 #include <sys/wait.h> 68 #include <sys/wait.h>
70 #include <sys/poll.h> 69 #include <sys/poll.h>
71 #include <sys/socket.h> 70 #include <sys/socket.h>
72 #include <sys/ioctl.h> 71 #include <sys/ioctl.h>
73 #include <sys/select.h> 72 #include <sys/select.h>
74 #include <netinet/in.h> 73 #include <netinet/in.h>
75 #include <netinet/tcp.h> 74 #include <netinet/tcp.h>
76 #include <arpa/inet.h> 75 #include <arpa/inet.h>
77 #include <netdb.h> 76 #include <netdb.h>
78 #include <pwd.h> 77 #include <pwd.h>
79 #include <inttypes.h> 78 #include <inttypes.h>
80 #include "../../../include/linux/magic.h" 79 #include "../../../include/linux/magic.h"
81 #include "types.h" 80 #include "types.h"
82 #include <sys/ttydefaults.h> 81 #include <sys/ttydefaults.h>
83 82
84 extern const char *graph_line; 83 extern const char *graph_line;
85 extern const char *graph_dotted_line; 84 extern const char *graph_dotted_line;
86 extern char buildid_dir[]; 85 extern char buildid_dir[];
87 86
88 /* On most systems <limits.h> would have given us this, but 87 /* On most systems <limits.h> would have given us this, but
89 * not on some systems (e.g. GNU/Hurd). 88 * not on some systems (e.g. GNU/Hurd).
90 */ 89 */
91 #ifndef PATH_MAX 90 #ifndef PATH_MAX
92 #define PATH_MAX 4096 91 #define PATH_MAX 4096
93 #endif 92 #endif
94 93
95 #ifndef PRIuMAX 94 #ifndef PRIuMAX
96 #define PRIuMAX "llu" 95 #define PRIuMAX "llu"
97 #endif 96 #endif
98 97
99 #ifndef PRIu32 98 #ifndef PRIu32
100 #define PRIu32 "u" 99 #define PRIu32 "u"
101 #endif 100 #endif
102 101
103 #ifndef PRIx32 102 #ifndef PRIx32
104 #define PRIx32 "x" 103 #define PRIx32 "x"
105 #endif 104 #endif
106 105
107 #ifndef PATH_SEP 106 #ifndef PATH_SEP
108 #define PATH_SEP ':' 107 #define PATH_SEP ':'
109 #endif 108 #endif
110 109
111 #ifndef STRIP_EXTENSION 110 #ifndef STRIP_EXTENSION
112 #define STRIP_EXTENSION "" 111 #define STRIP_EXTENSION ""
113 #endif 112 #endif
114 113
115 #ifndef has_dos_drive_prefix 114 #ifndef has_dos_drive_prefix
116 #define has_dos_drive_prefix(path) 0 115 #define has_dos_drive_prefix(path) 0
117 #endif 116 #endif
118 117
119 #ifndef is_dir_sep 118 #ifndef is_dir_sep
120 #define is_dir_sep(c) ((c) == '/') 119 #define is_dir_sep(c) ((c) == '/')
121 #endif 120 #endif
122 121
123 #ifdef __GNUC__ 122 #ifdef __GNUC__
124 #define NORETURN __attribute__((__noreturn__)) 123 #define NORETURN __attribute__((__noreturn__))
125 #else 124 #else
126 #define NORETURN 125 #define NORETURN
127 #ifndef __attribute__ 126 #ifndef __attribute__
128 #define __attribute__(x) 127 #define __attribute__(x)
129 #endif 128 #endif
130 #endif 129 #endif
131 130
132 /* General helper functions */ 131 /* General helper functions */
133 extern void usage(const char *err) NORETURN; 132 extern void usage(const char *err) NORETURN;
134 extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); 133 extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
135 extern int error(const char *err, ...) __attribute__((format (printf, 1, 2))); 134 extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
136 extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); 135 extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
137 136
138 #include "../../../include/linux/stringify.h" 137 #include "../../../include/linux/stringify.h"
139 138
140 #define DIE_IF(cnd) \ 139 #define DIE_IF(cnd) \
141 do { if (cnd) \ 140 do { if (cnd) \
142 die(" at (" __FILE__ ":" __stringify(__LINE__) "): " \ 141 die(" at (" __FILE__ ":" __stringify(__LINE__) "): " \
143 __stringify(cnd) "\n"); \ 142 __stringify(cnd) "\n"); \
144 } while (0) 143 } while (0)
145 144
146 145
147 extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); 146 extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
148 147
149 extern int prefixcmp(const char *str, const char *prefix); 148 extern int prefixcmp(const char *str, const char *prefix);
150 extern void set_buildid_dir(void); 149 extern void set_buildid_dir(void);
151 extern void disable_buildid_cache(void); 150 extern void disable_buildid_cache(void);
152 151
153 static inline const char *skip_prefix(const char *str, const char *prefix) 152 static inline const char *skip_prefix(const char *str, const char *prefix)
154 { 153 {
155 size_t len = strlen(prefix); 154 size_t len = strlen(prefix);
156 return strncmp(str, prefix, len) ? NULL : str + len; 155 return strncmp(str, prefix, len) ? NULL : str + len;
157 } 156 }
158 157
159 #ifdef __GLIBC_PREREQ 158 #ifdef __GLIBC_PREREQ
160 #if __GLIBC_PREREQ(2, 1) 159 #if __GLIBC_PREREQ(2, 1)
161 #define HAVE_STRCHRNUL 160 #define HAVE_STRCHRNUL
162 #endif 161 #endif
163 #endif 162 #endif
164 163
165 #ifndef HAVE_STRCHRNUL 164 #ifndef HAVE_STRCHRNUL
166 #define strchrnul gitstrchrnul 165 #define strchrnul gitstrchrnul
167 static inline char *gitstrchrnul(const char *s, int c) 166 static inline char *gitstrchrnul(const char *s, int c)
168 { 167 {
169 while (*s && *s != c) 168 while (*s && *s != c)
170 s++; 169 s++;
171 return (char *)s; 170 return (char *)s;
172 } 171 }
173 #endif 172 #endif
174 173
175 /* 174 /*
176 * Wrappers: 175 * Wrappers:
177 */ 176 */
178 extern char *xstrdup(const char *str); 177 extern char *xstrdup(const char *str);
179 extern void *xrealloc(void *ptr, size_t size) __attribute__((weak)); 178 extern void *xrealloc(void *ptr, size_t size) __attribute__((weak));
180 179
181 180
182 static inline void *zalloc(size_t size) 181 static inline void *zalloc(size_t size)
183 { 182 {
184 return calloc(1, size); 183 return calloc(1, size);
185 } 184 }
186 185
187 static inline int has_extension(const char *filename, const char *ext) 186 static inline int has_extension(const char *filename, const char *ext)
188 { 187 {
189 size_t len = strlen(filename); 188 size_t len = strlen(filename);
190 size_t extlen = strlen(ext); 189 size_t extlen = strlen(ext);
191 190
192 return len > extlen && !memcmp(filename + len - extlen, ext, extlen); 191 return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
193 } 192 }
194 193
195 /* Sane ctype - no locale, and works with signed chars */ 194 /* Sane ctype - no locale, and works with signed chars */
196 #undef isascii 195 #undef isascii
197 #undef isspace 196 #undef isspace
198 #undef isdigit 197 #undef isdigit
199 #undef isxdigit 198 #undef isxdigit
200 #undef isalpha 199 #undef isalpha
201 #undef isprint 200 #undef isprint
202 #undef isalnum 201 #undef isalnum
203 #undef tolower 202 #undef tolower
204 #undef toupper 203 #undef toupper
205 204
206 extern unsigned char sane_ctype[256]; 205 extern unsigned char sane_ctype[256];
207 #define GIT_SPACE 0x01 206 #define GIT_SPACE 0x01
208 #define GIT_DIGIT 0x02 207 #define GIT_DIGIT 0x02
209 #define GIT_ALPHA 0x04 208 #define GIT_ALPHA 0x04
210 #define GIT_GLOB_SPECIAL 0x08 209 #define GIT_GLOB_SPECIAL 0x08
211 #define GIT_REGEX_SPECIAL 0x10 210 #define GIT_REGEX_SPECIAL 0x10
212 #define GIT_PRINT_EXTRA 0x20 211 #define GIT_PRINT_EXTRA 0x20
213 #define GIT_PRINT 0x3E 212 #define GIT_PRINT 0x3E
214 #define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0) 213 #define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
215 #define isascii(x) (((x) & ~0x7f) == 0) 214 #define isascii(x) (((x) & ~0x7f) == 0)
216 #define isspace(x) sane_istest(x,GIT_SPACE) 215 #define isspace(x) sane_istest(x,GIT_SPACE)
217 #define isdigit(x) sane_istest(x,GIT_DIGIT) 216 #define isdigit(x) sane_istest(x,GIT_DIGIT)
218 #define isxdigit(x) \ 217 #define isxdigit(x) \
219 (sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G') 218 (sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G')
220 #define isalpha(x) sane_istest(x,GIT_ALPHA) 219 #define isalpha(x) sane_istest(x,GIT_ALPHA)
221 #define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) 220 #define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
222 #define isprint(x) sane_istest(x,GIT_PRINT) 221 #define isprint(x) sane_istest(x,GIT_PRINT)
223 #define tolower(x) sane_case((unsigned char)(x), 0x20) 222 #define tolower(x) sane_case((unsigned char)(x), 0x20)
224 #define toupper(x) sane_case((unsigned char)(x), 0) 223 #define toupper(x) sane_case((unsigned char)(x), 0)
225 224
226 static inline int sane_case(int x, int high) 225 static inline int sane_case(int x, int high)
227 { 226 {
228 if (sane_istest(x, GIT_ALPHA)) 227 if (sane_istest(x, GIT_ALPHA))
229 x = (x & ~0x20) | high; 228 x = (x & ~0x20) | high;
230 return x; 229 return x;
231 } 230 }
232 231
233 int mkdir_p(char *path, mode_t mode); 232 int mkdir_p(char *path, mode_t mode);
234 int copyfile(const char *from, const char *to); 233 int copyfile(const char *from, const char *to);
235 234
236 s64 perf_atoll(const char *str); 235 s64 perf_atoll(const char *str);
237 char **argv_split(const char *str, int *argcp); 236 char **argv_split(const char *str, int *argcp);
238 void argv_free(char **argv); 237 void argv_free(char **argv);
239 bool strglobmatch(const char *str, const char *pat); 238 bool strglobmatch(const char *str, const char *pat);
240 bool strlazymatch(const char *str, const char *pat); 239 bool strlazymatch(const char *str, const char *pat);
241 int strtailcmp(const char *s1, const char *s2); 240 int strtailcmp(const char *s1, const char *s2);
242 unsigned long convert_unit(unsigned long value, char *unit); 241 unsigned long convert_unit(unsigned long value, char *unit);
243 int readn(int fd, void *buf, size_t size); 242 int readn(int fd, void *buf, size_t size);
244 243
245 struct perf_event_attr; 244 struct perf_event_attr;
246 245
247 void event_attr_init(struct perf_event_attr *attr); 246 void event_attr_init(struct perf_event_attr *attr);
248 247
249 #define _STR(x) #x 248 #define _STR(x) #x
250 #define STR(x) _STR(x) 249 #define STR(x) _STR(x)
251 250
252 /* 251 /*
253 * Determine whether some value is a power of two, where zero is 252 * Determine whether some value is a power of two, where zero is
254 * *not* considered a power of two. 253 * *not* considered a power of two.
255 */ 254 */
256 255
257 static inline __attribute__((const)) 256 static inline __attribute__((const))
258 bool is_power_of_2(unsigned long n) 257 bool is_power_of_2(unsigned long n)
259 { 258 {
260 return (n != 0 && ((n & (n - 1)) == 0)); 259 return (n != 0 && ((n & (n - 1)) == 0));
261 } 260 }
262 261
263 #endif 262 #endif
264 263