perf fixes
Linus,
Please pull the latest perf-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf-urgent-for-linus
# HEAD: 47c1ded7fef108c730b803cd386241beffcdd15c Merge tag 'perf-urgent-for-mingo-4.12-20170608' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
This is mostly tooling fixes, plus an instruction pointer filtering fix. It's more fixes than usual - Arnaldo got back from a longer vacation and there was a backlog.
Thanks,
Ingo
------------------>
Andi Kleen (1):
perf stat: Only print NMI watchdog hint when enabled
Jin Yao (1):
perf/core: Drop kernel samples even though :u is specified
Jiri Olsa (2):
perf trace: Add mmap alias for s390
perf test: Disable breakpoint signal tests for powerpc
Kim Phillips (2):
perf annotate: Fix branch instruction with multiple operands perf annotate: Add missing powerpc triplet
Milian Wolff (2):
perf report: Include partial stacks unwound with libdw perf report: Ensure the perf DSO mapping matches what libdw sees
Namhyung Kim (12):
perf header: Set proper module name when build-id event found perf symbols: Set module info when build-id event found
perf symbols: Use correct filename for compressed modules in build-id cache perf annotate: Fix symbolic link of build-id cache
perf tools: Fix a memory leak in __open_dso()
perf tools: Introduce dso__decompress_kmodule_{fd,path}
perf annotate: Use dso__decompress_kmodule_path()
perf tools: Decompress kernel module when reading DSO data perf tools: Consolidate error path in __open_dso()
perf tests: Decompress kernel module before objdump
perf symbols: Keep DSO->symtab_type after decompress
perf symbols: Kill dso__build_id_is_kmod()
Ravi Bangoria (1):
perf annotate: Fix failure when filename has special chars
SeongJae Park (6):
perf probe: Fix examples section of documentation perf script: Fix outdated comment for perf-trace-python perf script: Fix documentation errors
perf script python: Fix wrong code snippets in documentation perf script python: Updated trace_unhandled() signature perf script python: Remove dups in documentation examples
kernel/events/core.c | 21 +++++ tools/perf/Documentation/perf-probe.txt | 8 +- tools/perf/Documentation/perf-script-perl.txt | 2 +- tools/perf/Documentation/perf-script-python.txt | 23 ++--- tools/perf/arch/common.c | 1 + tools/perf/builtin-stat.c | 5 +- tools/perf/builtin-trace.c | 4 + tools/perf/tests/bp_signal.c | 14 +++ tools/perf/tests/builtin-test.c | 7 ++ tools/perf/tests/code-reading.c | 20 ++++- tools/perf/tests/tests.h | 3 + tools/perf/util/annotate.c | 72 +++++++++------ tools/perf/util/build-id.c | 45 ---------- tools/perf/util/build-id.h | 1 - tools/perf/util/dso.c | 100 +++++++++++++++++++-- tools/perf/util/dso.h | 9 ++ tools/perf/util/header.c | 12 ++- tools/perf/util/machine.c | 11 +-- .../util/scripting-engines/trace-event-python.c | 2 +- tools/perf/util/symbol-elf.c | 41 +-------- tools/perf/util/symbol.c | 4 - tools/perf/util/unwind-libdw.c | 10 ++- 22 files changed, 259 insertions(+), 156 deletions(-)
kernel/events/core.c +21 -0
@@ -7316,6 +7316,21 @@ int perf_event_account_interrupt(struct perf_event *event)return __perf_event_account_interrupt (event,1 ); } +static bool sample_is_allowed (struct perf_event *event,struct pt_regs *regs) +{ +/* +* Due to interrupt latency (AKA "skid"), we may enter the +* kernel before taking an overflow, even if the PMU is only +* counting user events. +* To avoid leaking information to userspace, we must always +* reject kernel samples when exclude_kernel is set. +*/ +if (event->attr.exclude_kernel && !user_mode (regs)) +return false; + +return true; +} +/* * Generic event overflow handling, sampling. */
@@ -7337,6 +7352,12 @@ static int __perf_event_overflow(struct perf_event *event, ret =__perf_event_account_interrupt (event, throttle);/* +* For security, drop the skid kernel samples if necessary. +*/ +if (!sample_is_allowed (event, regs)) +return ret; + +/* * XXX event_limit might not quite work as expected on inherited * events */
tools/perf/Documentation/perf-probe.txt +6 -2
@@ -240,9 +240,13 @@ EXAMPLES or ./perf probe --add='schedule:12 cpu' - this will add one or more probes which has the name start with "schedule". +Add one or more probes which has the name start with "schedule". - Add probes on lines in schedule() function which calls update_rq_clock(). + ./perf probe schedule* + or + ./perf probe --add='schedule*' + +Add probes on lines in schedule() function which calls update_rq_clock(). ./perf probe 'schedule;update_rq_clock*' or
tools/perf/Documentation/perf-script-perl.txt +1 -1
@@ -39,7 +39,7 @@ EVENT HANDLERS When perf script is invoked using a trace script, a user-defined 'handler function' is called for each event in the trace. If there's no handler function defined for a given event type, the event is -ignored (or passed to a 'trace_handled' function, see below) and the +ignored (or passed to a 'trace_unhandled' function, see below) and the next event is processed. Most of the event's field values are passed as arguments to the
tools/perf/Documentation/perf-script-python.txt +9 -14
@@ -149,10 +149,8 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu, print "id=%d, args=%s\n" % \ (id, args), -def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs, - common_pid, common_comm): - print_header(event_name, common_cpu, common_secs, common_nsecs, - common_pid, common_comm) +def trace_unhandled(event_name, context, event_fields_dict): + print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) def print_header(event_name, cpu, secs, nsecs, pid, comm): print "%-20s %5u %05u.%09u %8u %-20s " % \
@@ -321,7 +319,7 @@ So those are the essential steps in writing and running a script. The process can be generalized to any tracepoint or set of tracepoints you're interested in - basically find the tracepoint(s) you're interested in by looking at the list of available events shown by -'perf list' and/or look in /sys/kernel/debug/tracing events for +'perf list' and/or look in /sys/kernel/debug/tracing/events/ for detailed event and field info, record the corresponding trace data using 'perf record', passing it the list of interesting events, generate a skeleton script using 'perf script -g python' and modify the
@@ -334,7 +332,7 @@ right place, you can have your script listed alongside the other scripts listed by the 'perf script -l' command e.g.: ---- -root@tropicana:~# perf script -l +# perf script -l List of available trace scripts: wakeup-latency system-wide min/max/avg wakeup latency rw-by-file <comm> r/w activity for a program, by file
@@ -383,8 +381,6 @@ to be located in the perf/scripts/python directory in the kernel ---- # ls -al kernel-source/tools/perf/scripts/python - -root@tropicana:/home/trz/src/tip# ls -al tools/perf/scripts/python total 32 drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 . drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
@@ -399,7 +395,7 @@ otherwise your script won't show up at run-time), 'perf script -l' should show a new entry for your script: ---- -root@tropicana:~# perf script -l +# perf script -l List of available trace scripts: wakeup-latency system-wide min/max/avg wakeup latency rw-by-file <comm> r/w activity for a program, by file
@@ -437,7 +433,7 @@ EVENT HANDLERS When perf script is invoked using a trace script, a user-defined 'handler function' is called for each event in the trace. If there's no handler function defined for a given event type, the event is -ignored (or passed to a 'trace_handled' function, see below) and the +ignored (or passed to a 'trace_unhandled' function, see below) and the next event is processed. Most of the event's field values are passed as arguments to the
@@ -532,7 +528,7 @@ Aside from the event handler functions discussed above, every script gives scripts a chance to do setup tasks: ---- -def trace_begin: +def trace_begin(): pass ----
@@ -541,7 +537,7 @@ Aside from the event handler functions discussed above, every script as display results: ---- -def trace_end: +def trace_end(): pass ----
@@ -550,8 +546,7 @@ Aside from the event handler functions discussed above, every script of common arguments are passed into it: ---- -def trace_unhandled(event_name, context, common_cpu, common_secs, - common_nsecs, common_pid, common_comm): +def trace_unhandled(event_name, context, event_fields_dict): pass ----
tools/perf/arch/common.c +1 -0
@@ -26,6 +26,7 @@ const char *const arm64_triplets[] = {const char *const powerpc_triplets[] = {"powerpc-unknown-linux-gnu-" , +"powerpc-linux-gnu-" ,"powerpc64-unknown-linux-gnu-" ,"powerpc64-linux-gnu-" ,"powerpc64le-linux-gnu-" ,
tools/perf/builtin-stat.c +4 -1
@@ -1578,6 +1578,7 @@ static void print_header(int argc, const char **argv)static void print_footer (void ) {FILE *output = stat_config.output; +int n;if (!null_run)fprintf (output,"\n" );
@@ -1590,7 +1591,9 @@ static void print_footer(void) }fprintf (output,"\n\n" ); -if (print_free_counters_hint) +if (print_free_counters_hint && +sysctl__read_int ("kernel/nmi_watchdog" , &n) >=0 && + n >0 )fprintf (output,"Some events weren't counted. Try disabling the NMI watchdog:\n" " echo 0 > /proc/sys/kernel/nmi_watchdog\n"
tools/perf/builtin-trace.c +4 -0
@@ -681,6 +681,10 @@ static struct syscall_fmt { { .name = "mlockall", .errmsg = true, .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, { .name = "mmap", .hexret = true, +/* The standard mmap maps to old_mmap on s390x */ +#if defined(__s390x__) + .alias = "old_mmap", +#endif .arg_scnprintf = { [0] = SCA_HEX, /* addr */ [2] = SCA_MMAP_PROT, /* prot */ [3] = SCA_MMAP_FLAGS, /* flags */ }, },
tools/perf/tests/bp_signal.c +14 -0
@@ -288,3 +288,17 @@ int test__bp_signal(int subtest __maybe_unused)return count1 ==1 && overflows ==3 && count2 ==3 && overflows_2 ==3 && count3 ==2 ?TEST_OK :TEST_FAIL ; } + +bool test__bp_signal_is_supported (void ) +{ +/* +* The powerpc so far does not have support to even create +* instruction breakpoint using the perf event interface. +* Once it's there we can release this. +*/ +#ifdef __powerpc__ +return false; +#else +return true; +#endif +}
tools/perf/tests/builtin-test.c +7 -0
@@ -97,10 +97,12 @@ static struct test generic_tests[] = { { .desc = "Breakpoint overflow signal handler", .func = test__bp_signal, + .is_supported = test__bp_signal_is_supported, }, { .desc = "Breakpoint overflow sampling", .func = test__bp_signal_overflow, + .is_supported = test__bp_signal_is_supported, }, { .desc = "Number of exit events of a simple workload",
@@ -401,6 +403,11 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)if (!perf_test__matches (t, curr, argc, argv))continue ; +if (t->is_supported && !t->is_supported ()) { +pr_debug ("%2d: %-*s: Disabled\n" , i, width, t->desc); +continue ; + } +pr_info ("%2d: %-*s:" , i, width, t->desc);if (intlist__find (skiplist, i)) {
tools/perf/tests/code-reading.c +19 -1
@@ -229,6 +229,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,unsigned char buf2[BUFSZ ];size_t ret_len;u64 objdump_addr; +const char *objdump_name; +char decomp_name[KMOD_DECOMP_LEN ];int ret;pr_debug ("Reading object code for memory address: %#" PRIx64"\n" , addr);
@@ -289,9 +291,25 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, state->done[state->done_cnt++] = al.map->start; } + objdump_name = al.map->dso->long_name; +if (dso__needs_decompress (al.map->dso)) { +if (dso__decompress_kmodule_path (al.map->dso, objdump_name, + decomp_name, +sizeof (decomp_name)) <0 ) { +pr_debug ("decompression failed\n" ); +return -1 ; + } + + objdump_name = decomp_name; + } +/* Read the object code using objdump */ objdump_addr =map__rip_2objdump (al.map, al.addr); - ret =read_via_objdump (al.map->dso->long_name, objdump_addr, buf2, len); + ret =read_via_objdump (objdump_name, objdump_addr, buf2, len); + +if (dso__needs_decompress (al.map->dso)) +unlink (objdump_name); +if (ret >0 ) {/* * The kernel maps are inaccurate - assume objdump is right in
tools/perf/tests/tests.h +3 -0
@@ -34,6 +34,7 @@ struct test {int (*get_nr)(void );const char *(*get_desc)(int subtest); } subtest; +bool (*is_supported)(void ); };/* Tests */
@@ -99,6 +100,8 @@ const char *test__clang_subtest_get_desc(int subtest);int test__clang_subtest_get_nr (void );int test__unit_number__scnprint (int subtest); +bool test__bp_signal_is_supported (void ); +#if defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT struct thread ;
tools/perf/util/annotate.c +43 -29
114 lines not on this page · raw message
tools/perf/util/build-id.c +0 -45
51 lines not on this page · raw message
tools/perf/util/build-id.h +0 -1
@@ -17,7 +17,6 @@ char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf, size_t size);char *dso__build_id_filename (const struct dso *dso,char *bf,size_t size); -bool dso__build_id_is_kmod (const struct dso *dso,char *bf,size_t size); int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel,
tools/perf/util/dso.c +94 -6
128 lines not on this page · raw message
tools/perf/util/dso.h +9 -0
@@ -244,6 +244,12 @@ bool is_supported_compression(const char *ext);bool is_kernel_module (const char *pathname,int cpumode);bool decompress_to_file (const char *ext,const char *filename,int output_fd);bool dso__needs_decompress (struct dso *dso); +int dso__decompress_kmodule_fd (struct dso *dso,const char *name); +int dso__decompress_kmodule_path (struct dso *dso,const char *name, +char *pathname,size_t len); + +#define KMOD_DECOMP_NAME "/tmp/perf-kmod-XXXXXX" +#define KMOD_DECOMP_LEN sizeof(KMOD_DECOMP_NAME)struct kmod_path {char *name;
@@ -259,6 +265,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,#define kmod_path__parse_name (__m, __p) __kmod_path__parse(__m, __p, true , false)#define kmod_path__parse_ext (__m, __p) __kmod_path__parse(__m, __p, false, true) +void dso__set_module_info (struct dso *dso,struct kmod_path *m, +struct machine *machine); +/* * The dso__data_* external interface provides following functions: * dso__data_get_fd
tools/perf/util/header.c +10 -2
@@ -1469,8 +1469,16 @@ static int __event_process_build_id(struct build_id_event *bev,dso__set_build_id (dso, &bev->build_id); -if (!is_kernel_module (filename, cpumode)) - dso->kernel = dso_type; +if (dso_type !=DSO_TYPE_USER ) { +struct kmod_path m = { .name =NULL , }; + +if (!kmod_path__parse_name (&m, filename) && m.kmod) +dso__set_module_info (dso, &m, machine); +else + dso->kernel = dso_type; + +free (m.name); + }build_id__sprintf (dso->build_id,sizeof (dso->build_id), sbuild_id);
tools/perf/util/machine.c +1 -10
@@ -572,16 +572,7 @@ static struct dso *machine__findnew_module_dso(struct machine *machine,if (dso ==NULL ) goto out_unlock; -if (machine__is_host (machine)) - dso->symtab_type =DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ; -else - dso->symtab_type =DSO_BINARY_TYPE__GUEST_KMODULE ; - -/* _KMODULE_COMP should be next to _KMODULE */ -if (m->kmod && m->comp) - dso->symtab_type++; - -dso__set_short_name (dso,strdup (m->name), true); +dso__set_module_info (dso, m, machine);dso__set_long_name (dso,strdup (filename), true); }
tools/perf/util/scripting-engines/trace-event-python.c +1 -1
@@ -1219,7 +1219,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)fprintf (ofp,"# be retrieved using Python functions of the form " "common_*(context).\n" ); -fprintf (ofp,"# See the perf-trace-python Documentation for the list " +fprintf (ofp,"# See the perf-script-python Documentation for the list " "of available functions.\n\n" );fprintf (ofp,"import os\n" );
tools/perf/util/symbol-elf.c +3 -38
55 lines not on this page · raw message
tools/perf/util/symbol.c +0 -4
@@ -1562,10 +1562,6 @@ int dso__load(struct dso *dso, struct map *map)if (!runtime_ss && syms_ss) runtime_ss = syms_ss; -if (syms_ss && syms_ss->type ==DSO_BINARY_TYPE__BUILD_ID_CACHE ) -if (dso__build_id_is_kmod (dso, name,PATH_MAX )) - kmod = true; -if (syms_ss) ret =dso__load_sym (dso, map, syms_ss, runtime_ss, kmod);else
tools/perf/util/unwind-libdw.c +9 -1
@@ -39,6 +39,14 @@ static int __report_module(struct addr_location *al, u64 ip,return 0 ; mod =dwfl_addrmodule (ui->dwfl, ip); +if (mod) { +Dwarf_Addr s; + +dwfl_module_info (mod,NULL , &s,NULL ,NULL ,NULL ,NULL ,NULL ); +if (s != al->map->start) + mod =0 ; + } +if (!mod) mod = dwfl_report_elf(ui->dwfl, dso->short_name, dso->long_name, -1, al->map->start,
@@ -224,7 +232,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, err =dwfl_getthread_frames (ui->dwfl, thread->tid, frame_callback, ui); -if (err && !ui->max_stack) +if (err && ui->max_stack != max_stack) err =0 ;/*