diff options
author | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2019-12-19 10:33:36 +0100 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2019-12-19 10:33:36 +0100 |
commit | 01956ef82685c0793214d0bd28889304c7ed9068 (patch) | |
tree | 8d4ec514ba1c9e88cb0fd90871777d4917ff113f /tools/perf | |
parent | 866ced99cbaa08b8dafdc0b0febf49cd6c3cf5a8 (diff) | |
parent | fa8a03bec68d9ef89da72277bd3501ed3daa6217 (diff) |
Merge branch 'github.com/Freescale/linux-fslc/4.14-2.0.x-imx' into toradex_4.14-2.0.x-imx-next
Conflicts:
sound/soc/codecs/sgtl5000.c
Diffstat (limited to 'tools/perf')
37 files changed, 295 insertions, 58 deletions
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index ecdc3770d899..b8f301ea30af 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -780,7 +780,7 @@ ifndef NO_JVMTI JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}') else ifneq (,$(wildcard /usr/sbin/alternatives)) - JDIR=$(shell /usr/sbin/alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g') + JDIR=$(shell /usr/sbin/alternatives --display java | tail -1 | cut -d' ' -f 5 | sed -e 's%/jre/bin/java.%%g' -e 's%/bin/java.%%g') endif endif ifndef JDIR diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index fbfc055d3f4d..aec62e822bab 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -43,6 +43,8 @@ struct cs_etm_recording { struct auxtrace_record itr; struct perf_pmu *cs_etm_pmu; struct perf_evlist *evlist; + int wrapped_cnt; + bool *wrapped; bool snapshot_mode; size_t snapshot_size; }; @@ -485,16 +487,131 @@ static int cs_etm_info_fill(struct auxtrace_record *itr, return 0; } -static int cs_etm_find_snapshot(struct auxtrace_record *itr __maybe_unused, +static int cs_etm_alloc_wrapped_array(struct cs_etm_recording *ptr, int idx) +{ + bool *wrapped; + int cnt = ptr->wrapped_cnt; + + /* Make @ptr->wrapped as big as @idx */ + while (cnt <= idx) + cnt++; + + /* + * Free'ed in cs_etm_recording_free(). Using realloc() to avoid + * cross compilation problems where the host's system supports + * reallocarray() but not the target. + */ + wrapped = realloc(ptr->wrapped, cnt * sizeof(bool)); + if (!wrapped) + return -ENOMEM; + + wrapped[cnt - 1] = false; + ptr->wrapped_cnt = cnt; + ptr->wrapped = wrapped; + + return 0; +} + +static bool cs_etm_buffer_has_wrapped(unsigned char *buffer, + size_t buffer_size, u64 head) +{ + u64 i, watermark; + u64 *buf = (u64 *)buffer; + size_t buf_size = buffer_size; + + /* + * We want to look the very last 512 byte (chosen arbitrarily) in + * the ring buffer. + */ + watermark = buf_size - 512; + + /* + * @head is continuously increasing - if its value is equal or greater + * than the size of the ring buffer, it has wrapped around. + */ + if (head >= buffer_size) + return true; + + /* + * The value of @head is somewhere within the size of the ring buffer. + * This can be that there hasn't been enough data to fill the ring + * buffer yet or the trace time was so long that @head has numerically + * wrapped around. To find we need to check if we have data at the very + * end of the ring buffer. We can reliably do this because mmap'ed + * pages are zeroed out and there is a fresh mapping with every new + * session. + */ + + /* @head is less than 512 byte from the end of the ring buffer */ + if (head > watermark) + watermark = head; + + /* + * Speed things up by using 64 bit transactions (see "u64 *buf" above) + */ + watermark >>= 3; + buf_size >>= 3; + + /* + * If we find trace data at the end of the ring buffer, @head has + * been there and has numerically wrapped around at least once. + */ + for (i = watermark; i < buf_size; i++) + if (buf[i]) + return true; + + return false; +} + +static int cs_etm_find_snapshot(struct auxtrace_record *itr, int idx, struct auxtrace_mmap *mm, - unsigned char *data __maybe_unused, + unsigned char *data, u64 *head, u64 *old) { + int err; + bool wrapped; + struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); + + /* + * Allocate memory to keep track of wrapping if this is the first + * time we deal with this *mm. + */ + if (idx >= ptr->wrapped_cnt) { + err = cs_etm_alloc_wrapped_array(ptr, idx); + if (err) + return err; + } + + /* + * Check to see if *head has wrapped around. If it hasn't only the + * amount of data between *head and *old is snapshot'ed to avoid + * bloating the perf.data file with zeros. But as soon as *head has + * wrapped around the entire size of the AUX ring buffer it taken. + */ + wrapped = ptr->wrapped[idx]; + if (!wrapped && cs_etm_buffer_has_wrapped(data, mm->len, *head)) { + wrapped = true; + ptr->wrapped[idx] = true; + } + pr_debug3("%s: mmap index %d old head %zu new head %zu size %zu\n", __func__, idx, (size_t)*old, (size_t)*head, mm->len); - *old = *head; - *head += mm->len; + /* No wrap has occurred, we can just use *head and *old. */ + if (!wrapped) + return 0; + + /* + * *head has wrapped around - adjust *head and *old to pickup the + * entire content of the AUX buffer. + */ + if (*head >= mm->len) { + *old = *head - mm->len; + } else { + *head += mm->len; + *old = *head - mm->len; + } return 0; } @@ -535,6 +652,8 @@ static void cs_etm_recording_free(struct auxtrace_record *itr) { struct cs_etm_recording *ptr = container_of(itr, struct cs_etm_recording, itr); + + zfree(&ptr->wrapped); free(ptr); } diff --git a/tools/perf/arch/s390/util/machine.c b/tools/perf/arch/s390/util/machine.c index 0b2054007314..c8c86a0c9b79 100644 --- a/tools/perf/arch/s390/util/machine.c +++ b/tools/perf/arch/s390/util/machine.c @@ -5,16 +5,48 @@ #include "util.h" #include "machine.h" #include "api/fs/fs.h" +#include "debug.h" +#include "symbol.h" -int arch__fix_module_text_start(u64 *start, const char *name) +int arch__fix_module_text_start(u64 *start, u64 *size, const char *name) { + u64 m_start = *start; char path[PATH_MAX]; snprintf(path, PATH_MAX, "module/%.*s/sections/.text", (int)strlen(name) - 2, name + 1); - - if (sysfs__read_ull(path, (unsigned long long *)start) < 0) - return -1; + if (sysfs__read_ull(path, (unsigned long long *)start) < 0) { + pr_debug2("Using module %s start:%#lx\n", path, m_start); + *start = m_start; + } else { + /* Successful read of the modules segment text start address. + * Calculate difference between module start address + * in memory and module text segment start address. + * For example module load address is 0x3ff8011b000 + * (from /proc/modules) and module text segment start + * address is 0x3ff8011b870 (from file above). + * + * Adjust the module size and subtract the GOT table + * size located at the beginning of the module. + */ + *size -= (*start - m_start); + } return 0; } + +/* On s390 kernel text segment start is located at very low memory addresses, + * for example 0x10000. Modules are located at very high memory addresses, + * for example 0x3ff xxxx xxxx. The gap between end of kernel text segment + * and beginning of first module's text segment is very big. + * Therefore do not fill this gap and do not assign it to the kernel dso map. + */ +void arch__symbols__fixup_end(struct symbol *p, struct symbol *c) +{ + if (strchr(p->name, '[') == NULL && strchr(c->name, '[')) + /* Last kernel symbol mapped to end of page */ + p->end = roundup(p->end, page_size); + else + p->end = c->start; + pr_debug4("%s sym:%s end:%#lx\n", __func__, p->name, p->end); +} diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c b/tools/perf/arch/x86/util/unwind-libunwind.c index 05920e3edf7a..47357973b55b 100644 --- a/tools/perf/arch/x86/util/unwind-libunwind.c +++ b/tools/perf/arch/x86/util/unwind-libunwind.c @@ -1,11 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 #include <errno.h> +#include "../../util/debug.h" #ifndef REMOTE_UNWIND_LIBUNWIND #include <libunwind.h> #include "perf_regs.h" #include "../../util/unwind.h" -#include "../../util/debug.h" #endif #ifdef HAVE_ARCH_X86_64_SUPPORT diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c index 997875c770b1..275f1c3c73b6 100644 --- a/tools/perf/bench/numa.c +++ b/tools/perf/bench/numa.c @@ -378,8 +378,10 @@ static u8 *alloc_data(ssize_t bytes0, int map_flags, /* Allocate and initialize all memory on CPU#0: */ if (init_cpu0) { - orig_mask = bind_to_node(0); - bind_to_memnode(0); + int node = numa_node_of_cpu(0); + + orig_mask = bind_to_node(node); + bind_to_memnode(node); } bytes = bytes0 + HPSIZE; diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 32e64a8a6443..bec7a2f1fb4d 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2454,6 +2454,7 @@ static int build_cl_output(char *cl_sort, bool no_source) bool add_sym = false; bool add_dso = false; bool add_src = false; + int ret = 0; if (!buf) return -ENOMEM; @@ -2472,7 +2473,8 @@ static int build_cl_output(char *cl_sort, bool no_source) add_dso = true; } else if (strcmp(tok, "offset")) { pr_err("unrecognized sort token: %s\n", tok); - return -EINVAL; + ret = -EINVAL; + goto err; } } @@ -2495,13 +2497,15 @@ static int build_cl_output(char *cl_sort, bool no_source) add_sym ? "symbol," : "", add_dso ? "dso," : "", add_src ? "cl_srcline," : "", - "node") < 0) - return -ENOMEM; + "node") < 0) { + ret = -ENOMEM; + goto err; + } c2c.show_src = add_src; - +err: free(buf); - return 0; + return ret; } static int setup_coalesce(const char *coalesce, bool no_source) diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index 25a42acabee1..13a33fb71a6d 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -162,7 +162,7 @@ static int set_tracing_cpumask(struct cpu_map *cpumap) int last_cpu; last_cpu = cpu_map__cpu(cpumap, cpumap->nr - 1); - mask_size = (last_cpu + 3) / 4 + 1; + mask_size = last_cpu / 4 + 2; /* one more byte for EOS */ mask_size += last_cpu / 32; /* ',' is needed for every 32th cpus */ cpumask = malloc(mask_size); diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index a0f7ed2b869b..3c364798093b 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -189,7 +189,7 @@ static void add_man_viewer(const char *name) while (*p) p = &((*p)->next); *p = zalloc(sizeof(**p) + len + 1); - strncpy((*p)->name, name, len); + strcpy((*p)->name, name); } static int supported_man_viewer(const char *name, size_t len) diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 9e693ce4b73b..ce786f363476 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -687,6 +687,7 @@ static char *compact_gfp_flags(char *gfp_flags) new = realloc(new_flags, len + strlen(cpt) + 2); if (new == NULL) { free(new_flags); + free(orig_flags); return NULL; } diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index c0065923a525..e1ac51aaedcf 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -712,6 +712,16 @@ __cmd_probe(int argc, const char **argv) ret = perf_add_probe_events(params.events, params.nevents); if (ret < 0) { + + /* + * When perf_add_probe_events() fails it calls + * cleanup_perf_probe_events(pevs, npevs), i.e. + * cleanup_perf_probe_events(params.events, params.nevents), which + * will call clear_perf_probe_event(), so set nevents to zero + * to avoid cleanup_params() to call clear_perf_probe_event() again + * on the same pevs. + */ + params.nevents = 0; pr_err_with_code(" Error: Failed to add events.", ret); return ret; } diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 52486c90ab93..0801e0ffba4a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -2769,8 +2769,11 @@ int cmd_stat(int argc, const char **argv) fprintf(output, "[ perf stat: executing run #%d ... ]\n", run_idx + 1); + if (run_idx != 0) + perf_evlist__reset_prev_raw_counts(evsel_list); + status = run_perf_stat(argc, argv); - if (forever && status != -1) { + if (forever && status != -1 && !interval) { print_counters(NULL, argc, argv); perf_stat__reset_stats(); } diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 96f62dd7e3ed..d4ebd0956114 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -25,7 +25,7 @@ static inline unsigned long long rdclock(void) } #ifndef MAX_NR_CPUS -#define MAX_NR_CPUS 1024 +#define MAX_NR_CPUS 2048 #endif extern const char *input_name; diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c index d51dc9ca8861..6f9f247b4516 100644 --- a/tools/perf/pmu-events/jevents.c +++ b/tools/perf/pmu-events/jevents.c @@ -342,11 +342,12 @@ static struct fixed { const char *name; const char *event; } fixed[] = { - { "inst_retired.any", "event=0xc0" }, - { "inst_retired.any_p", "event=0xc0" }, - { "cpu_clk_unhalted.ref", "event=0x0,umask=0x03" }, - { "cpu_clk_unhalted.thread", "event=0x3c" }, - { "cpu_clk_unhalted.thread_any", "event=0x3c,any=1" }, + { "inst_retired.any", "event=0xc0,period=2000003" }, + { "inst_retired.any_p", "event=0xc0,period=2000003" }, + { "cpu_clk_unhalted.ref", "event=0x0,umask=0x03,period=2000003" }, + { "cpu_clk_unhalted.thread", "event=0x3c,period=2000003" }, + { "cpu_clk_unhalted.core", "event=0x3c,period=2000003" }, + { "cpu_clk_unhalted.thread_any", "event=0x3c,any=1,period=2000003" }, { NULL, NULL}, }; diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c index 3c3f3e029e33..2ecb86876f10 100644 --- a/tools/perf/tests/mmap-thread-lookup.c +++ b/tools/perf/tests/mmap-thread-lookup.c @@ -52,7 +52,7 @@ static void *thread_fn(void *arg) { struct thread_data *td = arg; ssize_t ret; - int go; + int go = 0; if (thread_init(td)) return NULL; diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c index a693bcf017ea..44c16fd11bf6 100644 --- a/tools/perf/tests/perf-hooks.c +++ b/tools/perf/tests/perf-hooks.c @@ -20,12 +20,11 @@ static void sigsegv_handler(int sig __maybe_unused) static void the_hook(void *_hook_flags) { int *hook_flags = _hook_flags; - int *p = NULL; *hook_flags = 1234; /* Generate a segfault, test perf_hooks__recover */ - *p = 0; + raise(SIGSEGV); } int test__perf_hooks(struct test *test __maybe_unused, int subtest __maybe_unused) diff --git a/tools/perf/tests/shell/trace+probe_vfs_getname.sh b/tools/perf/tests/shell/trace+probe_vfs_getname.sh index 2a9ef080efd0..a8a516dec4ed 100755 --- a/tools/perf/tests/shell/trace+probe_vfs_getname.sh +++ b/tools/perf/tests/shell/trace+probe_vfs_getname.sh @@ -30,6 +30,10 @@ if [ $err -ne 0 ] ; then exit $err fi +# Do not use whatever ~/.perfconfig file, it may change the output +# via trace.{show_timestamp,show_prefix,etc} +export PERF_CONFIG=/dev/null + trace_open_vfs_getname err=$? rm -f ${file} diff --git a/tools/perf/trace/beauty/ioctl.c b/tools/perf/trace/beauty/ioctl.c index 1be3b4cf0827..82346ca06f17 100644 --- a/tools/perf/trace/beauty/ioctl.c +++ b/tools/perf/trace/beauty/ioctl.c @@ -22,7 +22,7 @@ static size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size) { static const char *ioctl_tty_cmd[] = { - "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW", + [_IOC_NR(TCGETS)] = "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW", "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL", "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI", "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC", "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", diff --git a/tools/perf/ui/tui/helpline.c b/tools/perf/ui/tui/helpline.c index 4ca799aadb4e..93d6b7240285 100644 --- a/tools/perf/ui/tui/helpline.c +++ b/tools/perf/ui/tui/helpline.c @@ -24,7 +24,7 @@ static void tui_helpline__push(const char *msg) SLsmg_set_color(0); SLsmg_write_nstring((char *)msg, SLtt_Screen_Cols); SLsmg_refresh(); - strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0'; + strlcpy(ui_helpline__current, msg, sz); } static int tui_helpline__show(const char *format, va_list ap) diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 398d4cc2f0e4..2a8d2a6723f6 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -868,16 +868,14 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp) *namep = strdup(name); if (*namep == NULL) - goto out_free_name; + goto out; (*rawp)[0] = tmp; *rawp = ltrim(*rawp); return 0; -out_free_name: - free((void *)namep); - *namep = NULL; +out: return -1; } diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 383674f448fc..f93846edc1e0 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -701,7 +701,10 @@ size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size) unsigned char *bitmap; int last_cpu = cpu_map__cpu(map, map->nr - 1); - bitmap = zalloc((last_cpu + 7) / 8); + if (buf == NULL) + return 0; + + bitmap = zalloc(last_cpu / 8 + 1); if (bitmap == NULL) { buf[0] = '\0'; return 0; diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 2346cecb8ea2..5131304ea3a8 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -271,7 +271,7 @@ static int string_set_value(struct bt_ctf_field *field, const char *string) if (i > 0) strncpy(buffer, string, i); } - strncat(buffer + p, numstr, 4); + memcpy(buffer + p, numstr, 4); p += 3; } } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0cf6f537f980..3ab81e8e079e 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -587,6 +587,9 @@ const char *perf_evsel__name(struct perf_evsel *evsel) { char bf[128]; + if (!evsel) + goto out_unknown; + if (evsel->name) return evsel->name; @@ -623,7 +626,10 @@ const char *perf_evsel__name(struct perf_evsel *evsel) evsel->name = strdup(bf); - return evsel->name ?: "unknown"; + if (evsel->name) + return evsel->name; +out_unknown: + return "unknown"; } const char *perf_evsel__group_name(struct perf_evsel *evsel) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 696f2654826b..c892bb4f26c3 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1063,7 +1063,7 @@ static int cpu_cache_level__read(struct cpu_cache_level *cache, u32 cpu, u16 lev scnprintf(file, PATH_MAX, "%s/shared_cpu_list", path); if (sysfs__read_str(file, &cache->map, &len)) { - free(cache->map); + free(cache->size); free(cache->type); return -1; } @@ -1122,7 +1122,7 @@ static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp) return 0; } -#define MAX_CACHES 2000 +#define MAX_CACHES (MAX_NR_CPUS * 4) static int write_cache(struct feat_fd *ff, struct perf_evlist *evlist __maybe_unused) @@ -1882,8 +1882,10 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) /* On s390 the socket_id number is not related to the numbers of cpus. * The socket_id number might be higher than the numbers of cpus. * This depends on the configuration. + * AArch64 is the same. */ - if (ph->env.arch && !strncmp(ph->env.arch, "s390", 4)) + if (ph->env.arch && (!strncmp(ph->env.arch, "s390", 4) + || !strncmp(ph->env.arch, "aarch64", 7))) do_core_id_test = false; for (i = 0; i < (u32)cpu_nr; i++) { @@ -2901,6 +2903,13 @@ int perf_session__read_header(struct perf_session *session) file->path); } + if (f_header.attr_size == 0) { + pr_err("ERROR: The %s file's attr size field is 0 which is unexpected.\n" + "Was the 'perf record' command properly terminated?\n", + file->path); + return -EINVAL; + } + nr_attrs = f_header.attrs.size / f_header.attr_size; lseek(fd, f_header.attrs.offset, SEEK_SET); @@ -2983,7 +2992,7 @@ int perf_event__synthesize_attr(struct perf_tool *tool, size += sizeof(struct perf_event_header); size += ids * sizeof(u64); - ev = malloc(size); + ev = zalloc(size); if (ev == NULL) return -ENOMEM; @@ -3081,7 +3090,7 @@ int perf_event__process_feature(struct perf_tool *tool, return 0; ff.buf = (void *)fe->data; - ff.size = event->header.size - sizeof(event->header); + ff.size = event->header.size - sizeof(*fe); ff.ph = &session->header; if (feat_ops[feat].process(&ff, NULL)) @@ -3171,7 +3180,7 @@ perf_event__synthesize_event_update_name(struct perf_tool *tool, if (ev == NULL) return -ENOMEM; - strncpy(ev->data, evsel->name, len); + strlcpy(ev->data, evsel->name, len + 1); err = process(tool, (union perf_event*) ev, NULL, NULL); free(ev); return err; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 5b8bc1fd943d..c1f9615b02f7 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1504,7 +1504,7 @@ int hists__collapse_resort(struct hists *hists, struct ui_progress *prog) return 0; } -static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b) +static int64_t hist_entry__sort(struct hist_entry *a, struct hist_entry *b) { struct hists *hists = a->hists; struct perf_hpp_fmt *fmt; diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 36483db032e8..3f02a5e284b2 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -394,7 +394,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) size_t size; u16 idr_size; const char *sym; - uint32_t count; + uint64_t count; int ret, csize, usize; pid_t pid, tid; struct { @@ -417,7 +417,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) return -1; filename = event->mmap2.filename; - size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%u.so", + size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%" PRIu64 ".so", jd->dir, pid, count); @@ -530,7 +530,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) return -1; filename = event->mmap2.filename; - size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%"PRIu64, + size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%" PRIu64 ".so", jd->dir, pid, jr->move.code_index); diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c index 2bdaac048a0a..da59a9e9543b 100644 --- a/tools/perf/util/llvm-utils.c +++ b/tools/perf/util/llvm-utils.c @@ -225,14 +225,14 @@ static int detect_kbuild_dir(char **kbuild_dir) const char *prefix_dir = ""; const char *suffix_dir = ""; + /* _UTSNAME_LENGTH is 65 */ + char release[128]; + char *autoconf_path; int err; if (!test_dir) { - /* _UTSNAME_LENGTH is 65 */ - char release[128]; - err = fetch_kernel_version(NULL, release, sizeof(release)); if (err) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 968fd0454e6b..5145c6a84c47 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -156,6 +156,9 @@ void machine__delete_threads(struct machine *machine) void machine__exit(struct machine *machine) { + if (machine == NULL) + return; + machine__destroy_kernel_maps(machine); map_groups__exit(&machine->kmaps); dsos__exit(&machine->dsos); @@ -1230,6 +1233,7 @@ static int machine__set_modules_path(struct machine *machine) return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0); } int __weak arch__fix_module_text_start(u64 *start __maybe_unused, + u64 *size __maybe_unused, const char *name __maybe_unused) { return 0; @@ -1241,7 +1245,7 @@ static int machine__create_module(void *arg, const char *name, u64 start, struct machine *machine = arg; struct map *map; - if (arch__fix_module_text_start(&start, name) < 0) + if (arch__fix_module_text_start(&start, &size, name) < 0) return -1; map = machine__findnew_module_map(machine, start, name); diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 13041b036a5b..ec339cdf854c 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -213,7 +213,7 @@ struct symbol *machine__find_kernel_function_by_name(struct machine *machine, struct map *machine__findnew_module_map(struct machine *machine, u64 start, const char *filename); -int arch__fix_module_text_start(u64 *start, const char *name); +int arch__fix_module_text_start(u64 *start, u64 *size, const char *name); int __machine__load_kallsyms(struct machine *machine, const char *filename, enum map_type type, bool no_kcore); diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 4e7bd2750122..63db9872c880 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include "symbol.h" +#include <assert.h> #include <errno.h> #include <inttypes.h> #include <limits.h> @@ -737,6 +738,8 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp } after->start = map->end; + after->pgoff += map->end - pos->start; + assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end)); __map_groups__insert(pos->groups, after); if (verbose >= 2 && !use_browser) map__fprintf(after, fp); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index da55081aefc6..c49e8ea1a42c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1145,6 +1145,9 @@ static void dump_read(struct perf_evsel *evsel, union perf_event *event) evsel ? perf_evsel__name(evsel) : "FAIL", event->read.value); + if (!evsel) + return; + read_format = evsel->attr.read_format; if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 37363869c9a1..eadc9a2aef16 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -271,7 +271,7 @@ static struct perf_evsel *perf_stat__find_event(struct perf_evlist *evsel_list, struct perf_evsel *c2; evlist__for_each_entry (evsel_list, c2) { - if (!strcasecmp(c2->name, name)) + if (!strcasecmp(c2->name, name) && !c2->collect_stat) return c2; } return NULL; @@ -310,7 +310,8 @@ void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list) if (leader) { /* Search in group */ for_each_group_member (oc, leader) { - if (!strcasecmp(oc->name, metric_names[i])) { + if (!strcasecmp(oc->name, metric_names[i]) && + !oc->collect_stat) { found = true; break; } diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index c9bae5fb8b47..d028c2786802 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -154,6 +154,15 @@ static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) evsel->prev_raw_counts = NULL; } +static void perf_evsel__reset_prev_raw_counts(struct perf_evsel *evsel) +{ + if (evsel->prev_raw_counts) { + evsel->prev_raw_counts->aggr.val = 0; + evsel->prev_raw_counts->aggr.ena = 0; + evsel->prev_raw_counts->aggr.run = 0; + } +} + static int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw) { int ncpus = perf_evsel__nr_cpus(evsel); @@ -204,6 +213,14 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist) } } +void perf_evlist__reset_prev_raw_counts(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + evlist__for_each_entry(evlist, evsel) + perf_evsel__reset_prev_raw_counts(evsel); +} + static void zero_per_pkg(struct perf_evsel *counter) { if (counter->per_pkg_mask) diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 96326b1f9443..bdfbed8e2df2 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -100,6 +100,7 @@ void perf_stat__collect_metric_expr(struct perf_evlist *); int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw); void perf_evlist__free_stats(struct perf_evlist *evlist); void perf_evlist__reset_stats(struct perf_evlist *evlist); +void perf_evlist__reset_prev_raw_counts(struct perf_evlist *evlist); int perf_stat_process_counter(struct perf_stat_config *config, struct perf_evsel *counter); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 3936f69f385c..27bffcb213eb 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -93,6 +93,11 @@ static int prefix_underscores_count(const char *str) return tail - str; } +void __weak arch__symbols__fixup_end(struct symbol *p, struct symbol *c) +{ + p->end = c->start; +} + const char * __weak arch__normalize_symbol_name(const char *name) { return name; @@ -219,7 +224,7 @@ void symbols__fixup_end(struct rb_root *symbols) curr = rb_entry(nd, struct symbol, rb_node); if (prev->end == prev->start && prev->end != curr->start) - prev->end = curr->start; + arch__symbols__fixup_end(prev, curr); } /* Last entry */ diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 698c65e603a8..95ac21be8481 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -351,6 +351,7 @@ const char *arch__normalize_symbol_name(const char *name); #define SYMBOL_A 0 #define SYMBOL_B 1 +void arch__symbols__fixup_end(struct symbol *p, struct symbol *c); int arch__compare_symbol_names(const char *namea, const char *nameb); int arch__compare_symbol_names_n(const char *namea, const char *nameb, unsigned int n); diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 1dbcd3c8dee0..177436c8e026 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -160,14 +160,24 @@ struct comm *thread__comm(const struct thread *thread) struct comm *thread__exec_comm(const struct thread *thread) { - struct comm *comm, *last = NULL; + struct comm *comm, *last = NULL, *second_last = NULL; list_for_each_entry(comm, &thread->comm_list, list) { if (comm->exec) return comm; + second_last = last; last = comm; } + /* + * 'last' with no start time might be the parent's comm of a synthesized + * thread (created by processing a synthesized fork event). For a main + * thread, that is very probably wrong. Prefer a later comm to avoid + * that case. + */ + if (second_last && !last->start && thread->pid_ == thread->tid) + return second_last; + return last; } diff --git a/tools/perf/util/xyarray.h b/tools/perf/util/xyarray.h index 7ffe562e7ae7..2627b038b6f2 100644 --- a/tools/perf/util/xyarray.h +++ b/tools/perf/util/xyarray.h @@ -2,6 +2,7 @@ #ifndef _PERF_XYARRAY_H_ #define _PERF_XYARRAY_H_ 1 +#include <linux/compiler.h> #include <sys/types.h> struct xyarray { @@ -10,7 +11,7 @@ struct xyarray { size_t entries; size_t max_x; size_t max_y; - char contents[]; + char contents[] __aligned(8); }; struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size); |