aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/jitdump-specification.txt170
-rw-r--r--tools/perf/Documentation/perf-record.txt9
-rw-r--r--tools/perf/Documentation/perf-script.txt6
-rw-r--r--tools/perf/Documentation/perf-trace.txt5
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile.config2
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c2
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl4
-rw-r--r--tools/perf/bench/futex-hash.c5
-rw-r--r--tools/perf/bench/mem-functions.c77
-rw-r--r--tools/perf/builtin-report.c12
-rw-r--r--tools/perf/builtin-script.c24
-rw-r--r--tools/perf/builtin-trace.c19
-rw-r--r--tools/perf/jvmti/jvmti_agent.c38
-rw-r--r--tools/perf/jvmti/libjvmti.c39
-rw-r--r--tools/perf/tests/backward-ring-buffer.c2
-rw-r--r--tools/perf/tests/bpf.c2
-rw-r--r--tools/perf/ui/browsers/hists.c5
-rw-r--r--tools/perf/util/Build2
-rw-r--r--tools/perf/util/bpf-loader.c14
-rw-r--r--tools/perf/util/event.h3
-rw-r--r--tools/perf/util/evsel.c9
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/genelf.c113
-rw-r--r--tools/perf/util/genelf.h5
-rw-r--r--tools/perf/util/header.c19
-rw-r--r--tools/perf/util/intel-bts.c9
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c2
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h1
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c13
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h6
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-log.c4
-rw-r--r--tools/perf/util/intel-pt.c19
-rw-r--r--tools/perf/util/jitdump.c82
-rw-r--r--tools/perf/util/jitdump.h12
-rw-r--r--tools/perf/util/llvm-utils.c2
-rw-r--r--tools/perf/util/map.c17
-rw-r--r--tools/perf/util/parse-branch-options.c85
-rw-r--r--tools/perf/util/parse-branch-options.h3
-rw-r--r--tools/perf/util/parse-events.c15
-rw-r--r--tools/perf/util/pmu.c10
-rw-r--r--tools/perf/util/quote.c2
-rw-r--r--tools/perf/util/session.c10
-rw-r--r--tools/perf/util/string.c21
-rw-r--r--tools/perf/util/unwind-libunwind-local.c4
-rw-r--r--tools/perf/util/util.h1
-rw-r--r--tools/perf/util/values.c81
-rw-r--r--tools/perf/util/values.h4
48 files changed, 732 insertions, 260 deletions
diff --git a/tools/perf/Documentation/jitdump-specification.txt b/tools/perf/Documentation/jitdump-specification.txt
new file mode 100644
index 000000000000..4c62b0713651
--- /dev/null
+++ b/tools/perf/Documentation/jitdump-specification.txt
@@ -0,0 +1,170 @@
1JITDUMP specification version 2
2Last Revised: 09/15/2016
3Author: Stephane Eranian <eranian@gmail.com>
4
5--------------------------------------------------------
6| Revision | Date | Description |
7--------------------------------------------------------
8| 1 | 09/07/2016 | Initial revision |
9--------------------------------------------------------
10| 2 | 09/15/2016 | Add JIT_CODE_UNWINDING_INFO |
11--------------------------------------------------------
12
13
14I/ Introduction
15
16
17This document describes the jitdump file format. The file is generated by Just-In-time compiler runtimes to save meta-data information about the generated code, such as address, size, and name of generated functions, the native code generated, the source line information. The data may then be used by performance tools, such as Linux perf to generate function and assembly level profiles.
18
19The format is not specific to any particular programming language. It can be extended as need be.
20
21The format of the file is binary. It is self-describing in terms of endianness and is portable across multiple processor architectures.
22
23
24II/ Overview of the format
25
26
27The format requires only sequential accesses, i.e., append only mode. The file starts with a fixed size file header describing the version of the specification, the endianness.
28
29The header is followed by a series of records, each starting with a fixed size header describing the type of record and its size. It is, itself, followed by the payload for the record. Records can have a variable size even for a given type.
30
31Each entry in the file is timestamped. All timestamps must use the same clock source. The CLOCK_MONOTONIC clock source is recommended.
32
33
34III/ Jitdump file header format
35
36Each jitdump file starts with a fixed size header containing the following fields in order:
37
38
39* uint32_t magic : a magic number tagging the file type. The value is 4-byte long and represents the string "JiTD" in ASCII form. It is 0x4A695444 or 0x4454694a depending on the endianness. The field can be used to detect the endianness of the file
40* uint32_t version : a 4-byte value representing the format version. It is currently set to 2
41* uint32_t total_size: size in bytes of file header
42* uint32_t elf_mach : ELF architecture encoding (ELF e_machine value as specified in /usr/include/elf.h)
43* uint32_t pad1 : padding. Reserved for future use
44* uint32_t pid : JIT runtime process identification (OS specific)
45* uint64_t timestamp : timestamp of when the file was created
46* uint64_t flags : a bitmask of flags
47
48The flags currently defined are as follows:
49 * bit 0: JITDUMP_FLAGS_ARCH_TIMESTAMP : set if the jitdump file is using an architecture-specific timestamp clock source. For instance, on x86, one could use TSC directly
50
51IV/ Record header
52
53The file header is immediately followed by records. Each record starts with a fixed size header describing the record that follows.
54
55The record header is specified in order as follows:
56* uint32_t id : a value identifying the record type (see below)
57* uint32_t total_size: the size in bytes of the record including the header.
58* uint64_t timestamp : a timestamp of when the record was created.
59
60The following record types are defined:
61 * Value 0 : JIT_CODE_LOAD : record describing a jitted function
62 * Value 1 : JIT_CODE_MOVE : record describing an already jitted function which is moved
63 * Value 2 : JIT_CODE_DEBUG_INFO: record describing the debug information for a jitted function
64 * Value 3 : JIT_CODE_CLOSE : record marking the end of the jit runtime (optional)
65 * Value 4 : JIT_CODE_UNWINDING_INFO: record describing a function unwinding information
66
67 The payload of the record must immediately follow the record header without padding.
68
69V/ JIT_CODE_LOAD record
70
71
72 The record has the following fields following the fixed-size record header in order:
73 * uint32_t pid: OS process id of the runtime generating the jitted code
74 * uint32_t tid: OS thread identification of the runtime thread generating the jitted code
75 * uint64_t vma: virtual address of jitted code start
76 * uint64_t code_addr: code start address for the jitted code. By default vma = code_addr
77 * uint64_t code_size: size in bytes of the generated jitted code
78 * uint64_t code_index: unique identifier for the jitted code (see below)
79 * char[n]: function name in ASCII including the null termination
80 * native code: raw byte encoding of the jitted code
81
82 The record header total_size field is inclusive of all components:
83 * record header
84 * fixed-sized fields
85 * function name string, including termination
86 * native code length
87 * record specific variable data (e.g., array of data entries)
88
89The code_index is used to uniquely identify each jitted function. The index can be a monotonically increasing 64-bit value. Each time a function is jitted it gets a new number. This value is used in case the code for a function is moved and avoids having to issue another JIT_CODE_LOAD record.
90
91The format supports empty functions with no native code.
92
93
94VI/ JIT_CODE_MOVE record
95
96 The record type is optional.
97
98 The record has the following fields following the fixed-size record header in order:
99 * uint32_t pid : OS process id of the runtime generating the jitted code
100 * uint32_t tid : OS thread identification of the runtime thread generating the jitted code
101 * uint64_t vma : new virtual address of jitted code start
102 * uint64_t old_code_addr: previous code address for the same function
103 * uint64_t new_code_addr: alternate new code started address for the jitted code. By default it should be equal to the vma address.
104 * uint64_t code_size : size in bytes of the jitted code
105 * uint64_t code_index : index referring to the JIT_CODE_LOAD code_index record of when the function was initially jitted
106
107
108The MOVE record can be used in case an already jitted function is simply moved by the runtime inside the code cache.
109
110The JIT_CODE_MOVE record cannot come before the JIT_CODE_LOAD record for the same function name. The function cannot have changed name, otherwise a new JIT_CODE_LOAD record must be emitted.
111
112The code size of the function cannot change.
113
114
115VII/ JIT_DEBUG_INFO record
116
117The record type is optional.
118
119The record contains source lines debug information, i.e., a way to map a code address back to a source line. This information may be used by the performance tool.
120
121The record has the following fields following the fixed-size record header in order:
122 * uint64_t code_addr: address of function for which the debug information is generated
123 * uint64_t nr_entry : number of debug entries for the function
124 * debug_entry[n]: array of nr_entry debug entries for the function
125
126The debug_entry describes the source line information. It is defined as follows in order:
127* uint64_t code_addr: address of function for which the debug information is generated
128* uint32_t line : source file line number (starting at 1)
129* uint32_t discrim : column discriminator, 0 is default
130* char name[n] : source file name in ASCII, including null termination
131
132The debug_entry entries are saved in sequence but given that they have variable sizes due to the file name string, they cannot be indexed directly.
133They need to be walked sequentially. The next debug_entry is found at sizeof(debug_entry) + strlen(name) + 1.
134
135IMPORTANT:
136 The JIT_CODE_DEBUG for a given function must always be generated BEFORE the JIT_CODE_LOAD for the function. This facilitates greatly the parser for the jitdump file.
137
138
139VIII/ JIT_CODE_CLOSE record
140
141
142The record type is optional.
143
144The record is used as a marker for the end of the jitted runtime. It can be replaced by the end of the file.
145
146The JIT_CODE_CLOSE record does not have any specific fields, the record header contains all the information needed.
147
148
149IX/ JIT_CODE_UNWINDING_INFO
150
151
152The record type is optional.
153
154The record is used to describe the unwinding information for a jitted function.
155
156The record has the following fields following the fixed-size record header in order:
157
158uint64_t unwind_data_size : the size in bytes of the unwinding data table at the end of the record
159uint64_t eh_frame_hdr_size : the size in bytes of the DWARF EH Frame Header at the start of the unwinding data table at the end of the record
160uint64_t mapped_size : the size of the unwinding data mapped in memory
161const char unwinding_data[n]: an array of unwinding data, consisting of the EH Frame Header, followed by the actual EH Frame
162
163
164The EH Frame header follows the Linux Standard Base (LSB) specification as described in the document at https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html
165
166
167The EH Frame follows the LSB specicfication as described in the document at https://refspecs.linuxbase.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html
168
169
170NOTE: The mapped_size is generally either the same as unwind_data_size (if the unwinding data was mapped in memory by the running process) or zero (if the unwinding data is not mapped by the process). If the unwinding data was not mapped, then only the EH Frame Header will be read, which can be used to specify FP based unwinding for a function which does not have unwinding information.
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 92335193dc33..27fc3617c6a4 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -45,9 +45,9 @@ OPTIONS
45 param1 and param2 are defined as formats for the PMU in: 45 param1 and param2 are defined as formats for the PMU in:
46 /sys/bus/event_source/devices/<pmu>/format/* 46 /sys/bus/event_source/devices/<pmu>/format/*
47 47
48 There are also some params which are not defined in .../<pmu>/format/*. 48 There are also some parameters which are not defined in .../<pmu>/format/*.
49 These params can be used to overload default config values per event. 49 These params can be used to overload default config values per event.
50 Here is a list of the params. 50 Here are some common parameters:
51 - 'period': Set event sampling period 51 - 'period': Set event sampling period
52 - 'freq': Set event sampling frequency 52 - 'freq': Set event sampling frequency
53 - 'time': Disable/enable time stamping. Acceptable values are 1 for 53 - 'time': Disable/enable time stamping. Acceptable values are 1 for
@@ -57,8 +57,11 @@ OPTIONS
57 FP mode, "dwarf" for DWARF mode, "lbr" for LBR mode and 57 FP mode, "dwarf" for DWARF mode, "lbr" for LBR mode and
58 "no" for disable callgraph. 58 "no" for disable callgraph.
59 - 'stack-size': user stack size for dwarf mode 59 - 'stack-size': user stack size for dwarf mode
60
61 See the linkperf:perf-list[1] man page for more parameters.
62
60 Note: If user explicitly sets options which conflict with the params, 63 Note: If user explicitly sets options which conflict with the params,
61 the value set by the params will be overridden. 64 the value set by the parameters will be overridden.
62 65
63 Also not defined in .../<pmu>/format/* are PMU driver specific 66 Also not defined in .../<pmu>/format/* are PMU driver specific
64 configuration parameters. Any configuration parameter preceded by 67 configuration parameters. Any configuration parameter preceded by
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 053bbbd84ece..c01904f388ce 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -117,7 +117,7 @@ OPTIONS
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
119 srcline, period, iregs, brstack, brstacksym, flags, bpf-output, 119 srcline, period, iregs, brstack, brstacksym, flags, bpf-output,
120 callindent. Field list can be prepended with the type, trace, sw or hw, 120 callindent, insn, insnlen. Field list can be prepended with the type, trace, sw or hw,
121 to indicate to which event type the field list applies. 121 to indicate to which event type the field list applies.
122 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace 122 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
123 123
@@ -181,6 +181,10 @@ OPTIONS
181 Instruction Trace decoding. For calls and returns, it will display the 181 Instruction Trace decoding. For calls and returns, it will display the
182 name of the symbol indented with spaces to reflect the stack depth. 182 name of the symbol indented with spaces to reflect the stack depth.
183 183
184 When doing instruction trace decoding insn and insnlen give the
185 instruction bytes and the instruction length of the current
186 instruction.
187
184 Finally, a user may not set fields to none for all event types. 188 Finally, a user may not set fields to none for all event types.
185 i.e., -F "" is not allowed. 189 i.e., -F "" is not allowed.
186 190
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 1ab0782369b1..781b019751a4 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -39,6 +39,11 @@ OPTIONS
39 Prefixing with ! shows all syscalls but the ones specified. You may 39 Prefixing with ! shows all syscalls but the ones specified. You may
40 need to escape it. 40 need to escape it.
41 41
42-D msecs::
43--delay msecs::
44After starting the program, wait msecs before measuring. This is useful to
45filter out the startup phase of the program, which is often very different.
46
42-o:: 47-o::
43--output=:: 48--output=::
44 Output file name. 49 Output file name.
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 0bda2cca2b3a..a511e5f31e36 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -51,6 +51,7 @@ tools/include/asm-generic/bitops/arch_hweight.h
51tools/include/asm-generic/bitops/atomic.h 51tools/include/asm-generic/bitops/atomic.h
52tools/include/asm-generic/bitops/const_hweight.h 52tools/include/asm-generic/bitops/const_hweight.h
53tools/include/asm-generic/bitops/__ffs.h 53tools/include/asm-generic/bitops/__ffs.h
54tools/include/asm-generic/bitops/__ffz.h
54tools/include/asm-generic/bitops/__fls.h 55tools/include/asm-generic/bitops/__fls.h
55tools/include/asm-generic/bitops/find.h 56tools/include/asm-generic/bitops/find.h
56tools/include/asm-generic/bitops/fls64.h 57tools/include/asm-generic/bitops/fls64.h
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 72edf83d76b7..cffdd9cf3ebf 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -366,7 +366,7 @@ ifndef NO_SDT
366endif 366endif
367 367
368ifdef PERF_HAVE_JITDUMP 368ifdef PERF_HAVE_JITDUMP
369 ifndef NO_DWARF 369 ifndef NO_LIBELF
370 $(call detected,CONFIG_JITDUMP) 370 $(call detected,CONFIG_JITDUMP)
371 CFLAGS += -DHAVE_JITDUMP 371 CFLAGS += -DHAVE_JITDUMP
372 endif 372 endif
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
index 47d584da5819..dfea6b635525 100644
--- a/tools/perf/arch/arm/util/cs-etm.c
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -575,8 +575,6 @@ static FILE *cs_device__open_file(const char *name)
575 snprintf(path, PATH_MAX, 575 snprintf(path, PATH_MAX,
576 "%s" CS_BUS_DEVICE_PATH "%s", sysfs, name); 576 "%s" CS_BUS_DEVICE_PATH "%s", sysfs, name);
577 577
578 printf("path: %s\n", path);
579
580 if (stat(path, &st) < 0) 578 if (stat(path, &st) < 0)
581 return NULL; 579 return NULL;
582 580
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index 555263e385c9..e9ce9c7c39b4 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -374,5 +374,5 @@
374543 x32 io_setup compat_sys_io_setup 374543 x32 io_setup compat_sys_io_setup
375544 x32 io_submit compat_sys_io_submit 375544 x32 io_submit compat_sys_io_submit
376545 x32 execveat compat_sys_execveat/ptregs 376545 x32 execveat compat_sys_execveat/ptregs
377534 x32 preadv2 compat_sys_preadv2 377546 x32 preadv2 compat_sys_preadv64v2
378535 x32 pwritev2 compat_sys_pwritev2 378547 x32 pwritev2 compat_sys_pwritev64v2
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index 8024cd5febd2..d9e5e80bb4d0 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -39,12 +39,15 @@ static unsigned int threads_starting;
39static struct stats throughput_stats; 39static struct stats throughput_stats;
40static pthread_cond_t thread_parent, thread_worker; 40static pthread_cond_t thread_parent, thread_worker;
41 41
42#define SMP_CACHE_BYTES 256
43#define __cacheline_aligned __attribute__ ((aligned (SMP_CACHE_BYTES)))
44
42struct worker { 45struct worker {
43 int tid; 46 int tid;
44 u_int32_t *futex; 47 u_int32_t *futex;
45 pthread_t thread; 48 pthread_t thread;
46 unsigned long ops; 49 unsigned long ops;
47}; 50} __cacheline_aligned;
48 51
49static const struct option options[] = { 52static const struct option options[] = {
50 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"), 53 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index c684910e5a48..52504a83b5a1 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -106,9 +106,10 @@ static double timeval2double(struct timeval *ts)
106 106
107struct bench_mem_info { 107struct bench_mem_info {
108 const struct function *functions; 108 const struct function *functions;
109 u64 (*do_cycles)(const struct function *r, size_t size); 109 u64 (*do_cycles)(const struct function *r, size_t size, void *src, void *dst);
110 double (*do_gettimeofday)(const struct function *r, size_t size); 110 double (*do_gettimeofday)(const struct function *r, size_t size, void *src, void *dst);
111 const char *const *usage; 111 const char *const *usage;
112 bool alloc_src;
112}; 113};
113 114
114static void __bench_mem_function(struct bench_mem_info *info, int r_idx, size_t size, double size_total) 115static void __bench_mem_function(struct bench_mem_info *info, int r_idx, size_t size, double size_total)
@@ -116,16 +117,26 @@ static void __bench_mem_function(struct bench_mem_info *info, int r_idx, size_t
116 const struct function *r = &info->functions[r_idx]; 117 const struct function *r = &info->functions[r_idx];
117 double result_bps = 0.0; 118 double result_bps = 0.0;
118 u64 result_cycles = 0; 119 u64 result_cycles = 0;
120 void *src = NULL, *dst = zalloc(size);
119 121
120 printf("# function '%s' (%s)\n", r->name, r->desc); 122 printf("# function '%s' (%s)\n", r->name, r->desc);
121 123
124 if (dst == NULL)
125 goto out_alloc_failed;
126
127 if (info->alloc_src) {
128 src = zalloc(size);
129 if (src == NULL)
130 goto out_alloc_failed;
131 }
132
122 if (bench_format == BENCH_FORMAT_DEFAULT) 133 if (bench_format == BENCH_FORMAT_DEFAULT)
123 printf("# Copying %s bytes ...\n\n", size_str); 134 printf("# Copying %s bytes ...\n\n", size_str);
124 135
125 if (use_cycles) { 136 if (use_cycles) {
126 result_cycles = info->do_cycles(r, size); 137 result_cycles = info->do_cycles(r, size, src, dst);
127 } else { 138 } else {
128 result_bps = info->do_gettimeofday(r, size); 139 result_bps = info->do_gettimeofday(r, size, src, dst);
129 } 140 }
130 141
131 switch (bench_format) { 142 switch (bench_format) {
@@ -149,6 +160,14 @@ static void __bench_mem_function(struct bench_mem_info *info, int r_idx, size_t
149 BUG_ON(1); 160 BUG_ON(1);
150 break; 161 break;
151 } 162 }
163
164out_free:
165 free(src);
166 free(dst);
167 return;
168out_alloc_failed:
169 printf("# Memory allocation failed - maybe size (%s) is too large?\n", size_str);
170 goto out_free;
152} 171}
153 172
154static int bench_mem_common(int argc, const char **argv, struct bench_mem_info *info) 173static int bench_mem_common(int argc, const char **argv, struct bench_mem_info *info)
@@ -201,28 +220,14 @@ static int bench_mem_common(int argc, const char **argv, struct bench_mem_info *
201 return 0; 220 return 0;
202} 221}
203 222
204static void memcpy_alloc_mem(void **dst, void **src, size_t size) 223static u64 do_memcpy_cycles(const struct function *r, size_t size, void *src, void *dst)
205{
206 *dst = zalloc(size);
207 if (!*dst)
208 die("memory allocation failed - maybe size is too large?\n");
209
210 *src = zalloc(size);
211 if (!*src)
212 die("memory allocation failed - maybe size is too large?\n");
213
214 /* Make sure to always prefault zero pages even if MMAP_THRESH is crossed: */
215 memset(*src, 0, size);
216}
217
218static u64 do_memcpy_cycles(const struct function *r, size_t size)
219{ 224{
220 u64 cycle_start = 0ULL, cycle_end = 0ULL; 225 u64 cycle_start = 0ULL, cycle_end = 0ULL;
221 void *src = NULL, *dst = NULL;
222 memcpy_t fn = r->fn.memcpy; 226 memcpy_t fn = r->fn.memcpy;
223 int i; 227 int i;
224 228
225 memcpy_alloc_mem(&dst, &src, size); 229 /* Make sure to always prefault zero pages even if MMAP_THRESH is crossed: */
230 memset(src, 0, size);
226 231
227 /* 232 /*
228 * We prefault the freshly allocated memory range here, 233 * We prefault the freshly allocated memory range here,
@@ -235,20 +240,15 @@ static u64 do_memcpy_cycles(const struct function *r, size_t size)
235 fn(dst, src, size); 240 fn(dst, src, size);
236 cycle_end = get_cycles(); 241 cycle_end = get_cycles();
237 242
238 free(src);
239 free(dst);
240 return cycle_end - cycle_start; 243 return cycle_end - cycle_start;
241} 244}
242 245
243static double do_memcpy_gettimeofday(const struct function *r, size_t size) 246static double do_memcpy_gettimeofday(const struct function *r, size_t size, void *src, void *dst)
244{ 247{
245 struct timeval tv_start, tv_end, tv_diff; 248 struct timeval tv_start, tv_end, tv_diff;
246 memcpy_t fn = r->fn.memcpy; 249 memcpy_t fn = r->fn.memcpy;
247 void *src = NULL, *dst = NULL;
248 int i; 250 int i;
249 251
250 memcpy_alloc_mem(&dst, &src, size);
251
252 /* 252 /*
253 * We prefault the freshly allocated memory range here, 253 * We prefault the freshly allocated memory range here,
254 * to not measure page fault overhead: 254 * to not measure page fault overhead:
@@ -262,9 +262,6 @@ static double do_memcpy_gettimeofday(const struct function *r, size_t size)
262 262
263 timersub(&tv_end, &tv_start, &tv_diff); 263 timersub(&tv_end, &tv_start, &tv_diff);
264 264
265 free(src);
266 free(dst);
267
268 return (double)(((double)size * nr_loops) / timeval2double(&tv_diff)); 265 return (double)(((double)size * nr_loops) / timeval2double(&tv_diff));
269} 266}
270 267
@@ -294,27 +291,18 @@ int bench_mem_memcpy(int argc, const char **argv, const char *prefix __maybe_unu
294 .do_cycles = do_memcpy_cycles, 291 .do_cycles = do_memcpy_cycles,
295 .do_gettimeofday = do_memcpy_gettimeofday, 292 .do_gettimeofday = do_memcpy_gettimeofday,
296 .usage = bench_mem_memcpy_usage, 293 .usage = bench_mem_memcpy_usage,
294 .alloc_src = true,
297 }; 295 };
298 296
299 return bench_mem_common(argc, argv, &info); 297 return bench_mem_common(argc, argv, &info);
300} 298}
301 299
302static void memset_alloc_mem(void **dst, size_t size) 300static u64 do_memset_cycles(const struct function *r, size_t size, void *src __maybe_unused, void *dst)
303{
304 *dst = zalloc(size);
305 if (!*dst)
306 die("memory allocation failed - maybe size is too large?\n");
307}
308
309static u64 do_memset_cycles(const struct function *r, size_t size)
310{ 301{
311 u64 cycle_start = 0ULL, cycle_end = 0ULL; 302 u64 cycle_start = 0ULL, cycle_end = 0ULL;
312 memset_t fn = r->fn.memset; 303 memset_t fn = r->fn.memset;
313 void *dst = NULL;
314 int i; 304 int i;
315 305
316 memset_alloc_mem(&dst, size);
317
318 /* 306 /*
319 * We prefault the freshly allocated memory range here, 307 * We prefault the freshly allocated memory range here,
320 * to not measure page fault overhead: 308 * to not measure page fault overhead:
@@ -326,19 +314,15 @@ static u64 do_memset_cycles(const struct function *r, size_t size)
326 fn(dst, i, size); 314 fn(dst, i, size);
327 cycle_end = get_cycles(); 315 cycle_end = get_cycles();
328 316
329 free(dst);
330 return cycle_end - cycle_start; 317 return cycle_end - cycle_start;
331} 318}
332 319
333static double do_memset_gettimeofday(const struct function *r, size_t size) 320static double do_memset_gettimeofday(const struct function *r, size_t size, void *src __maybe_unused, void *dst)
334{ 321{
335 struct timeval tv_start, tv_end, tv_diff; 322 struct timeval tv_start, tv_end, tv_diff;
336 memset_t fn = r->fn.memset; 323 memset_t fn = r->fn.memset;
337 void *dst = NULL;
338 int i; 324 int i;
339 325
340 memset_alloc_mem(&dst, size);
341
342 /* 326 /*
343 * We prefault the freshly allocated memory range here, 327 * We prefault the freshly allocated memory range here,
344 * to not measure page fault overhead: 328 * to not measure page fault overhead:
@@ -352,7 +336,6 @@ static double do_memset_gettimeofday(const struct function *r, size_t size)
352 336
353 timersub(&tv_end, &tv_start, &tv_diff); 337 timersub(&tv_end, &tv_start, &tv_diff);
354 338
355 free(dst);
356 return (double)(((double)size * nr_loops) / timeval2double(&tv_diff)); 339 return (double)(((double)size * nr_loops) / timeval2double(&tv_diff));
357} 340}
358 341
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 6e88460cd13d..8064de8ceedc 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -207,11 +207,14 @@ static int process_read_event(struct perf_tool *tool,
207 207
208 if (rep->show_threads) { 208 if (rep->show_threads) {
209 const char *name = evsel ? perf_evsel__name(evsel) : "unknown"; 209 const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
210 perf_read_values_add_value(&rep->show_threads_values, 210 int err = perf_read_values_add_value(&rep->show_threads_values,
211 event->read.pid, event->read.tid, 211 event->read.pid, event->read.tid,
212 event->read.id, 212 event->read.id,
213 name, 213 name,
214 event->read.value); 214 event->read.value);
215
216 if (err)
217 return err;
215 } 218 }
216 219
217 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid, 220 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
@@ -539,8 +542,11 @@ static int __cmd_report(struct report *rep)
539 } 542 }
540 } 543 }
541 544
542 if (rep->show_threads) 545 if (rep->show_threads) {
543 perf_read_values_init(&rep->show_threads_values); 546 ret = perf_read_values_init(&rep->show_threads_values);
547 if (ret)
548 return ret;
549 }
544 550
545 ret = report__setup_sample_type(rep); 551 ret = report__setup_sample_type(rep);
546 if (ret) { 552 if (ret) {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 7228d141a789..412fb6e65ac0 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -66,6 +66,8 @@ enum perf_output_field {
66 PERF_OUTPUT_WEIGHT = 1U << 18, 66 PERF_OUTPUT_WEIGHT = 1U << 18,
67 PERF_OUTPUT_BPF_OUTPUT = 1U << 19, 67 PERF_OUTPUT_BPF_OUTPUT = 1U << 19,
68 PERF_OUTPUT_CALLINDENT = 1U << 20, 68 PERF_OUTPUT_CALLINDENT = 1U << 20,
69 PERF_OUTPUT_INSN = 1U << 21,
70 PERF_OUTPUT_INSNLEN = 1U << 22,
69}; 71};
70 72
71struct output_option { 73struct output_option {
@@ -93,6 +95,8 @@ struct output_option {
93 {.str = "weight", .field = PERF_OUTPUT_WEIGHT}, 95 {.str = "weight", .field = PERF_OUTPUT_WEIGHT},
94 {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT}, 96 {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT},
95 {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT}, 97 {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
98 {.str = "insn", .field = PERF_OUTPUT_INSN},
99 {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
96}; 100};
97 101
98/* default set to maintain compatibility with current format */ 102/* default set to maintain compatibility with current format */
@@ -624,6 +628,20 @@ static void print_sample_callindent(struct perf_sample *sample,
624 printf("%*s", spacing - len, ""); 628 printf("%*s", spacing - len, "");
625} 629}
626 630
631static void print_insn(struct perf_sample *sample,
632 struct perf_event_attr *attr)
633{
634 if (PRINT_FIELD(INSNLEN))
635 printf(" ilen: %d", sample->insn_len);
636 if (PRINT_FIELD(INSN)) {
637 int i;
638
639 printf(" insn:");
640 for (i = 0; i < sample->insn_len; i++)
641 printf(" %02x", (unsigned char)sample->insn[i]);
642 }
643}
644
627static void print_sample_bts(struct perf_sample *sample, 645static void print_sample_bts(struct perf_sample *sample,
628 struct perf_evsel *evsel, 646 struct perf_evsel *evsel,
629 struct thread *thread, 647 struct thread *thread,
@@ -668,6 +686,8 @@ static void print_sample_bts(struct perf_sample *sample,
668 if (print_srcline_last) 686 if (print_srcline_last)
669 map__fprintf_srcline(al->map, al->addr, "\n ", stdout); 687 map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
670 688
689 print_insn(sample, attr);
690
671 printf("\n"); 691 printf("\n");
672} 692}
673 693
@@ -911,7 +931,7 @@ static void process_event(struct perf_script *script,
911 931
912 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) 932 if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
913 print_sample_bpf_output(sample); 933 print_sample_bpf_output(sample);
914 934 print_insn(sample, attr);
915 printf("\n"); 935 printf("\n");
916} 936}
917 937
@@ -2124,7 +2144,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2124 "Valid types: hw,sw,trace,raw. " 2144 "Valid types: hw,sw,trace,raw. "
2125 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 2145 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
2126 "addr,symoff,period,iregs,brstack,brstacksym,flags," 2146 "addr,symoff,period,iregs,brstack,brstacksym,flags,"
2127 "bpf-output,callindent", parse_output_fields), 2147 "bpf-output,callindent,insn,insnlen", parse_output_fields),
2128 OPT_BOOLEAN('a', "all-cpus", &system_wide, 2148 OPT_BOOLEAN('a', "all-cpus", &system_wide,
2129 "system-wide collection from all CPUs"), 2149 "system-wide collection from all CPUs"),
2130 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 2150 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index c298bd3e1d90..5f45166c892d 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -843,7 +843,6 @@ static size_t fprintf_duration(unsigned long t, FILE *fp)
843 */ 843 */
844struct thread_trace { 844struct thread_trace {
845 u64 entry_time; 845 u64 entry_time;
846 u64 exit_time;
847 bool entry_pending; 846 bool entry_pending;
848 unsigned long nr_events; 847 unsigned long nr_events;
849 unsigned long pfmaj, pfmin; 848 unsigned long pfmaj, pfmin;
@@ -1452,7 +1451,7 @@ static int trace__printf_interrupted_entry(struct trace *trace, struct perf_samp
1452 1451
1453 duration = sample->time - ttrace->entry_time; 1452 duration = sample->time - ttrace->entry_time;
1454 1453
1455 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output); 1454 printed = trace__fprintf_entry_head(trace, trace->current, duration, ttrace->entry_time, trace->output);
1456 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str); 1455 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1457 ttrace->entry_pending = false; 1456 ttrace->entry_pending = false;
1458 1457
@@ -1499,7 +1498,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1499 1498
1500 if (sc->is_exit) { 1499 if (sc->is_exit) {
1501 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { 1500 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
1502 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output); 1501 trace__fprintf_entry_head(trace, thread, 1, ttrace->entry_time, trace->output);
1503 fprintf(trace->output, "%-70s)\n", ttrace->entry_str); 1502 fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
1504 } 1503 }
1505 } else { 1504 } else {
@@ -1571,8 +1570,6 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1571 ++trace->stats.vfs_getname; 1570 ++trace->stats.vfs_getname;
1572 } 1571 }
1573 1572
1574 ttrace->exit_time = sample->time;
1575
1576 if (ttrace->entry_time) { 1573 if (ttrace->entry_time) {
1577 duration = sample->time - ttrace->entry_time; 1574 duration = sample->time - ttrace->entry_time;
1578 if (trace__filter_duration(trace, duration)) 1575 if (trace__filter_duration(trace, duration))
@@ -1592,7 +1589,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1592 if (trace->summary_only) 1589 if (trace->summary_only)
1593 goto out; 1590 goto out;
1594 1591
1595 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output); 1592 trace__fprintf_entry_head(trace, thread, duration, ttrace->entry_time, trace->output);
1596 1593
1597 if (ttrace->entry_pending) { 1594 if (ttrace->entry_pending) {
1598 fprintf(trace->output, "%-70s", ttrace->entry_str); 1595 fprintf(trace->output, "%-70s", ttrace->entry_str);
@@ -2310,12 +2307,17 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2310 if (err < 0) 2307 if (err < 0)
2311 goto out_error_mmap; 2308 goto out_error_mmap;
2312 2309
2313 if (!target__none(&trace->opts.target)) 2310 if (!target__none(&trace->opts.target) && !trace->opts.initial_delay)
2314 perf_evlist__enable(evlist); 2311 perf_evlist__enable(evlist);
2315 2312
2316 if (forks) 2313 if (forks)
2317 perf_evlist__start_workload(evlist); 2314 perf_evlist__start_workload(evlist);
2318 2315
2316 if (trace->opts.initial_delay) {
2317 usleep(trace->opts.initial_delay * 1000);
2318 perf_evlist__enable(evlist);
2319 }
2320
2319 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 || 2321 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
2320 evlist->threads->nr > 1 || 2322 evlist->threads->nr > 1 ||
2321 perf_evlist__first(evlist)->attr.inherit; 2323 perf_evlist__first(evlist)->attr.inherit;
@@ -2816,6 +2818,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2816 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)), 2818 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
2817 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, 2819 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
2818 "per thread proc mmap processing timeout in ms"), 2820 "per thread proc mmap processing timeout in ms"),
2821 OPT_UINTEGER('D', "delay", &trace.opts.initial_delay,
2822 "ms to wait before starting measurement after program "
2823 "start"),
2819 OPT_END() 2824 OPT_END()
2820 }; 2825 };
2821 bool __maybe_unused max_stack_user_set = true; 2826 bool __maybe_unused max_stack_user_set = true;
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c
index 55daefff0d54..e9651a9d670e 100644
--- a/tools/perf/jvmti/jvmti_agent.c
+++ b/tools/perf/jvmti/jvmti_agent.c
@@ -44,11 +44,6 @@
44static char jit_path[PATH_MAX]; 44static char jit_path[PATH_MAX];
45static void *marker_addr; 45static void *marker_addr;
46 46
47/*
48 * padding buffer
49 */
50static const char pad_bytes[7];
51
52static inline pid_t gettid(void) 47static inline pid_t gettid(void)
53{ 48{
54 return (pid_t)syscall(__NR_gettid); 49 return (pid_t)syscall(__NR_gettid);
@@ -230,7 +225,6 @@ init_arch_timestamp(void)
230 225
231void *jvmti_open(void) 226void *jvmti_open(void)
232{ 227{
233 int pad_cnt;
234 char dump_path[PATH_MAX]; 228 char dump_path[PATH_MAX];
235 struct jitheader header; 229 struct jitheader header;
236 int fd; 230 int fd;
@@ -288,10 +282,6 @@ void *jvmti_open(void)
288 header.total_size = sizeof(header); 282 header.total_size = sizeof(header);
289 header.pid = getpid(); 283 header.pid = getpid();
290 284
291 /* calculate amount of padding '\0' */
292 pad_cnt = PADDING_8ALIGNED(header.total_size);
293 header.total_size += pad_cnt;
294
295 header.timestamp = perf_get_timestamp(); 285 header.timestamp = perf_get_timestamp();
296 286
297 if (use_arch_timestamp) 287 if (use_arch_timestamp)
@@ -301,13 +291,6 @@ void *jvmti_open(void)
301 warn("jvmti: cannot write dumpfile header"); 291 warn("jvmti: cannot write dumpfile header");
302 goto error; 292 goto error;
303 } 293 }
304
305 /* write padding '\0' if necessary */
306 if (pad_cnt && !fwrite(pad_bytes, pad_cnt, 1, fp)) {
307 warn("jvmti: cannot write dumpfile header padding");
308 goto error;
309 }
310
311 return fp; 294 return fp;
312error: 295error:
313 fclose(fp); 296 fclose(fp);
@@ -349,7 +332,6 @@ jvmti_write_code(void *agent, char const *sym,
349 static int code_generation = 1; 332 static int code_generation = 1;
350 struct jr_code_load rec; 333 struct jr_code_load rec;
351 size_t sym_len; 334 size_t sym_len;
352 size_t padding_count;
353 FILE *fp = agent; 335 FILE *fp = agent;
354 int ret = -1; 336 int ret = -1;
355 337
@@ -366,8 +348,6 @@ jvmti_write_code(void *agent, char const *sym,
366 348
367 rec.p.id = JIT_CODE_LOAD; 349 rec.p.id = JIT_CODE_LOAD;
368 rec.p.total_size = sizeof(rec) + sym_len; 350 rec.p.total_size = sizeof(rec) + sym_len;
369 padding_count = PADDING_8ALIGNED(rec.p.total_size);
370 rec.p. total_size += padding_count;
371 rec.p.timestamp = perf_get_timestamp(); 351 rec.p.timestamp = perf_get_timestamp();
372 352
373 rec.code_size = size; 353 rec.code_size = size;
@@ -393,9 +373,6 @@ jvmti_write_code(void *agent, char const *sym,
393 ret = fwrite_unlocked(&rec, sizeof(rec), 1, fp); 373 ret = fwrite_unlocked(&rec, sizeof(rec), 1, fp);
394 fwrite_unlocked(sym, sym_len, 1, fp); 374 fwrite_unlocked(sym, sym_len, 1, fp);
395 375
396 if (padding_count)
397 fwrite_unlocked(pad_bytes, padding_count, 1, fp);
398
399 if (code) 376 if (code)
400 fwrite_unlocked(code, size, 1, fp); 377 fwrite_unlocked(code, size, 1, fp);
401 378
@@ -412,7 +389,6 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
412{ 389{
413 struct jr_code_debug_info rec; 390 struct jr_code_debug_info rec;
414 size_t sret, len, size, flen; 391 size_t sret, len, size, flen;
415 size_t padding_count;
416 uint64_t addr; 392 uint64_t addr;
417 const char *fn = file; 393 const char *fn = file;
418 FILE *fp = agent; 394 FILE *fp = agent;
@@ -443,16 +419,10 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
443 * int : line number 419 * int : line number
444 * int : column discriminator 420 * int : column discriminator
445 * file[] : source file name 421 * file[] : source file name
446 * padding : pad to multiple of 8 bytes
447 */ 422 */
448 size += nr_lines * sizeof(struct debug_entry); 423 size += nr_lines * sizeof(struct debug_entry);
449 size += flen * nr_lines; 424 size += flen * nr_lines;
450 /* 425 rec.p.total_size = size;
451 * pad to 8 bytes
452 */
453 padding_count = PADDING_8ALIGNED(size);
454
455 rec.p.total_size = size + padding_count;
456 426
457 /* 427 /*
458 * If JVM is multi-threaded, nultiple concurrent calls to agent 428 * If JVM is multi-threaded, nultiple concurrent calls to agent
@@ -486,12 +456,6 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
486 if (sret != 1) 456 if (sret != 1)
487 goto error; 457 goto error;
488 } 458 }
489 if (padding_count) {
490 sret = fwrite_unlocked(pad_bytes, padding_count, 1, fp);
491 if (sret != 1)
492 goto error;
493 }
494
495 funlockfile(fp); 459 funlockfile(fp);
496 return 0; 460 return 0;
497error: 461error:
diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c
index ac12e4b91a92..5612641c69b4 100644
--- a/tools/perf/jvmti/libjvmti.c
+++ b/tools/perf/jvmti/libjvmti.c
@@ -12,6 +12,19 @@
12static int has_line_numbers; 12static int has_line_numbers;
13void *jvmti_agent; 13void *jvmti_agent;
14 14
15static void print_error(jvmtiEnv *jvmti, const char *msg, jvmtiError ret)
16{
17 char *err_msg = NULL;
18 jvmtiError err;
19 err = (*jvmti)->GetErrorName(jvmti, ret, &err_msg);
20 if (err == JVMTI_ERROR_NONE) {
21 warnx("%s failed with %s", msg, err_msg);
22 (*jvmti)->Deallocate(jvmti, (unsigned char *)err_msg);
23 } else {
24 warnx("%s failed with an unknown error %d", msg, ret);
25 }
26}
27
15static jvmtiError 28static jvmtiError
16do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci, 29do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci,
17 jvmti_line_info_t *tab, jint *nr) 30 jvmti_line_info_t *tab, jint *nr)
@@ -22,8 +35,10 @@ do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci,
22 jvmtiError ret; 35 jvmtiError ret;
23 36
24 ret = (*jvmti)->GetLineNumberTable(jvmti, m, &nr_lines, &loc_tab); 37 ret = (*jvmti)->GetLineNumberTable(jvmti, m, &nr_lines, &loc_tab);
25 if (ret != JVMTI_ERROR_NONE) 38 if (ret != JVMTI_ERROR_NONE) {
39 print_error(jvmti, "GetLineNumberTable", ret);
26 return ret; 40 return ret;
41 }
27 42
28 for (i = 0; i < nr_lines; i++) { 43 for (i = 0; i < nr_lines; i++) {
29 if (loc_tab[i].start_location < bci) { 44 if (loc_tab[i].start_location < bci) {
@@ -71,6 +86,8 @@ get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t **
71 /* free what was allocated for nothing */ 86 /* free what was allocated for nothing */
72 (*jvmti)->Deallocate(jvmti, (unsigned char *)lne); 87 (*jvmti)->Deallocate(jvmti, (unsigned char *)lne);
73 nr_total += (int)nr; 88 nr_total += (int)nr;
89 } else {
90 print_error(jvmti, "GetLineNumberTable", ret);
74 } 91 }
75 } 92 }
76 } 93 }
@@ -130,7 +147,7 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
130 ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method, 147 ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method,
131 &decl_class); 148 &decl_class);
132 if (ret != JVMTI_ERROR_NONE) { 149 if (ret != JVMTI_ERROR_NONE) {
133 warnx("jvmti: cannot get declaring class"); 150 print_error(jvmti, "GetMethodDeclaringClass", ret);
134 return; 151 return;
135 } 152 }
136 153
@@ -144,21 +161,21 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
144 161
145 ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name); 162 ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name);
146 if (ret != JVMTI_ERROR_NONE) { 163 if (ret != JVMTI_ERROR_NONE) {
147 warnx("jvmti: cannot get source filename ret=%d", ret); 164 print_error(jvmti, "GetSourceFileName", ret);
148 goto error; 165 goto error;
149 } 166 }
150 167
151 ret = (*jvmti)->GetClassSignature(jvmti, decl_class, 168 ret = (*jvmti)->GetClassSignature(jvmti, decl_class,
152 &class_sign, NULL); 169 &class_sign, NULL);
153 if (ret != JVMTI_ERROR_NONE) { 170 if (ret != JVMTI_ERROR_NONE) {
154 warnx("jvmti: getclassignature failed"); 171 print_error(jvmti, "GetClassSignature", ret);
155 goto error; 172 goto error;
156 } 173 }
157 174
158 ret = (*jvmti)->GetMethodName(jvmti, method, &func_name, 175 ret = (*jvmti)->GetMethodName(jvmti, method, &func_name,
159 &func_sign, NULL); 176 &func_sign, NULL);
160 if (ret != JVMTI_ERROR_NONE) { 177 if (ret != JVMTI_ERROR_NONE) {
161 warnx("jvmti: failed getmethodname"); 178 print_error(jvmti, "GetMethodName", ret);
162 goto error; 179 goto error;
163 } 180 }
164 181
@@ -253,7 +270,7 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused)
253 270
254 ret = (*jvmti)->AddCapabilities(jvmti, &caps1); 271 ret = (*jvmti)->AddCapabilities(jvmti, &caps1);
255 if (ret != JVMTI_ERROR_NONE) { 272 if (ret != JVMTI_ERROR_NONE) {
256 warnx("jvmti: acquire compiled_method capability failed"); 273 print_error(jvmti, "AddCapabilities", ret);
257 return -1; 274 return -1;
258 } 275 }
259 ret = (*jvmti)->GetJLocationFormat(jvmti, &format); 276 ret = (*jvmti)->GetJLocationFormat(jvmti, &format);
@@ -264,7 +281,9 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused)
264 ret = (*jvmti)->AddCapabilities(jvmti, &caps1); 281 ret = (*jvmti)->AddCapabilities(jvmti, &caps1);
265 if (ret == JVMTI_ERROR_NONE) 282 if (ret == JVMTI_ERROR_NONE)
266 has_line_numbers = 1; 283 has_line_numbers = 1;
267 } 284 } else if (ret != JVMTI_ERROR_NONE)
285 print_error(jvmti, "GetJLocationFormat", ret);
286
268 287
269 memset(&cb, 0, sizeof(cb)); 288 memset(&cb, 0, sizeof(cb));
270 289
@@ -273,21 +292,21 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused)
273 292
274 ret = (*jvmti)->SetEventCallbacks(jvmti, &cb, sizeof(cb)); 293 ret = (*jvmti)->SetEventCallbacks(jvmti, &cb, sizeof(cb));
275 if (ret != JVMTI_ERROR_NONE) { 294 if (ret != JVMTI_ERROR_NONE) {
276 warnx("jvmti: cannot set event callbacks"); 295 print_error(jvmti, "SetEventCallbacks", ret);
277 return -1; 296 return -1;
278 } 297 }
279 298
280 ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, 299 ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
281 JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL); 300 JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL);
282 if (ret != JVMTI_ERROR_NONE) { 301 if (ret != JVMTI_ERROR_NONE) {
283 warnx("jvmti: setnotification failed for method_load"); 302 print_error(jvmti, "SetEventNotificationMode(METHOD_LOAD)", ret);
284 return -1; 303 return -1;
285 } 304 }
286 305
287 ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, 306 ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
288 JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL); 307 JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL);
289 if (ret != JVMTI_ERROR_NONE) { 308 if (ret != JVMTI_ERROR_NONE) {
290 warnx("jvmti: setnotification failed on code_generated"); 309 print_error(jvmti, "SetEventNotificationMode(CODE_GENERATED)", ret);
291 return -1; 310 return -1;
292 } 311 }
293 return 0; 312 return 0;
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index e6d1816e431a..42e892b1e979 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -97,7 +97,7 @@ int test__backward_ring_buffer(int subtest __maybe_unused)
97 97
98 evlist = perf_evlist__new(); 98 evlist = perf_evlist__new();
99 if (!evlist) { 99 if (!evlist) {
100 pr_debug("No enough memory to create evlist\n"); 100 pr_debug("Not enough memory to create evlist\n");
101 return TEST_FAIL; 101 return TEST_FAIL;
102 } 102 }
103 103
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index 2673e86ed50f..8f0298aff222 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -125,7 +125,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
125 /* Instead of perf_evlist__new_default, don't add default events */ 125 /* Instead of perf_evlist__new_default, don't add default events */
126 evlist = perf_evlist__new(); 126 evlist = perf_evlist__new();
127 if (!evlist) { 127 if (!evlist) {
128 pr_debug("No enough memory to create evlist\n"); 128 pr_debug("Not enough memory to create evlist\n");
129 return TEST_FAIL; 129 return TEST_FAIL;
130 } 130 }
131 131
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 31d6d5a7c2dc..ddc4c3e59cc1 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -2807,7 +2807,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2807 do_zoom_dso(browser, actions); 2807 do_zoom_dso(browser, actions);
2808 continue; 2808 continue;
2809 case 'V': 2809 case 'V':
2810 browser->show_dso = !browser->show_dso; 2810 verbose = (verbose + 1) % 4;
2811 browser->show_dso = verbose > 0;
2812 ui_helpline__fpush("Verbosity level set to %d\n",
2813 verbose);
2811 continue; 2814 continue;
2812 case 't': 2815 case 't':
2813 actions->thread = thread; 2816 actions->thread = thread;
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index eb60e613d795..1dc67efad634 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -120,7 +120,7 @@ libperf-y += demangle-rust.o
120ifdef CONFIG_JITDUMP 120ifdef CONFIG_JITDUMP
121libperf-$(CONFIG_LIBELF) += jitdump.o 121libperf-$(CONFIG_LIBELF) += jitdump.o
122libperf-$(CONFIG_LIBELF) += genelf.o 122libperf-$(CONFIG_LIBELF) += genelf.o
123libperf-$(CONFIG_LIBELF) += genelf_debug.o 123libperf-$(CONFIG_DWARF) += genelf_debug.o
124endif 124endif
125 125
126CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 126CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 2b2c9b82f5ab..a5fd275238f7 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -241,7 +241,7 @@ parse_prog_config_kvpair(const char *config_str, struct perf_probe_event *pev)
241 int err = 0; 241 int err = 0;
242 242
243 if (!text) { 243 if (!text) {
244 pr_debug("No enough memory: dup config_str failed\n"); 244 pr_debug("Not enough memory: dup config_str failed\n");
245 return ERR_PTR(-ENOMEM); 245 return ERR_PTR(-ENOMEM);
246 } 246 }
247 247
@@ -531,7 +531,7 @@ static int map_prologue(struct perf_probe_event *pev, int *mapping,
531 531
532 ptevs = malloc(array_sz); 532 ptevs = malloc(array_sz);
533 if (!ptevs) { 533 if (!ptevs) {
534 pr_debug("No enough memory: alloc ptevs failed\n"); 534 pr_debug("Not enough memory: alloc ptevs failed\n");
535 return -ENOMEM; 535 return -ENOMEM;
536 } 536 }
537 537
@@ -604,13 +604,13 @@ static int hook_load_preprocessor(struct bpf_program *prog)
604 priv->need_prologue = true; 604 priv->need_prologue = true;
605 priv->insns_buf = malloc(sizeof(struct bpf_insn) * BPF_MAXINSNS); 605 priv->insns_buf = malloc(sizeof(struct bpf_insn) * BPF_MAXINSNS);
606 if (!priv->insns_buf) { 606 if (!priv->insns_buf) {
607 pr_debug("No enough memory: alloc insns_buf failed\n"); 607 pr_debug("Not enough memory: alloc insns_buf failed\n");
608 return -ENOMEM; 608 return -ENOMEM;
609 } 609 }
610 610
611 priv->type_mapping = malloc(sizeof(int) * pev->ntevs); 611 priv->type_mapping = malloc(sizeof(int) * pev->ntevs);
612 if (!priv->type_mapping) { 612 if (!priv->type_mapping) {
613 pr_debug("No enough memory: alloc type_mapping failed\n"); 613 pr_debug("Not enough memory: alloc type_mapping failed\n");
614 return -ENOMEM; 614 return -ENOMEM;
615 } 615 }
616 memset(priv->type_mapping, -1, 616 memset(priv->type_mapping, -1,
@@ -864,7 +864,7 @@ bpf_map_op_setkey(struct bpf_map_op *op, struct parse_events_term *term)
864 864
865 op->k.array.ranges = memdup(term->array.ranges, memsz); 865 op->k.array.ranges = memdup(term->array.ranges, memsz);
866 if (!op->k.array.ranges) { 866 if (!op->k.array.ranges) {
867 pr_debug("No enough memory to alloc indices for map\n"); 867 pr_debug("Not enough memory to alloc indices for map\n");
868 return -ENOMEM; 868 return -ENOMEM;
869 } 869 }
870 op->key_type = BPF_MAP_KEY_RANGES; 870 op->key_type = BPF_MAP_KEY_RANGES;
@@ -929,7 +929,7 @@ bpf_map_priv__clone(struct bpf_map_priv *priv)
929 929
930 newpriv = zalloc(sizeof(*newpriv)); 930 newpriv = zalloc(sizeof(*newpriv));
931 if (!newpriv) { 931 if (!newpriv) {
932 pr_debug("No enough memory to alloc map private\n"); 932 pr_debug("Not enough memory to alloc map private\n");
933 return NULL; 933 return NULL;
934 } 934 }
935 INIT_LIST_HEAD(&newpriv->ops_list); 935 INIT_LIST_HEAD(&newpriv->ops_list);
@@ -960,7 +960,7 @@ bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op)
960 if (!priv) { 960 if (!priv) {
961 priv = zalloc(sizeof(*priv)); 961 priv = zalloc(sizeof(*priv));
962 if (!priv) { 962 if (!priv) {
963 pr_debug("No enough memory to alloc map private\n"); 963 pr_debug("Not enough memory to alloc map private\n");
964 return -ENOMEM; 964 return -ENOMEM;
965 } 965 }
966 INIT_LIST_HEAD(&priv->ops_list); 966 INIT_LIST_HEAD(&priv->ops_list);
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8d363d5e65a2..c735c53a26f8 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -177,6 +177,8 @@ enum {
177 PERF_IP_FLAG_TRACE_BEGIN |\ 177 PERF_IP_FLAG_TRACE_BEGIN |\
178 PERF_IP_FLAG_TRACE_END) 178 PERF_IP_FLAG_TRACE_END)
179 179
180#define MAX_INSN 16
181
180struct perf_sample { 182struct perf_sample {
181 u64 ip; 183 u64 ip;
182 u32 pid, tid; 184 u32 pid, tid;
@@ -193,6 +195,7 @@ struct perf_sample {
193 u32 flags; 195 u32 flags;
194 u16 insn_len; 196 u16 insn_len;
195 u8 cpumode; 197 u8 cpumode;
198 char insn[MAX_INSN];
196 void *raw_data; 199 void *raw_data;
197 struct ip_callchain *callchain; 200 struct ip_callchain *callchain;
198 struct branch_stack *branch_stack; 201 struct branch_stack *branch_stack;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 8bc271141d9d..e58a2fbf3b16 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -28,6 +28,7 @@
28#include "debug.h" 28#include "debug.h"
29#include "trace-event.h" 29#include "trace-event.h"
30#include "stat.h" 30#include "stat.h"
31#include "util/parse-branch-options.h"
31 32
32static struct { 33static struct {
33 bool sample_id_all; 34 bool sample_id_all;
@@ -708,6 +709,14 @@ static void apply_config_terms(struct perf_evsel *evsel,
708 case PERF_EVSEL__CONFIG_TERM_CALLGRAPH: 709 case PERF_EVSEL__CONFIG_TERM_CALLGRAPH:
709 callgraph_buf = term->val.callgraph; 710 callgraph_buf = term->val.callgraph;
710 break; 711 break;
712 case PERF_EVSEL__CONFIG_TERM_BRANCH:
713 if (term->val.branch && strcmp(term->val.branch, "no")) {
714 perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
715 parse_branch_str(term->val.branch,
716 &attr->branch_sample_type);
717 } else
718 perf_evsel__reset_sample_bit(evsel, BRANCH_STACK);
719 break;
711 case PERF_EVSEL__CONFIG_TERM_STACK_USER: 720 case PERF_EVSEL__CONFIG_TERM_STACK_USER:
712 dump_size = term->val.stack_user; 721 dump_size = term->val.stack_user;
713 break; 722 break;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b1503b0ecdff..8cd7cd227483 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -47,6 +47,7 @@ enum {
47 PERF_EVSEL__CONFIG_TERM_MAX_STACK, 47 PERF_EVSEL__CONFIG_TERM_MAX_STACK,
48 PERF_EVSEL__CONFIG_TERM_OVERWRITE, 48 PERF_EVSEL__CONFIG_TERM_OVERWRITE,
49 PERF_EVSEL__CONFIG_TERM_DRV_CFG, 49 PERF_EVSEL__CONFIG_TERM_DRV_CFG,
50 PERF_EVSEL__CONFIG_TERM_BRANCH,
50 PERF_EVSEL__CONFIG_TERM_MAX, 51 PERF_EVSEL__CONFIG_TERM_MAX,
51}; 52};
52 53
@@ -63,6 +64,7 @@ struct perf_evsel_config_term {
63 int max_stack; 64 int max_stack;
64 bool inherit; 65 bool inherit;
65 bool overwrite; 66 bool overwrite;
67 char *branch;
66 } val; 68 } val;
67}; 69};
68 70
diff --git a/tools/perf/util/genelf.c b/tools/perf/util/genelf.c
index c1ef805c6a8f..c540d47583e7 100644
--- a/tools/perf/util/genelf.c
+++ b/tools/perf/util/genelf.c
@@ -19,12 +19,18 @@
19#include <limits.h> 19#include <limits.h>
20#include <fcntl.h> 20#include <fcntl.h>
21#include <err.h> 21#include <err.h>
22#ifdef HAVE_DWARF_SUPPORT
22#include <dwarf.h> 23#include <dwarf.h>
24#endif
23 25
24#include "perf.h" 26#include "perf.h"
25#include "genelf.h" 27#include "genelf.h"
26#include "../util/jitdump.h" 28#include "../util/jitdump.h"
27 29
30#ifndef NT_GNU_BUILD_ID
31#define NT_GNU_BUILD_ID 3
32#endif
33
28#define JVMTI 34#define JVMTI
29 35
30#define BUILD_ID_URANDOM /* different uuid for each run */ 36#define BUILD_ID_URANDOM /* different uuid for each run */
@@ -67,6 +73,8 @@ static char shd_string_table[] = {
67 '.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */ 73 '.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */
68 '.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */ 74 '.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */
69 '.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */ 75 '.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */
76 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', '_', 'h', 'd', 'r', 0, /* 90 */
77 '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0, /* 104 */
70}; 78};
71 79
72static struct buildid_note { 80static struct buildid_note {
@@ -147,6 +155,86 @@ gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *cod
147} 155}
148#endif 156#endif
149 157
158static int
159jit_add_eh_frame_info(Elf *e, void* unwinding, uint64_t unwinding_header_size,
160 uint64_t unwinding_size, uint64_t base_offset)
161{
162 Elf_Data *d;
163 Elf_Scn *scn;
164 Elf_Shdr *shdr;
165 uint64_t unwinding_table_size = unwinding_size - unwinding_header_size;
166
167 /*
168 * setup eh_frame section
169 */
170 scn = elf_newscn(e);
171 if (!scn) {
172 warnx("cannot create section");
173 return -1;
174 }
175
176 d = elf_newdata(scn);
177 if (!d) {
178 warnx("cannot get new data");
179 return -1;
180 }
181
182 d->d_align = 8;
183 d->d_off = 0LL;
184 d->d_buf = unwinding;
185 d->d_type = ELF_T_BYTE;
186 d->d_size = unwinding_table_size;
187 d->d_version = EV_CURRENT;
188
189 shdr = elf_getshdr(scn);
190 if (!shdr) {
191 warnx("cannot get section header");
192 return -1;
193 }
194
195 shdr->sh_name = 104;
196 shdr->sh_type = SHT_PROGBITS;
197 shdr->sh_addr = base_offset;
198 shdr->sh_flags = SHF_ALLOC;
199 shdr->sh_entsize = 0;
200
201 /*
202 * setup eh_frame_hdr section
203 */
204 scn = elf_newscn(e);
205 if (!scn) {
206 warnx("cannot create section");
207 return -1;
208 }
209
210 d = elf_newdata(scn);
211 if (!d) {
212 warnx("cannot get new data");
213 return -1;
214 }
215
216 d->d_align = 4;
217 d->d_off = 0LL;
218 d->d_buf = unwinding + unwinding_table_size;
219 d->d_type = ELF_T_BYTE;
220 d->d_size = unwinding_header_size;
221 d->d_version = EV_CURRENT;
222
223 shdr = elf_getshdr(scn);
224 if (!shdr) {
225 warnx("cannot get section header");
226 return -1;
227 }
228
229 shdr->sh_name = 90;
230 shdr->sh_type = SHT_PROGBITS;
231 shdr->sh_addr = base_offset + unwinding_table_size;
232 shdr->sh_flags = SHF_ALLOC;
233 shdr->sh_entsize = 0;
234
235 return 0;
236}
237
150/* 238/*
151 * fd: file descriptor open for writing for the output file 239 * fd: file descriptor open for writing for the output file
152 * load_addr: code load address (could be zero, just used for buildid) 240 * load_addr: code load address (could be zero, just used for buildid)
@@ -157,13 +245,15 @@ gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *cod
157int 245int
158jit_write_elf(int fd, uint64_t load_addr, const char *sym, 246jit_write_elf(int fd, uint64_t load_addr, const char *sym,
159 const void *code, int csize, 247 const void *code, int csize,
160 void *debug, int nr_debug_entries) 248 void *debug __maybe_unused, int nr_debug_entries __maybe_unused,
249 void *unwinding, uint64_t unwinding_header_size, uint64_t unwinding_size)
161{ 250{
162 Elf *e; 251 Elf *e;
163 Elf_Data *d; 252 Elf_Data *d;
164 Elf_Scn *scn; 253 Elf_Scn *scn;
165 Elf_Ehdr *ehdr; 254 Elf_Ehdr *ehdr;
166 Elf_Shdr *shdr; 255 Elf_Shdr *shdr;
256 uint64_t eh_frame_base_offset;
167 char *strsym = NULL; 257 char *strsym = NULL;
168 int symlen; 258 int symlen;
169 int retval = -1; 259 int retval = -1;
@@ -194,7 +284,7 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
194 ehdr->e_type = ET_DYN; 284 ehdr->e_type = ET_DYN;
195 ehdr->e_entry = GEN_ELF_TEXT_OFFSET; 285 ehdr->e_entry = GEN_ELF_TEXT_OFFSET;
196 ehdr->e_version = EV_CURRENT; 286 ehdr->e_version = EV_CURRENT;
197 ehdr->e_shstrndx= 2; /* shdr index for section name */ 287 ehdr->e_shstrndx= unwinding ? 4 : 2; /* shdr index for section name */
198 288
199 /* 289 /*
200 * setup text section 290 * setup text section
@@ -231,6 +321,18 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
231 shdr->sh_entsize = 0; 321 shdr->sh_entsize = 0;
232 322
233 /* 323 /*
324 * Setup .eh_frame_hdr and .eh_frame
325 */
326 if (unwinding) {
327 eh_frame_base_offset = ALIGN_8(GEN_ELF_TEXT_OFFSET + csize);
328 retval = jit_add_eh_frame_info(e, unwinding,
329 unwinding_header_size, unwinding_size,
330 eh_frame_base_offset);
331 if (retval)
332 goto error;
333 }
334
335 /*
234 * setup section headers string table 336 * setup section headers string table
235 */ 337 */
236 scn = elf_newscn(e); 338 scn = elf_newscn(e);
@@ -298,7 +400,7 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
298 shdr->sh_type = SHT_SYMTAB; 400 shdr->sh_type = SHT_SYMTAB;
299 shdr->sh_flags = 0; 401 shdr->sh_flags = 0;
300 shdr->sh_entsize = sizeof(Elf_Sym); 402 shdr->sh_entsize = sizeof(Elf_Sym);
301 shdr->sh_link = 4; /* index of .strtab section */ 403 shdr->sh_link = unwinding ? 6 : 4; /* index of .strtab section */
302 404
303 /* 405 /*
304 * setup symbols string table 406 * setup symbols string table
@@ -386,11 +488,14 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym,
386 shdr->sh_size = sizeof(bnote); 488 shdr->sh_size = sizeof(bnote);
387 shdr->sh_entsize = 0; 489 shdr->sh_entsize = 0;
388 490
491#ifdef HAVE_DWARF_SUPPORT
389 if (debug && nr_debug_entries) { 492 if (debug && nr_debug_entries) {
390 retval = jit_add_debug_info(e, load_addr, debug, nr_debug_entries); 493 retval = jit_add_debug_info(e, load_addr, debug, nr_debug_entries);
391 if (retval) 494 if (retval)
392 goto error; 495 goto error;
393 } else { 496 } else
497#endif
498 {
394 if (elf_update(e, ELF_C_WRITE) < 0) { 499 if (elf_update(e, ELF_C_WRITE) < 0) {
395 warnx("elf_update 4 failed"); 500 warnx("elf_update 4 failed");
396 goto error; 501 goto error;
diff --git a/tools/perf/util/genelf.h b/tools/perf/util/genelf.h
index 2fbeb59c4bdd..2424bd9862a3 100644
--- a/tools/perf/util/genelf.h
+++ b/tools/perf/util/genelf.h
@@ -3,9 +3,12 @@
3 3
4/* genelf.c */ 4/* genelf.c */
5int jit_write_elf(int fd, uint64_t code_addr, const char *sym, 5int jit_write_elf(int fd, uint64_t code_addr, const char *sym,
6 const void *code, int csize, void *debug, int nr_debug_entries); 6 const void *code, int csize, void *debug, int nr_debug_entries,
7 void *unwinding, uint64_t unwinding_header_size, uint64_t unwinding_size);
8#ifdef HAVE_DWARF_SUPPORT
7/* genelf_debug.c */ 9/* genelf_debug.c */
8int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries); 10int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries);
11#endif
9 12
10#if defined(__arm__) 13#if defined(__arm__)
11#define GEN_ELF_ARCH EM_ARM 14#define GEN_ELF_ARCH EM_ARM
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 2f3eded54b0c..d89c9c7ef4e5 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2250,11 +2250,28 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2250 struct header_print_data hd; 2250 struct header_print_data hd;
2251 struct perf_header *header = &session->header; 2251 struct perf_header *header = &session->header;
2252 int fd = perf_data_file__fd(session->file); 2252 int fd = perf_data_file__fd(session->file);
2253 struct stat st;
2254 int ret, bit;
2255
2253 hd.fp = fp; 2256 hd.fp = fp;
2254 hd.full = full; 2257 hd.full = full;
2255 2258
2259 ret = fstat(fd, &st);
2260 if (ret == -1)
2261 return -1;
2262
2263 fprintf(fp, "# captured on: %s", ctime(&st.st_ctime));
2264
2256 perf_header__process_sections(header, fd, &hd, 2265 perf_header__process_sections(header, fd, &hd,
2257 perf_file_section__fprintf_info); 2266 perf_file_section__fprintf_info);
2267
2268 fprintf(fp, "# missing features: ");
2269 for_each_clear_bit(bit, header->adds_features, HEADER_LAST_FEATURE) {
2270 if (bit)
2271 fprintf(fp, "%s ", feat_ops[bit].name);
2272 }
2273
2274 fprintf(fp, "\n");
2258 return 0; 2275 return 0;
2259} 2276}
2260 2277
@@ -2273,7 +2290,7 @@ static int do_write_feat(int fd, struct perf_header *h, int type,
2273 2290
2274 err = feat_ops[type].write(fd, h, evlist); 2291 err = feat_ops[type].write(fd, h, evlist);
2275 if (err < 0) { 2292 if (err < 0) {
2276 pr_debug("failed to write feature %d\n", type); 2293 pr_debug("failed to write feature %s\n", feat_ops[type].name);
2277 2294
2278 /* undo anything written */ 2295 /* undo anything written */
2279 lseek(fd, (*p)->offset, SEEK_SET); 2296 lseek(fd, (*p)->offset, SEEK_SET);
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index f545ec1e758a..6c2eb5da4afc 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -295,6 +295,7 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
295 sample.cpu = btsq->cpu; 295 sample.cpu = btsq->cpu;
296 sample.flags = btsq->sample_flags; 296 sample.flags = btsq->sample_flags;
297 sample.insn_len = btsq->intel_pt_insn.length; 297 sample.insn_len = btsq->intel_pt_insn.length;
298 memcpy(sample.insn, btsq->intel_pt_insn.buf, INTEL_PT_INSN_BUF_SZ);
298 299
299 if (bts->synth_opts.inject) { 300 if (bts->synth_opts.inject) {
300 event.sample.header.size = bts->branches_event_size; 301 event.sample.header.size = bts->branches_event_size;
@@ -319,15 +320,12 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
319 struct machine *machine = btsq->bts->machine; 320 struct machine *machine = btsq->bts->machine;
320 struct thread *thread; 321 struct thread *thread;
321 struct addr_location al; 322 struct addr_location al;
322 unsigned char buf[1024]; 323 unsigned char buf[INTEL_PT_INSN_BUF_SZ];
323 size_t bufsz;
324 ssize_t len; 324 ssize_t len;
325 int x86_64; 325 int x86_64;
326 uint8_t cpumode; 326 uint8_t cpumode;
327 int err = -1; 327 int err = -1;
328 328
329 bufsz = intel_pt_insn_max_size();
330
331 if (machine__kernel_ip(machine, ip)) 329 if (machine__kernel_ip(machine, ip))
332 cpumode = PERF_RECORD_MISC_KERNEL; 330 cpumode = PERF_RECORD_MISC_KERNEL;
333 else 331 else
@@ -341,7 +339,8 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
341 if (!al.map || !al.map->dso) 339 if (!al.map || !al.map->dso)
342 goto out_put; 340 goto out_put;
343 341
344 len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf, bufsz); 342 len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf,
343 INTEL_PT_INSN_BUF_SZ);
345 if (len <= 0) 344 if (len <= 0)
346 goto out_put; 345 goto out_put;
347 346
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 16c06d3ae577..e4e7dc781d21 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -980,6 +980,8 @@ out:
980out_no_progress: 980out_no_progress:
981 decoder->state.insn_op = intel_pt_insn->op; 981 decoder->state.insn_op = intel_pt_insn->op;
982 decoder->state.insn_len = intel_pt_insn->length; 982 decoder->state.insn_len = intel_pt_insn->length;
983 memcpy(decoder->state.insn, intel_pt_insn->buf,
984 INTEL_PT_INSN_BUF_SZ);
983 985
984 if (decoder->tx_flags & INTEL_PT_IN_TX) 986 if (decoder->tx_flags & INTEL_PT_IN_TX)
985 decoder->state.flags |= INTEL_PT_IN_TX; 987 decoder->state.flags |= INTEL_PT_IN_TX;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 89399985fa4d..e90619a43c0c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -66,6 +66,7 @@ struct intel_pt_state {
66 uint32_t flags; 66 uint32_t flags;
67 enum intel_pt_insn_op insn_op; 67 enum intel_pt_insn_op insn_op;
68 int insn_len; 68 int insn_len;
69 char insn[INTEL_PT_INSN_BUF_SZ];
69}; 70};
70 71
71struct intel_pt_insn; 72struct intel_pt_insn;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
index d23138c06665..7913363bde5c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -27,6 +27,10 @@
27 27
28#include "intel-pt-insn-decoder.h" 28#include "intel-pt-insn-decoder.h"
29 29
30#if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE || INTEL_PT_INSN_BUF_SZ > MAX_INSN
31#error Instruction buffer size too small
32#endif
33
30/* Based on branch_type() from perf_event_intel_lbr.c */ 34/* Based on branch_type() from perf_event_intel_lbr.c */
31static void intel_pt_insn_decoder(struct insn *insn, 35static void intel_pt_insn_decoder(struct insn *insn,
32 struct intel_pt_insn *intel_pt_insn) 36 struct intel_pt_insn *intel_pt_insn)
@@ -166,10 +170,10 @@ int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
166 if (!insn_complete(&insn) || insn.length > len) 170 if (!insn_complete(&insn) || insn.length > len)
167 return -1; 171 return -1;
168 intel_pt_insn_decoder(&insn, intel_pt_insn); 172 intel_pt_insn_decoder(&insn, intel_pt_insn);
169 if (insn.length < INTEL_PT_INSN_DBG_BUF_SZ) 173 if (insn.length < INTEL_PT_INSN_BUF_SZ)
170 memcpy(intel_pt_insn->buf, buf, insn.length); 174 memcpy(intel_pt_insn->buf, buf, insn.length);
171 else 175 else
172 memcpy(intel_pt_insn->buf, buf, INTEL_PT_INSN_DBG_BUF_SZ); 176 memcpy(intel_pt_insn->buf, buf, INTEL_PT_INSN_BUF_SZ);
173 return 0; 177 return 0;
174} 178}
175 179
@@ -211,11 +215,6 @@ int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
211 return 0; 215 return 0;
212} 216}
213 217
214size_t intel_pt_insn_max_size(void)
215{
216 return MAX_INSN_SIZE;
217}
218
219int intel_pt_insn_type(enum intel_pt_insn_op op) 218int intel_pt_insn_type(enum intel_pt_insn_op op)
220{ 219{
221 switch (op) { 220 switch (op) {
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
index b0adbf37323e..37ec5627ae9b 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
@@ -20,7 +20,7 @@
20#include <stdint.h> 20#include <stdint.h>
21 21
22#define INTEL_PT_INSN_DESC_MAX 32 22#define INTEL_PT_INSN_DESC_MAX 32
23#define INTEL_PT_INSN_DBG_BUF_SZ 16 23#define INTEL_PT_INSN_BUF_SZ 16
24 24
25enum intel_pt_insn_op { 25enum intel_pt_insn_op {
26 INTEL_PT_OP_OTHER, 26 INTEL_PT_OP_OTHER,
@@ -47,7 +47,7 @@ struct intel_pt_insn {
47 enum intel_pt_insn_branch branch; 47 enum intel_pt_insn_branch branch;
48 int length; 48 int length;
49 int32_t rel; 49 int32_t rel;
50 unsigned char buf[INTEL_PT_INSN_DBG_BUF_SZ]; 50 unsigned char buf[INTEL_PT_INSN_BUF_SZ];
51}; 51};
52 52
53int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64, 53int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
@@ -58,8 +58,6 @@ const char *intel_pt_insn_name(enum intel_pt_insn_op op);
58int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf, 58int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
59 size_t buf_len); 59 size_t buf_len);
60 60
61size_t intel_pt_insn_max_size(void);
62
63int intel_pt_insn_type(enum intel_pt_insn_op op); 61int intel_pt_insn_type(enum intel_pt_insn_op op);
64 62
65#endif 63#endif
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.c b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
index 319bef33a64b..e02bc7b166a0 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
@@ -119,8 +119,8 @@ void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
119 if (intel_pt_log_open()) 119 if (intel_pt_log_open())
120 return; 120 return;
121 121
122 if (len > INTEL_PT_INSN_DBG_BUF_SZ) 122 if (len > INTEL_PT_INSN_BUF_SZ)
123 len = INTEL_PT_INSN_DBG_BUF_SZ; 123 len = INTEL_PT_INSN_BUF_SZ;
124 intel_pt_print_data(intel_pt_insn->buf, len, ip, 8); 124 intel_pt_print_data(intel_pt_insn->buf, len, ip, 8);
125 if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0) 125 if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0)
126 fprintf(f, "%s\n", desc); 126 fprintf(f, "%s\n", desc);
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index dc041d4368c8..85d5eeb66c75 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -143,6 +143,7 @@ struct intel_pt_queue {
143 u32 flags; 143 u32 flags;
144 u16 insn_len; 144 u16 insn_len;
145 u64 last_insn_cnt; 145 u64 last_insn_cnt;
146 char insn[INTEL_PT_INSN_BUF_SZ];
146}; 147};
147 148
148static void intel_pt_dump(struct intel_pt *pt __maybe_unused, 149static void intel_pt_dump(struct intel_pt *pt __maybe_unused,
@@ -315,6 +316,7 @@ struct intel_pt_cache_entry {
315 enum intel_pt_insn_branch branch; 316 enum intel_pt_insn_branch branch;
316 int length; 317 int length;
317 int32_t rel; 318 int32_t rel;
319 char insn[INTEL_PT_INSN_BUF_SZ];
318}; 320};
319 321
320static int intel_pt_config_div(const char *var, const char *value, void *data) 322static int intel_pt_config_div(const char *var, const char *value, void *data)
@@ -400,6 +402,7 @@ static int intel_pt_cache_add(struct dso *dso, struct machine *machine,
400 e->branch = intel_pt_insn->branch; 402 e->branch = intel_pt_insn->branch;
401 e->length = intel_pt_insn->length; 403 e->length = intel_pt_insn->length;
402 e->rel = intel_pt_insn->rel; 404 e->rel = intel_pt_insn->rel;
405 memcpy(e->insn, intel_pt_insn->buf, INTEL_PT_INSN_BUF_SZ);
403 406
404 err = auxtrace_cache__add(c, offset, &e->entry); 407 err = auxtrace_cache__add(c, offset, &e->entry);
405 if (err) 408 if (err)
@@ -428,8 +431,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
428 struct machine *machine = ptq->pt->machine; 431 struct machine *machine = ptq->pt->machine;
429 struct thread *thread; 432 struct thread *thread;
430 struct addr_location al; 433 struct addr_location al;
431 unsigned char buf[1024]; 434 unsigned char buf[INTEL_PT_INSN_BUF_SZ];
432 size_t bufsz;
433 ssize_t len; 435 ssize_t len;
434 int x86_64; 436 int x86_64;
435 u8 cpumode; 437 u8 cpumode;
@@ -437,11 +439,11 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
437 u64 insn_cnt = 0; 439 u64 insn_cnt = 0;
438 bool one_map = true; 440 bool one_map = true;
439 441
442 intel_pt_insn->length = 0;
443
440 if (to_ip && *ip == to_ip) 444 if (to_ip && *ip == to_ip)
441 goto out_no_cache; 445 goto out_no_cache;
442 446
443 bufsz = intel_pt_insn_max_size();
444
445 if (*ip >= ptq->pt->kernel_start) 447 if (*ip >= ptq->pt->kernel_start)
446 cpumode = PERF_RECORD_MISC_KERNEL; 448 cpumode = PERF_RECORD_MISC_KERNEL;
447 else 449 else
@@ -478,6 +480,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
478 intel_pt_insn->branch = e->branch; 480 intel_pt_insn->branch = e->branch;
479 intel_pt_insn->length = e->length; 481 intel_pt_insn->length = e->length;
480 intel_pt_insn->rel = e->rel; 482 intel_pt_insn->rel = e->rel;
483 memcpy(intel_pt_insn->buf, e->insn,
484 INTEL_PT_INSN_BUF_SZ);
481 intel_pt_log_insn_no_data(intel_pt_insn, *ip); 485 intel_pt_log_insn_no_data(intel_pt_insn, *ip);
482 return 0; 486 return 0;
483 } 487 }
@@ -493,7 +497,8 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
493 497
494 while (1) { 498 while (1) {
495 len = dso__data_read_offset(al.map->dso, machine, 499 len = dso__data_read_offset(al.map->dso, machine,
496 offset, buf, bufsz); 500 offset, buf,
501 INTEL_PT_INSN_BUF_SZ);
497 if (len <= 0) 502 if (len <= 0)
498 return -EINVAL; 503 return -EINVAL;
499 504
@@ -900,6 +905,7 @@ static void intel_pt_sample_flags(struct intel_pt_queue *ptq)
900 if (ptq->state->flags & INTEL_PT_IN_TX) 905 if (ptq->state->flags & INTEL_PT_IN_TX)
901 ptq->flags |= PERF_IP_FLAG_IN_TX; 906 ptq->flags |= PERF_IP_FLAG_IN_TX;
902 ptq->insn_len = ptq->state->insn_len; 907 ptq->insn_len = ptq->state->insn_len;
908 memcpy(ptq->insn, ptq->state->insn, INTEL_PT_INSN_BUF_SZ);
903 } 909 }
904} 910}
905 911
@@ -1080,6 +1086,7 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
1080 sample.cpu = ptq->cpu; 1086 sample.cpu = ptq->cpu;
1081 sample.flags = ptq->flags; 1087 sample.flags = ptq->flags;
1082 sample.insn_len = ptq->insn_len; 1088 sample.insn_len = ptq->insn_len;
1089 memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
1083 1090
1084 /* 1091 /*
1085 * perf report cannot handle events without a branch stack when using 1092 * perf report cannot handle events without a branch stack when using
@@ -1141,6 +1148,7 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
1141 sample.cpu = ptq->cpu; 1148 sample.cpu = ptq->cpu;
1142 sample.flags = ptq->flags; 1149 sample.flags = ptq->flags;
1143 sample.insn_len = ptq->insn_len; 1150 sample.insn_len = ptq->insn_len;
1151 memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
1144 1152
1145 ptq->last_insn_cnt = ptq->state->tot_insn_cnt; 1153 ptq->last_insn_cnt = ptq->state->tot_insn_cnt;
1146 1154
@@ -1203,6 +1211,7 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
1203 sample.cpu = ptq->cpu; 1211 sample.cpu = ptq->cpu;
1204 sample.flags = ptq->flags; 1212 sample.flags = ptq->flags;
1205 sample.insn_len = ptq->insn_len; 1213 sample.insn_len = ptq->insn_len;
1214 memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
1206 1215
1207 if (pt->synth_opts.callchain) { 1216 if (pt->synth_opts.callchain) {
1208 thread_stack__sample(ptq->thread, ptq->chain, 1217 thread_stack__sample(ptq->thread, ptq->chain,
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
index 95f0884aae02..c9a941ef0f6d 100644
--- a/tools/perf/util/jitdump.c
+++ b/tools/perf/util/jitdump.c
@@ -37,6 +37,10 @@ struct jit_buf_desc {
37 bool needs_bswap; /* handles cross-endianess */ 37 bool needs_bswap; /* handles cross-endianess */
38 bool use_arch_timestamp; 38 bool use_arch_timestamp;
39 void *debug_data; 39 void *debug_data;
40 void *unwinding_data;
41 uint64_t unwinding_size;
42 uint64_t unwinding_mapped_size;
43 uint64_t eh_frame_hdr_size;
40 size_t nr_debug_entries; 44 size_t nr_debug_entries;
41 uint32_t code_load_count; 45 uint32_t code_load_count;
42 u64 bytes_written; 46 u64 bytes_written;
@@ -68,7 +72,10 @@ jit_emit_elf(char *filename,
68 const void *code, 72 const void *code,
69 int csize, 73 int csize,
70 void *debug, 74 void *debug,
71 int nr_debug_entries) 75 int nr_debug_entries,
76 void *unwinding,
77 uint32_t unwinding_header_size,
78 uint32_t unwinding_size)
72{ 79{
73 int ret, fd; 80 int ret, fd;
74 81
@@ -81,7 +88,8 @@ jit_emit_elf(char *filename,
81 return -1; 88 return -1;
82 } 89 }
83 90
84 ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize, debug, nr_debug_entries); 91 ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize, debug, nr_debug_entries,
92 unwinding, unwinding_header_size, unwinding_size);
85 93
86 close(fd); 94 close(fd);
87 95
@@ -172,6 +180,12 @@ jit_open(struct jit_buf_desc *jd, const char *name)
172 header.elf_mach, 180 header.elf_mach,
173 jd->use_arch_timestamp); 181 jd->use_arch_timestamp);
174 182
183 if (header.version > JITHEADER_VERSION) {
184 pr_err("wrong jitdump version %u, expected " STR(JITHEADER_VERSION),
185 header.version);
186 goto error;
187 }
188
175 if (header.flags & JITDUMP_FLAGS_RESERVED) { 189 if (header.flags & JITDUMP_FLAGS_RESERVED) {
176 pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n", 190 pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
177 (unsigned long long)header.flags & JITDUMP_FLAGS_RESERVED); 191 (unsigned long long)header.flags & JITDUMP_FLAGS_RESERVED);
@@ -263,8 +277,7 @@ jit_get_next_entry(struct jit_buf_desc *jd)
263 return NULL; 277 return NULL;
264 278
265 if (id >= JIT_CODE_MAX) { 279 if (id >= JIT_CODE_MAX) {
266 pr_warning("next_entry: unknown prefix %d, skipping\n", id); 280 pr_warning("next_entry: unknown record type %d, skipping\n", id);
267 return NULL;
268 } 281 }
269 if (bs > jd->bufsize) { 282 if (bs > jd->bufsize) {
270 void *n; 283 void *n;
@@ -296,6 +309,13 @@ jit_get_next_entry(struct jit_buf_desc *jd)
296 } 309 }
297 } 310 }
298 break; 311 break;
312 case JIT_CODE_UNWINDING_INFO:
313 if (jd->needs_bswap) {
314 jr->unwinding.unwinding_size = bswap_64(jr->unwinding.unwinding_size);
315 jr->unwinding.eh_frame_hdr_size = bswap_64(jr->unwinding.eh_frame_hdr_size);
316 jr->unwinding.mapped_size = bswap_64(jr->unwinding.mapped_size);
317 }
318 break;
299 case JIT_CODE_CLOSE: 319 case JIT_CODE_CLOSE:
300 break; 320 break;
301 case JIT_CODE_LOAD: 321 case JIT_CODE_LOAD:
@@ -322,7 +342,8 @@ jit_get_next_entry(struct jit_buf_desc *jd)
322 break; 342 break;
323 case JIT_CODE_MAX: 343 case JIT_CODE_MAX:
324 default: 344 default:
325 return NULL; 345 /* skip unknown record (we have read them) */
346 break;
326 } 347 }
327 return jr; 348 return jr;
328} 349}
@@ -370,7 +391,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
370 u16 idr_size; 391 u16 idr_size;
371 const char *sym; 392 const char *sym;
372 uint32_t count; 393 uint32_t count;
373 int ret, csize; 394 int ret, csize, usize;
374 pid_t pid, tid; 395 pid_t pid, tid;
375 struct { 396 struct {
376 u32 pid, tid; 397 u32 pid, tid;
@@ -380,6 +401,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
380 pid = jr->load.pid; 401 pid = jr->load.pid;
381 tid = jr->load.tid; 402 tid = jr->load.tid;
382 csize = jr->load.code_size; 403 csize = jr->load.code_size;
404 usize = jd->unwinding_mapped_size;
383 addr = jr->load.code_addr; 405 addr = jr->load.code_addr;
384 sym = (void *)((unsigned long)jr + sizeof(jr->load)); 406 sym = (void *)((unsigned long)jr + sizeof(jr->load));
385 code = (unsigned long)jr + jr->load.p.total_size - csize; 407 code = (unsigned long)jr + jr->load.p.total_size - csize;
@@ -400,7 +422,8 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
400 422
401 size = PERF_ALIGN(size, sizeof(u64)); 423 size = PERF_ALIGN(size, sizeof(u64));
402 uaddr = (uintptr_t)code; 424 uaddr = (uintptr_t)code;
403 ret = jit_emit_elf(filename, sym, addr, (const void *)uaddr, csize, jd->debug_data, jd->nr_debug_entries); 425 ret = jit_emit_elf(filename, sym, addr, (const void *)uaddr, csize, jd->debug_data, jd->nr_debug_entries,
426 jd->unwinding_data, jd->eh_frame_hdr_size, jd->unwinding_size);
404 427
405 if (jd->debug_data && jd->nr_debug_entries) { 428 if (jd->debug_data && jd->nr_debug_entries) {
406 free(jd->debug_data); 429 free(jd->debug_data);
@@ -408,6 +431,14 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
408 jd->nr_debug_entries = 0; 431 jd->nr_debug_entries = 0;
409 } 432 }
410 433
434 if (jd->unwinding_data && jd->eh_frame_hdr_size) {
435 free(jd->unwinding_data);
436 jd->unwinding_data = NULL;
437 jd->eh_frame_hdr_size = 0;
438 jd->unwinding_mapped_size = 0;
439 jd->unwinding_size = 0;
440 }
441
411 if (ret) { 442 if (ret) {
412 free(event); 443 free(event);
413 return -1; 444 return -1;
@@ -422,7 +453,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
422 453
423 event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET; 454 event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET;
424 event->mmap2.start = addr; 455 event->mmap2.start = addr;
425 event->mmap2.len = csize; 456 event->mmap2.len = usize ? ALIGN_8(csize) + usize : csize;
426 event->mmap2.pid = pid; 457 event->mmap2.pid = pid;
427 event->mmap2.tid = tid; 458 event->mmap2.tid = tid;
428 event->mmap2.ino = st.st_ino; 459 event->mmap2.ino = st.st_ino;
@@ -473,6 +504,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
473 char *filename; 504 char *filename;
474 size_t size; 505 size_t size;
475 struct stat st; 506 struct stat st;
507 int usize;
476 u16 idr_size; 508 u16 idr_size;
477 int ret; 509 int ret;
478 pid_t pid, tid; 510 pid_t pid, tid;
@@ -483,6 +515,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
483 515
484 pid = jr->move.pid; 516 pid = jr->move.pid;
485 tid = jr->move.tid; 517 tid = jr->move.tid;
518 usize = jd->unwinding_mapped_size;
486 idr_size = jd->machine->id_hdr_size; 519 idr_size = jd->machine->id_hdr_size;
487 520
488 /* 521 /*
@@ -511,7 +544,8 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
511 (sizeof(event->mmap2.filename) - size) + idr_size); 544 (sizeof(event->mmap2.filename) - size) + idr_size);
512 event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET; 545 event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET;
513 event->mmap2.start = jr->move.new_code_addr; 546 event->mmap2.start = jr->move.new_code_addr;
514 event->mmap2.len = jr->move.code_size; 547 event->mmap2.len = usize ? ALIGN_8(jr->move.code_size) + usize
548 : jr->move.code_size;
515 event->mmap2.pid = pid; 549 event->mmap2.pid = pid;
516 event->mmap2.tid = tid; 550 event->mmap2.tid = tid;
517 event->mmap2.ino = st.st_ino; 551 event->mmap2.ino = st.st_ino;
@@ -578,10 +612,35 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr)
578} 612}
579 613
580static int 614static int
615jit_repipe_unwinding_info(struct jit_buf_desc *jd, union jr_entry *jr)
616{
617 void *unwinding_data;
618 uint32_t unwinding_data_size;
619
620 if (!(jd && jr))
621 return -1;
622
623 unwinding_data_size = jr->prefix.total_size - sizeof(jr->unwinding);
624 unwinding_data = malloc(unwinding_data_size);
625 if (!unwinding_data)
626 return -1;
627
628 memcpy(unwinding_data, &jr->unwinding.unwinding_data,
629 unwinding_data_size);
630
631 jd->eh_frame_hdr_size = jr->unwinding.eh_frame_hdr_size;
632 jd->unwinding_size = jr->unwinding.unwinding_size;
633 jd->unwinding_mapped_size = jr->unwinding.mapped_size;
634 jd->unwinding_data = unwinding_data;
635
636 return 0;
637}
638
639static int
581jit_process_dump(struct jit_buf_desc *jd) 640jit_process_dump(struct jit_buf_desc *jd)
582{ 641{
583 union jr_entry *jr; 642 union jr_entry *jr;
584 int ret; 643 int ret = 0;
585 644
586 while ((jr = jit_get_next_entry(jd))) { 645 while ((jr = jit_get_next_entry(jd))) {
587 switch(jr->prefix.id) { 646 switch(jr->prefix.id) {
@@ -594,6 +653,9 @@ jit_process_dump(struct jit_buf_desc *jd)
594 case JIT_CODE_DEBUG_INFO: 653 case JIT_CODE_DEBUG_INFO:
595 ret = jit_repipe_debug_info(jd, jr); 654 ret = jit_repipe_debug_info(jd, jr);
596 break; 655 break;
656 case JIT_CODE_UNWINDING_INFO:
657 ret = jit_repipe_unwinding_info(jd, jr);
658 break;
597 default: 659 default:
598 ret = 0; 660 ret = 0;
599 continue; 661 continue;
diff --git a/tools/perf/util/jitdump.h b/tools/perf/util/jitdump.h
index bcacd20d0c1c..c6b9b67f43bf 100644
--- a/tools/perf/util/jitdump.h
+++ b/tools/perf/util/jitdump.h
@@ -19,6 +19,7 @@
19#define JITHEADER_MAGIC_SW 0x4454694A 19#define JITHEADER_MAGIC_SW 0x4454694A
20 20
21#define PADDING_8ALIGNED(x) ((((x) + 7) & 7) ^ 7) 21#define PADDING_8ALIGNED(x) ((((x) + 7) & 7) ^ 7)
22#define ALIGN_8(x) (((x) + 7) & (~7))
22 23
23#define JITHEADER_VERSION 1 24#define JITHEADER_VERSION 1
24 25
@@ -48,6 +49,7 @@ enum jit_record_type {
48 JIT_CODE_MOVE = 1, 49 JIT_CODE_MOVE = 1,
49 JIT_CODE_DEBUG_INFO = 2, 50 JIT_CODE_DEBUG_INFO = 2,
50 JIT_CODE_CLOSE = 3, 51 JIT_CODE_CLOSE = 3,
52 JIT_CODE_UNWINDING_INFO = 4,
51 53
52 JIT_CODE_MAX, 54 JIT_CODE_MAX,
53}; 55};
@@ -101,12 +103,22 @@ struct jr_code_debug_info {
101 struct debug_entry entries[0]; 103 struct debug_entry entries[0];
102}; 104};
103 105
106struct jr_code_unwinding_info {
107 struct jr_prefix p;
108
109 uint64_t unwinding_size;
110 uint64_t eh_frame_hdr_size;
111 uint64_t mapped_size;
112 const char unwinding_data[0];
113};
114
104union jr_entry { 115union jr_entry {
105 struct jr_code_debug_info info; 116 struct jr_code_debug_info info;
106 struct jr_code_close close; 117 struct jr_code_close close;
107 struct jr_code_load load; 118 struct jr_code_load load;
108 struct jr_code_move move; 119 struct jr_code_move move;
109 struct jr_prefix prefix; 120 struct jr_prefix prefix;
121 struct jr_code_unwinding_info unwinding;
110}; 122};
111 123
112static inline struct debug_entry * 124static inline struct debug_entry *
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index bf7216b8731d..27b6f303720a 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -339,7 +339,7 @@ dump_obj(const char *path, void *obj_buf, size_t size)
339 char *p; 339 char *p;
340 340
341 if (!obj_path) { 341 if (!obj_path) {
342 pr_warning("WARNING: No enough memory, skip object dumping\n"); 342 pr_warning("WARNING: Not enough memory, skip object dumping\n");
343 return; 343 return;
344 } 344 }
345 345
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index c662fef95d14..4f9a71c63026 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -682,9 +682,16 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
682 continue; 682 continue;
683 683
684 if (verbose >= 2) { 684 if (verbose >= 2) {
685 fputs("overlapping maps:\n", fp); 685
686 map__fprintf(map, fp); 686 if (use_browser) {
687 map__fprintf(pos, fp); 687 pr_warning("overlapping maps in %s "
688 "(disable tui for more info)\n",
689 map->dso->name);
690 } else {
691 fputs("overlapping maps:\n", fp);
692 map__fprintf(map, fp);
693 map__fprintf(pos, fp);
694 }
688 } 695 }
689 696
690 rb_erase_init(&pos->rb_node, root); 697 rb_erase_init(&pos->rb_node, root);
@@ -702,7 +709,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
702 709
703 before->end = map->start; 710 before->end = map->start;
704 __map_groups__insert(pos->groups, before); 711 __map_groups__insert(pos->groups, before);
705 if (verbose >= 2) 712 if (verbose >= 2 && !use_browser)
706 map__fprintf(before, fp); 713 map__fprintf(before, fp);
707 map__put(before); 714 map__put(before);
708 } 715 }
@@ -717,7 +724,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
717 724
718 after->start = map->end; 725 after->start = map->end;
719 __map_groups__insert(pos->groups, after); 726 __map_groups__insert(pos->groups, after);
720 if (verbose >= 2) 727 if (verbose >= 2 && !use_browser)
721 map__fprintf(after, fp); 728 map__fprintf(after, fp);
722 map__put(after); 729 map__put(after);
723 } 730 }
diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c
index afc088dd7d20..3634d6974300 100644
--- a/tools/perf/util/parse-branch-options.c
+++ b/tools/perf/util/parse-branch-options.c
@@ -31,59 +31,51 @@ static const struct branch_mode branch_modes[] = {
31 BRANCH_END 31 BRANCH_END
32}; 32};
33 33
34int 34int parse_branch_str(const char *str, __u64 *mode)
35parse_branch_stack(const struct option *opt, const char *str, int unset)
36{ 35{
37#define ONLY_PLM \ 36#define ONLY_PLM \
38 (PERF_SAMPLE_BRANCH_USER |\ 37 (PERF_SAMPLE_BRANCH_USER |\
39 PERF_SAMPLE_BRANCH_KERNEL |\ 38 PERF_SAMPLE_BRANCH_KERNEL |\
40 PERF_SAMPLE_BRANCH_HV) 39 PERF_SAMPLE_BRANCH_HV)
41 40
42 uint64_t *mode = (uint64_t *)opt->value; 41 int ret = 0;
42 char *p, *s;
43 char *os = NULL;
43 const struct branch_mode *br; 44 const struct branch_mode *br;
44 char *s, *os = NULL, *p;
45 int ret = -1;
46 45
47 if (unset) 46 if (str == NULL) {
47 *mode = PERF_SAMPLE_BRANCH_ANY;
48 return 0; 48 return 0;
49 }
49 50
50 /* 51 /* because str is read-only */
51 * cannot set it twice, -b + --branch-filter for instance 52 s = os = strdup(str);
52 */ 53 if (!s)
53 if (*mode)
54 return -1; 54 return -1;
55 55
56 /* str may be NULL in case no arg is passed to -b */ 56 for (;;) {
57 if (str) { 57 p = strchr(s, ',');
58 /* because str is read-only */ 58 if (p)
59 s = os = strdup(str); 59 *p = '\0';
60 if (!s)
61 return -1;
62
63 for (;;) {
64 p = strchr(s, ',');
65 if (p)
66 *p = '\0';
67
68 for (br = branch_modes; br->name; br++) {
69 if (!strcasecmp(s, br->name))
70 break;
71 }
72 if (!br->name) {
73 ui__warning("unknown branch filter %s,"
74 " check man page\n", s);
75 goto error;
76 }
77
78 *mode |= br->mode;
79
80 if (!p)
81 break;
82 60
83 s = p + 1; 61 for (br = branch_modes; br->name; br++) {
62 if (!strcasecmp(s, br->name))
63 break;
64 }
65 if (!br->name) {
66 ret = -1;
67 ui__warning("unknown branch filter %s,"
68 " check man page\n", s);
69 goto error;
84 } 70 }
71
72 *mode |= br->mode;
73
74 if (!p)
75 break;
76
77 s = p + 1;
85 } 78 }
86 ret = 0;
87 79
88 /* default to any branch */ 80 /* default to any branch */
89 if ((*mode & ~ONLY_PLM) == 0) { 81 if ((*mode & ~ONLY_PLM) == 0) {
@@ -93,3 +85,20 @@ error:
93 free(os); 85 free(os);
94 return ret; 86 return ret;
95} 87}
88
89int
90parse_branch_stack(const struct option *opt, const char *str, int unset)
91{
92 __u64 *mode = (__u64 *)opt->value;
93
94 if (unset)
95 return 0;
96
97 /*
98 * cannot set it twice, -b + --branch-filter for instance
99 */
100 if (*mode)
101 return -1;
102
103 return parse_branch_str(str, mode);
104}
diff --git a/tools/perf/util/parse-branch-options.h b/tools/perf/util/parse-branch-options.h
index b9d9470c2e82..6086fd90eb23 100644
--- a/tools/perf/util/parse-branch-options.h
+++ b/tools/perf/util/parse-branch-options.h
@@ -1,5 +1,6 @@
1#ifndef _PERF_PARSE_BRANCH_OPTIONS_H 1#ifndef _PERF_PARSE_BRANCH_OPTIONS_H
2#define _PERF_PARSE_BRANCH_OPTIONS_H 1 2#define _PERF_PARSE_BRANCH_OPTIONS_H 1
3struct option; 3#include <stdint.h>
4int parse_branch_stack(const struct option *opt, const char *str, int unset); 4int parse_branch_stack(const struct option *opt, const char *str, int unset);
5int parse_branch_str(const char *str, __u64 *mode);
5#endif /* _PERF_PARSE_BRANCH_OPTIONS_H */ 6#endif /* _PERF_PARSE_BRANCH_OPTIONS_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4e778eae1510..3c876b8ba4de 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -22,6 +22,7 @@
22#include "cpumap.h" 22#include "cpumap.h"
23#include "probe-file.h" 23#include "probe-file.h"
24#include "asm/bug.h" 24#include "asm/bug.h"
25#include "util/parse-branch-options.h"
25 26
26#define MAX_NAME_LEN 100 27#define MAX_NAME_LEN 100
27 28
@@ -973,10 +974,13 @@ do { \
973 CHECK_TYPE_VAL(NUM); 974 CHECK_TYPE_VAL(NUM);
974 break; 975 break;
975 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 976 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
976 /* 977 CHECK_TYPE_VAL(STR);
977 * TODO uncomment when the field is available 978 if (strcmp(term->val.str, "no") &&
978 * attr->branch_sample_type = term->val.num; 979 parse_branch_str(term->val.str, &attr->branch_sample_type)) {
979 */ 980 err->str = strdup("invalid branch sample type");
981 err->idx = term->err_val;
982 return -EINVAL;
983 }
980 break; 984 break;
981 case PARSE_EVENTS__TERM_TYPE_TIME: 985 case PARSE_EVENTS__TERM_TYPE_TIME:
982 CHECK_TYPE_VAL(NUM); 986 CHECK_TYPE_VAL(NUM);
@@ -1119,6 +1123,9 @@ do { \
1119 case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 1123 case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
1120 ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str); 1124 ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str);
1121 break; 1125 break;
1126 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
1127 ADD_CONFIG_TERM(BRANCH, branch, term->val.str);
1128 break;
1122 case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1129 case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
1123 ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num); 1130 ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num);
1124 break; 1131 break;
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index b1474dcadfa2..31b845ec32e2 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -504,6 +504,7 @@ static void pmu_add_cpu_aliases(struct list_head *head)
504 struct pmu_events_map *map; 504 struct pmu_events_map *map;
505 struct pmu_event *pe; 505 struct pmu_event *pe;
506 char *cpuid; 506 char *cpuid;
507 static bool printed;
507 508
508 cpuid = getenv("PERF_CPUID"); 509 cpuid = getenv("PERF_CPUID");
509 if (cpuid) 510 if (cpuid)
@@ -513,7 +514,10 @@ static void pmu_add_cpu_aliases(struct list_head *head)
513 if (!cpuid) 514 if (!cpuid)
514 return; 515 return;
515 516
516 pr_debug("Using CPUID %s\n", cpuid); 517 if (!printed) {
518 pr_debug("Using CPUID %s\n", cpuid);
519 printed = true;
520 }
517 521
518 i = 0; 522 i = 0;
519 while (1) { 523 while (1) {
@@ -1135,8 +1139,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1135 bool is_cpu = !strcmp(pmu->name, "cpu"); 1139 bool is_cpu = !strcmp(pmu->name, "cpu");
1136 1140
1137 if (event_glob != NULL && 1141 if (event_glob != NULL &&
1138 !(strglobmatch(name, event_glob) || 1142 !(strglobmatch_nocase(name, event_glob) ||
1139 (!is_cpu && strglobmatch(alias->name, 1143 (!is_cpu && strglobmatch_nocase(alias->name,
1140 event_glob)))) 1144 event_glob))))
1141 continue; 1145 continue;
1142 1146
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index 639d1da2f978..293534c1a474 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -54,7 +54,7 @@ int sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
54 break; 54 break;
55 ret = sq_quote_buf(dst, argv[i]); 55 ret = sq_quote_buf(dst, argv[i]);
56 if (maxlen && dst->len > maxlen) 56 if (maxlen && dst->len > maxlen)
57 die("Too many or long arguments"); 57 return -ENOSPC;
58 } 58 }
59 return ret; 59 return ret;
60} 60}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5d61242a6e64..f268201048a0 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -2025,20 +2025,10 @@ out_delete_map:
2025void perf_session__fprintf_info(struct perf_session *session, FILE *fp, 2025void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
2026 bool full) 2026 bool full)
2027{ 2027{
2028 struct stat st;
2029 int fd, ret;
2030
2031 if (session == NULL || fp == NULL) 2028 if (session == NULL || fp == NULL)
2032 return; 2029 return;
2033 2030
2034 fd = perf_data_file__fd(session->file);
2035
2036 ret = fstat(fd, &st);
2037 if (ret == -1)
2038 return;
2039
2040 fprintf(fp, "# ========\n"); 2031 fprintf(fp, "# ========\n");
2041 fprintf(fp, "# captured on: %s", ctime(&st.st_ctime));
2042 perf_header__fprintf_info(session, fp, full); 2032 perf_header__fprintf_info(session, fp, full);
2043 fprintf(fp, "# ========\n#\n"); 2033 fprintf(fp, "# ========\n#\n");
2044} 2034}
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 7f7e072be746..d8dfaf64b32e 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -193,7 +193,8 @@ error:
193} 193}
194 194
195/* Glob/lazy pattern matching */ 195/* Glob/lazy pattern matching */
196static bool __match_glob(const char *str, const char *pat, bool ignore_space) 196static bool __match_glob(const char *str, const char *pat, bool ignore_space,
197 bool case_ins)
197{ 198{
198 while (*str && *pat && *pat != '*') { 199 while (*str && *pat && *pat != '*') {
199 if (ignore_space) { 200 if (ignore_space) {
@@ -219,8 +220,13 @@ static bool __match_glob(const char *str, const char *pat, bool ignore_space)
219 return false; 220 return false;
220 else if (*pat == '\\') /* Escaped char match as normal char */ 221 else if (*pat == '\\') /* Escaped char match as normal char */
221 pat++; 222 pat++;
222 if (*str++ != *pat++) 223 if (case_ins) {
224 if (tolower(*str) != tolower(*pat))
225 return false;
226 } else if (*str != *pat)
223 return false; 227 return false;
228 str++;
229 pat++;
224 } 230 }
225 /* Check wild card */ 231 /* Check wild card */
226 if (*pat == '*') { 232 if (*pat == '*') {
@@ -229,7 +235,7 @@ static bool __match_glob(const char *str, const char *pat, bool ignore_space)
229 if (!*pat) /* Tail wild card matches all */ 235 if (!*pat) /* Tail wild card matches all */
230 return true; 236 return true;
231 while (*str) 237 while (*str)
232 if (__match_glob(str++, pat, ignore_space)) 238 if (__match_glob(str++, pat, ignore_space, case_ins))
233 return true; 239 return true;
234 } 240 }
235 return !*str && !*pat; 241 return !*str && !*pat;
@@ -249,7 +255,12 @@ static bool __match_glob(const char *str, const char *pat, bool ignore_space)
249 */ 255 */
250bool strglobmatch(const char *str, const char *pat) 256bool strglobmatch(const char *str, const char *pat)
251{ 257{
252 return __match_glob(str, pat, false); 258 return __match_glob(str, pat, false, false);
259}
260
261bool strglobmatch_nocase(const char *str, const char *pat)
262{
263 return __match_glob(str, pat, false, true);
253} 264}
254 265
255/** 266/**
@@ -262,7 +273,7 @@ bool strglobmatch(const char *str, const char *pat)
262 */ 273 */
263bool strlazymatch(const char *str, const char *pat) 274bool strlazymatch(const char *str, const char *pat)
264{ 275{
265 return __match_glob(str, pat, true); 276 return __match_glob(str, pat, true, false);
266} 277}
267 278
268/** 279/**
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index 20c2e5743903..6fec84dff3f7 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -357,8 +357,8 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
357 di.format = UNW_INFO_FORMAT_REMOTE_TABLE; 357 di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
358 di.start_ip = map->start; 358 di.start_ip = map->start;
359 di.end_ip = map->end; 359 di.end_ip = map->end;
360 di.u.rti.segbase = map->start + segbase; 360 di.u.rti.segbase = map->start + segbase - map->pgoff;
361 di.u.rti.table_data = map->start + table_data; 361 di.u.rti.table_data = map->start + table_data - map->pgoff;
362 di.u.rti.table_len = fde_count * sizeof(struct table_entry) 362 di.u.rti.table_len = fde_count * sizeof(struct table_entry)
363 / sizeof(unw_word_t); 363 / sizeof(unw_word_t);
364 ret = dwarf_search_unwind_table(as, ip, &di, pi, 364 ret = dwarf_search_unwind_table(as, ip, &di, pi,
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 43899e0d6fa1..71b6992f1d98 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -222,6 +222,7 @@ s64 perf_atoll(const char *str);
222char **argv_split(const char *str, int *argcp); 222char **argv_split(const char *str, int *argcp);
223void argv_free(char **argv); 223void argv_free(char **argv);
224bool strglobmatch(const char *str, const char *pat); 224bool strglobmatch(const char *str, const char *pat);
225bool strglobmatch_nocase(const char *str, const char *pat);
225bool strlazymatch(const char *str, const char *pat); 226bool strlazymatch(const char *str, const char *pat);
226static inline bool strisglob(const char *str) 227static inline bool strisglob(const char *str)
227{ 228{
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index 0fb3c1fcd3e6..5074be4ed467 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -2,15 +2,18 @@
2 2
3#include "util.h" 3#include "util.h"
4#include "values.h" 4#include "values.h"
5#include "debug.h"
5 6
6void perf_read_values_init(struct perf_read_values *values) 7int perf_read_values_init(struct perf_read_values *values)
7{ 8{
8 values->threads_max = 16; 9 values->threads_max = 16;
9 values->pid = malloc(values->threads_max * sizeof(*values->pid)); 10 values->pid = malloc(values->threads_max * sizeof(*values->pid));
10 values->tid = malloc(values->threads_max * sizeof(*values->tid)); 11 values->tid = malloc(values->threads_max * sizeof(*values->tid));
11 values->value = malloc(values->threads_max * sizeof(*values->value)); 12 values->value = malloc(values->threads_max * sizeof(*values->value));
12 if (!values->pid || !values->tid || !values->value) 13 if (!values->pid || !values->tid || !values->value) {
13 die("failed to allocate read_values threads arrays"); 14 pr_debug("failed to allocate read_values threads arrays");
15 goto out_free_pid;
16 }
14 values->threads = 0; 17 values->threads = 0;
15 18
16 values->counters_max = 16; 19 values->counters_max = 16;
@@ -18,9 +21,22 @@ void perf_read_values_init(struct perf_read_values *values)
18 * sizeof(*values->counterrawid)); 21 * sizeof(*values->counterrawid));
19 values->countername = malloc(values->counters_max 22 values->countername = malloc(values->counters_max
20 * sizeof(*values->countername)); 23 * sizeof(*values->countername));
21 if (!values->counterrawid || !values->countername) 24 if (!values->counterrawid || !values->countername) {
22 die("failed to allocate read_values counters arrays"); 25 pr_debug("failed to allocate read_values counters arrays");
26 goto out_free_counter;
27 }
23 values->counters = 0; 28 values->counters = 0;
29
30 return 0;
31
32out_free_counter:
33 zfree(&values->counterrawid);
34 zfree(&values->countername);
35out_free_pid:
36 zfree(&values->pid);
37 zfree(&values->tid);
38 zfree(&values->value);
39 return -ENOMEM;
24} 40}
25 41
26void perf_read_values_destroy(struct perf_read_values *values) 42void perf_read_values_destroy(struct perf_read_values *values)
@@ -41,17 +57,27 @@ void perf_read_values_destroy(struct perf_read_values *values)
41 zfree(&values->countername); 57 zfree(&values->countername);
42} 58}
43 59
44static void perf_read_values__enlarge_threads(struct perf_read_values *values) 60static int perf_read_values__enlarge_threads(struct perf_read_values *values)
45{ 61{
46 values->threads_max *= 2; 62 int nthreads_max = values->threads_max * 2;
47 values->pid = realloc(values->pid, 63 void *npid = realloc(values->pid, nthreads_max * sizeof(*values->pid)),
48 values->threads_max * sizeof(*values->pid)); 64 *ntid = realloc(values->tid, nthreads_max * sizeof(*values->tid)),
49 values->tid = realloc(values->tid, 65 *nvalue = realloc(values->value, nthreads_max * sizeof(*values->value));
50 values->threads_max * sizeof(*values->tid)); 66
51 values->value = realloc(values->value, 67 if (!npid || !ntid || !nvalue)
52 values->threads_max * sizeof(*values->value)); 68 goto out_err;
53 if (!values->pid || !values->tid || !values->value) 69
54 die("failed to enlarge read_values threads arrays"); 70 values->threads_max = nthreads_max;
71 values->pid = npid;
72 values->tid = ntid;
73 values->value = nvalue;
74 return 0;
75out_err:
76 free(npid);
77 free(ntid);
78 free(nvalue);
79 pr_debug("failed to enlarge read_values threads arrays");
80 return -ENOMEM;
55} 81}
56 82
57static int perf_read_values__findnew_thread(struct perf_read_values *values, 83static int perf_read_values__findnew_thread(struct perf_read_values *values,
@@ -63,15 +89,21 @@ static int perf_read_values__findnew_thread(struct perf_read_values *values,
63 if (values->pid[i] == pid && values->tid[i] == tid) 89 if (values->pid[i] == pid && values->tid[i] == tid)
64 return i; 90 return i;
65 91
66 if (values->threads == values->threads_max) 92 if (values->threads == values->threads_max) {
67 perf_read_values__enlarge_threads(values); 93 i = perf_read_values__enlarge_threads(values);
94 if (i < 0)
95 return i;
96 }
68 97
69 i = values->threads++; 98 i = values->threads + 1;
99 values->value[i] = malloc(values->counters_max * sizeof(**values->value));
100 if (!values->value[i]) {
101 pr_debug("failed to allocate read_values counters array");
102 return -ENOMEM;
103 }
70 values->pid[i] = pid; 104 values->pid[i] = pid;
71 values->tid[i] = tid; 105 values->tid[i] = tid;
72 values->value[i] = malloc(values->counters_max * sizeof(**values->value)); 106 values->threads = i;
73 if (!values->value[i])
74 die("failed to allocate read_values counters array");
75 107
76 return i; 108 return i;
77} 109}
@@ -115,16 +147,21 @@ static int perf_read_values__findnew_counter(struct perf_read_values *values,
115 return i; 147 return i;
116} 148}
117 149
118void perf_read_values_add_value(struct perf_read_values *values, 150int perf_read_values_add_value(struct perf_read_values *values,
119 u32 pid, u32 tid, 151 u32 pid, u32 tid,
120 u64 rawid, const char *name, u64 value) 152 u64 rawid, const char *name, u64 value)
121{ 153{
122 int tindex, cindex; 154 int tindex, cindex;
123 155
124 tindex = perf_read_values__findnew_thread(values, pid, tid); 156 tindex = perf_read_values__findnew_thread(values, pid, tid);
157 if (tindex < 0)
158 return tindex;
125 cindex = perf_read_values__findnew_counter(values, rawid, name); 159 cindex = perf_read_values__findnew_counter(values, rawid, name);
160 if (cindex < 0)
161 return cindex;
126 162
127 values->value[tindex][cindex] = value; 163 values->value[tindex][cindex] = value;
164 return 0;
128} 165}
129 166
130static void perf_read_values__display_pretty(FILE *fp, 167static void perf_read_values__display_pretty(FILE *fp,
diff --git a/tools/perf/util/values.h b/tools/perf/util/values.h
index b21a80c6cf8d..808ff9c73bf5 100644
--- a/tools/perf/util/values.h
+++ b/tools/perf/util/values.h
@@ -14,10 +14,10 @@ struct perf_read_values {
14 u64 **value; 14 u64 **value;
15}; 15};
16 16
17void perf_read_values_init(struct perf_read_values *values); 17int perf_read_values_init(struct perf_read_values *values);
18void perf_read_values_destroy(struct perf_read_values *values); 18void perf_read_values_destroy(struct perf_read_values *values);
19 19
20void perf_read_values_add_value(struct perf_read_values *values, 20int perf_read_values_add_value(struct perf_read_values *values,
21 u32 pid, u32 tid, 21 u32 pid, u32 tid,
22 u64 rawid, const char *name, u64 value); 22 u64 rawid, const char *name, u64 value);
23 23