History

Merge tag 'perf-urgent-for-mingo-4.19-20180903' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent

Pull perf/urgent fixes from Arnaldo Carvalho de Melo: Kernel: - Modify breakpoint fixes (Jiri Olsa) perf annotate: - Fix parsing aarch64 branch instructions after objdump update (Kim Phillips) - Fix parsing indirect calls in 'perf annotate' (Martin Liška) perf probe: - Ignore SyS symbols irrespective of endianness on PowerPC (Sandipan Das) perf trace: - Fix include path for asm-generic/unistd.h on arm64 (Kim Phillips) Core libraries: - Fix potential null pointer dereference in perf_evsel__new_idx() (Hisao Tanabe) - Use fixed size string for comms instead of scanf("%m"), that is not present in the bionic libc and leads to a crash (Chris Phlipot) - Fix bad memory access in trace info on 32-bit systems, we were reading 8 bytes from a 4-byte long variable when saving the command line in the perf.data file. (Chris Phlipot) Build system: - Streamline bpf examples and headers installation, clarifying some install messages. (Arnaldo Carvalho de Melo)

Ingo Molnar committed 8 years ago

Commit fa943512 parents 9a56827 4e67b2a15 files · +282 −39Browse files

Unified · Split

15 files
  1. kernel/events/core.c +3 −8
  2. kernel/events/hw_breakpoint.c +6 −7
  3. tools/perf/Makefile.perf +6 −8
  4. tools/perf/arch/arm64/Makefile +3 −2
  5. tools/perf/arch/arm64/entry/syscalls/mksyscalltbl +3 −3
  6. tools/perf/arch/powerpc/util/sym-handling.c +3 −1
  7. tools/perf/arch/x86/include/arch-tests.h +1 −0
  8. tools/perf/arch/x86/tests/Build +1 −0
  9. tools/perf/arch/x86/tests/arch-tests.c +6 −0
  10. tools/perf/arch/x86/tests/bp-modify.c +213 −0
  11. tools/perf/util/annotate.c +29 −3
  12. tools/perf/util/annotate.h +1 −0
  13. tools/perf/util/evsel.c +3 −2
  14. tools/perf/util/trace-event-info.c +1 −1
  15. tools/perf/util/trace-event-parse.c +3 −4
kernel/events/core.c+3−8
@@ -2867,16 +2867,11 @@ static int perf_event_modify_breakpoint(struct perf_event *bp, · 2866 unmodified lines
28672867 _perf_event_disable(bp);
28682868
28692869 err = modify_user_hw_breakpoint_check(bp, attr, true);
2870− if (err) {
2871− if (!bp->attr.disabled)
2872− _perf_event_enable(bp);
28732870
2874− return err;
2875− }
2876−
2877− if (!attr->disabled)
2871+ if (!bp->attr.disabled)
28782872 _perf_event_enable(bp);
2879− return 0;
2873+
2874+ return err;
28802875 }
28812876
28822877 static int perf_event_modify_attr(struct perf_event *event,
kernel/events/hw_breakpoint.c+6−7
@@ -509,6 +509,8 @@ modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *a · 508 unmodified lines
509509 */
510510 int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr)
511511 {
512+ int err;
513+
512514 /*
513515 * modify_user_hw_breakpoint can be invoked with IRQs disabled and hence it
514516 * will not be possible to raise IPIs that invoke __perf_event_disable.
@@ -520,15 +522,12 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att · 5 unmodified lines
520522 else
521523 perf_event_disable(bp);
522524
523− if (!attr->disabled) {
524− int err = modify_user_hw_breakpoint_check(bp, attr, false);
525+ err = modify_user_hw_breakpoint_check(bp, attr, false);
525526
526− if (err)
527− return err;
527+ if (!bp->attr.disabled)
528528 perf_event_enable(bp);
529− bp->attr.disabled = 0;
530− }
531− return 0;
529+
530+ return err;
532531 }
533532 EXPORT_SYMBOL_GPL(modify_user_hw_breakpoint);
534533
tools/perf/Makefile.perf+6−8
@@ -777,14 +777,12 @@ endif · 776 unmodified lines
777777 $(call QUIET_INSTALL, libexec) \
778778 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
779779 ifndef NO_LIBBPF
780− $(call QUIET_INSTALL, lib) \
781− $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'
782− $(call QUIET_INSTALL, include/bpf) \
783− $(INSTALL) include/bpf/*.h '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'
784− $(call QUIET_INSTALL, lib) \
785− $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'
786− $(call QUIET_INSTALL, examples/bpf) \
787− $(INSTALL) examples/bpf/*.c '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'
780+ $(call QUIET_INSTALL, bpf-headers) \
781+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \
782+ $(INSTALL) include/bpf/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'
783+ $(call QUIET_INSTALL, bpf-examples) \
784+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'; \
785+ $(INSTALL) examples/bpf/*.c -t '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'
788786 endif
789787 $(call QUIET_INSTALL, perf-archive) \
790788 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
tools/perf/arch/arm64/Makefile+3−2
@@ -11,7 +11,8 @@ PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 · 10 unmodified lines
1111
1212 out := $(OUTPUT)arch/arm64/include/generated/asm
1313 header := $(out)/syscalls.c
14−sysdef := $(srctree)/tools/include/uapi/asm-generic/unistd.h
14+incpath := $(srctree)/tools
15+sysdef := $(srctree)/tools/arch/arm64/include/uapi/asm/unistd.h
1516 sysprf := $(srctree)/tools/perf/arch/arm64/entry/syscalls/
1617 systbl := $(sysprf)/mksyscalltbl
1718
@@ -19,7 +20,7 @@ systbl := $(sysprf)/mksyscalltbl · 1 unmodified line
1920 _dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
2021
2122 $(header): $(sysdef) $(systbl)
22− $(Q)$(SHELL) '$(systbl)' '$(CC)' '$(HOSTCC)' $(sysdef) > $@
23+ $(Q)$(SHELL) '$(systbl)' '$(CC)' '$(HOSTCC)' $(incpath) $(sysdef) > $@
2324
2425 clean::
2526 $(call QUIET_CLEAN, arm64) $(RM) $(header)
tools/perf/arch/arm64/entry/syscalls/mksyscalltbl+3−3
@@ -11,7 +11,8 @@ · 10 unmodified lines
1111
1212 gcc=$1
1313 hostcc=$2
14−input=$3
14+incpath=$3
15+input=$4
1516
1617 if ! test -r $input; then
1718 echo "Could not read input file" >&2
@@ -28,7 +29,6 @@ create_table_from_c() · 10 unmodified lines
2829
2930 cat <<-_EoHEADER
3031 #include <stdio.h>
31− #define __ARCH_WANT_RENAMEAT
3232 #include "$input"
3333 int main(int argc, char *argv[])
3434 {
@@ -42,7 +42,7 @@ create_table_from_c() · 7 unmodified lines
4242 printf "%s\n" " printf(\"#define SYSCALLTBL_ARM64_MAX_ID %d\\n\", __NR_$last_sc);"
4343 printf "}\n"
4444
45− } | $hostcc -o $create_table_exe -x c -
45+ } | $hostcc -I $incpath/include/uapi -o $create_table_exe -x c -
4646
4747 $create_table_exe
4848
tools/perf/arch/powerpc/util/sym-handling.c+3−1
@@ -22,15 +22,16 @@ bool elf__needs_adjust_symbols(GElf_Ehdr ehdr) · 21 unmodified lines
2222
2323 #endif
2424
25−#if !defined(_CALL_ELF) || _CALL_ELF != 2
2625 int arch__choose_best_symbol(struct symbol *syma,
2726 struct symbol *symb __maybe_unused)
2827 {
2928 char *sym = syma->name;
3029
30+#if !defined(_CALL_ELF) || _CALL_ELF != 2
3131 /* Skip over any initial dot */
3232 if (*sym == '.')
3333 sym++;
34+#endif
3435
3536 /* Avoid "SyS" kernel syscall aliases */
3637 if (strlen(sym) >= 3 && !strncmp(sym, "SyS", 3))
@@ -41,6 +42,7 @@ int arch__choose_best_symbol(struct symbol *syma, · 4 unmodified lines
4142 return SYMBOL_A;
4243 }
4344
45+#if !defined(_CALL_ELF) || _CALL_ELF != 2
4446 /* Allow matching against dot variants */
4547 int arch__compare_symbol_names(const char *namea, const char *nameb)
4648 {
tools/perf/arch/x86/include/arch-tests.h+1−0
@@ -9,6 +9,7 @@ struct test; · 8 unmodified lines
99 int test__rdpmc(struct test *test __maybe_unused, int subtest);
1010 int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest);
1111 int test__insn_x86(struct test *test __maybe_unused, int subtest);
12+int test__bp_modify(struct test *test, int subtest);
1213
1314 #ifdef HAVE_DWARF_UNWIND_SUPPORT
1415 struct thread;
tools/perf/arch/x86/tests/Build+1−0
@@ -5,3 +5,4 @@ libperf-y += arch-tests.o · 4 unmodified lines
55 libperf-y += rdpmc.o
66 libperf-y += perf-time-to-tsc.o
77 libperf-$(CONFIG_AUXTRACE) += insn-x86.o
8+libperf-$(CONFIG_X86_64) += bp-modify.o
tools/perf/arch/x86/tests/arch-tests.c+6−0
@@ -23,6 +23,12 @@ struct test arch_tests[] = { · 22 unmodified lines
2323 .desc = "x86 instruction decoder - new instructions",
2424 .func = test__insn_x86,
2525 },
26+#endif
27+#if defined(__x86_64__)
28+ {
29+ .desc = "x86 bp modify",
30+ .func = test__bp_modify,
31+ },
2632 #endif
2733 {
2834 .func = NULL,
tools/perf/arch/x86/tests/bp-modify.c+213−0
@@ -0,0 +1,213 @@
1+// SPDX-License-Identifier: GPL-2.0
2+#include <linux/compiler.h>
3+#include <sys/types.h>
4+#include <sys/wait.h>
5+#include <sys/user.h>
6+#include <syscall.h>
7+#include <unistd.h>
8+#include <stdio.h>
9+#include <stdlib.h>
10+#include <sys/ptrace.h>
11+#include <asm/ptrace.h>
12+#include <errno.h>
13+#include "debug.h"
14+#include "tests/tests.h"
15+#include "arch-tests.h"
16+
17+static noinline int bp_1(void)
18+{
19+ pr_debug("in %s\n", __func__);
20+ return 0;
21+}
22+
23+static noinline int bp_2(void)
24+{
25+ pr_debug("in %s\n", __func__);
26+ return 0;
27+}
28+
29+static int spawn_child(void)
30+{
31+ int child = fork();
32+
33+ if (child == 0) {
34+ /*
35+ * The child sets itself for as tracee and
36+ * waits in signal for parent to trace it,
37+ * then it calls bp_1 and quits.
38+ */
39+ int err = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
40+
41+ if (err) {
42+ pr_debug("failed to PTRACE_TRACEME\n");
43+ exit(1);
44+ }
45+
46+ raise(SIGCONT);
47+ bp_1();
48+ exit(0);
49+ }
50+
51+ return child;
52+}
53+
54+/*
55+ * This tests creates HW breakpoint, tries to
56+ * change it and checks it was properly changed.
57+ */
58+static int bp_modify1(void)
59+{
60+ pid_t child;
61+ int status;
62+ unsigned long rip = 0, dr7 = 1;
63+
64+ child = spawn_child();
65+
66+ waitpid(child, &status, 0);
67+ if (WIFEXITED(status)) {
68+ pr_debug("tracee exited prematurely 1\n");
69+ return TEST_FAIL;
70+ }
71+
72+ /*
73+ * The parent does following steps:
74+ * - creates a new breakpoint (id 0) for bp_2 function
75+ * - changes that breakponit to bp_1 function
76+ * - waits for the breakpoint to hit and checks
77+ * it has proper rip of bp_1 function
78+ * - detaches the child
79+ */
80+ if (ptrace(PTRACE_POKEUSER, child,
81+ offsetof(struct user, u_debugreg[0]), bp_2)) {
82+ pr_debug("failed to set breakpoint, 1st time: %s\n",
83+ strerror(errno));
84+ goto out;
85+ }
86+
87+ if (ptrace(PTRACE_POKEUSER, child,
88+ offsetof(struct user, u_debugreg[0]), bp_1)) {
89+ pr_debug("failed to set breakpoint, 2nd time: %s\n",
90+ strerror(errno));
91+ goto out;
92+ }
93+
94+ if (ptrace(PTRACE_POKEUSER, child,
95+ offsetof(struct user, u_debugreg[7]), dr7)) {
96+ pr_debug("failed to set dr7: %s\n", strerror(errno));
97+ goto out;
98+ }
99+
100+ if (ptrace(PTRACE_CONT, child, NULL, NULL)) {
101+ pr_debug("failed to PTRACE_CONT: %s\n", strerror(errno));
102+ goto out;
103+ }
104+
105+ waitpid(child, &status, 0);
106+ if (WIFEXITED(status)) {
107+ pr_debug("tracee exited prematurely 2\n");
108+ return TEST_FAIL;
109+ }
110+
111+ rip = ptrace(PTRACE_PEEKUSER, child,
112+ offsetof(struct user_regs_struct, rip), NULL);
113+ if (rip == (unsigned long) -1) {
114+ pr_debug("failed to PTRACE_PEEKUSER: %s\n",
115+ strerror(errno));
116+ goto out;
117+ }
118+
119+ pr_debug("rip %lx, bp_1 %p\n", rip, bp_1);
120+
121+out:
122+ if (ptrace(PTRACE_DETACH, child, NULL, NULL)) {
123+ pr_debug("failed to PTRACE_DETACH: %s", strerror(errno));
124+ return TEST_FAIL;
125+ }
126+
127+ return rip == (unsigned long) bp_1 ? TEST_OK : TEST_FAIL;
128+}
129+
130+/*
131+ * This tests creates HW breakpoint, tries to
132+ * change it to bogus value and checks the original
133+ * breakpoint is hit.
134+ */
135+static int bp_modify2(void)
136+{
137+ pid_t child;
138+ int status;
139+ unsigned long rip = 0, dr7 = 1;
140+
141+ child = spawn_child();
142+
143+ waitpid(child, &status, 0);
144+ if (WIFEXITED(status)) {
145+ pr_debug("tracee exited prematurely 1\n");
146+ return TEST_FAIL;
147+ }
148+
149+ /*
150+ * The parent does following steps:
151+ * - creates a new breakpoint (id 0) for bp_1 function
152+ * - tries to change that breakpoint to (-1) address
153+ * - waits for the breakpoint to hit and checks
154+ * it has proper rip of bp_1 function
155+ * - detaches the child
156+ */
157+ if (ptrace(PTRACE_POKEUSER, child,
158+ offsetof(struct user, u_debugreg[0]), bp_1)) {
159+ pr_debug("failed to set breakpoint: %s\n",
160+ strerror(errno));
161+ goto out;
162+ }
163+
164+ if (ptrace(PTRACE_POKEUSER, child,
165+ offsetof(struct user, u_debugreg[7]), dr7)) {
166+ pr_debug("failed to set dr7: %s\n", strerror(errno));
167+ goto out;
168+ }
169+
170+ if (!ptrace(PTRACE_POKEUSER, child,
171+ offsetof(struct user, u_debugreg[0]), (unsigned long) (-1))) {
172+ pr_debug("failed, breakpoint set to bogus address\n");
173+ goto out;
174+ }
175+
176+ if (ptrace(PTRACE_CONT, child, NULL, NULL)) {
177+ pr_debug("failed to PTRACE_CONT: %s\n", strerror(errno));
178+ goto out;
179+ }
180+
181+ waitpid(child, &status, 0);
182+ if (WIFEXITED(status)) {
183+ pr_debug("tracee exited prematurely 2\n");
184+ return TEST_FAIL;
185+ }
186+
187+ rip = ptrace(PTRACE_PEEKUSER, child,
188+ offsetof(struct user_regs_struct, rip), NULL);
189+ if (rip == (unsigned long) -1) {
190+ pr_debug("failed to PTRACE_PEEKUSER: %s\n",
191+ strerror(errno));
192+ goto out;
193+ }
194+
195+ pr_debug("rip %lx, bp_1 %p\n", rip, bp_1);
196+
197+out:
198+ if (ptrace(PTRACE_DETACH, child, NULL, NULL)) {
199+ pr_debug("failed to PTRACE_DETACH: %s", strerror(errno));
200+ return TEST_FAIL;
201+ }
202+
203+ return rip == (unsigned long) bp_1 ? TEST_OK : TEST_FAIL;
204+}
205+
206+int test__bp_modify(struct test *test __maybe_unused,
207+ int subtest __maybe_unused)
208+{
209+ TEST_ASSERT_VAL("modify test 1 failed\n", !bp_modify1());
210+ TEST_ASSERT_VAL("modify test 2 failed\n", !bp_modify2());
211+
212+ return 0;
213+}
tools/perf/util/annotate.c+29−3
@@ -246,8 +246,14 @@ find_target: · 245 unmodified lines
246246
247247 indirect_call:
248248 tok = strchr(endptr, '*');
249− if (tok != NULL)
250− ops->target.addr = strtoull(tok + 1, NULL, 16);
249+ if (tok != NULL) {
250+ endptr++;
251+
252+ /* Indirect call can use a non-rip register and offset: callq *0x8(%rbx).
253+ * Do not parse such instruction. */
254+ if (strstr(endptr, "(%r") == NULL)
255+ ops->target.addr = strtoull(endptr, NULL, 16);
256+ }
251257 goto find_target;
252258 }
253259
@@ -276,7 +282,19 @@ bool ins__is_call(const struct ins *ins) · 22 unmodified lines
276282 return ins->ops == &call_ops || ins->ops == &s390_call_ops;
277283 }
278284
279−static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms)
285+/*
286+ * Prevents from matching commas in the comment section, e.g.:
287+ * ffff200008446e70: b.cs ffff2000084470f4 <generic_exec_single+0x314> // b.hs, b.nlast
288+ */
289+static inline const char *validate_comma(const char *c, struct ins_operands *ops)
290+{
291+ if (ops->raw_comment && c > ops->raw_comment)
292+ return NULL;
293+
294+ return c;
295+}
296+
297+static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
280298 {
281299 struct map *map = ms->map;
282300 struct symbol *sym = ms->sym;
@@ -285,6 +303,10 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op · 2 unmodified lines
285303 };
286304 const char *c = strchr(ops->raw, ',');
287305 u64 start, end;
306+
307+ ops->raw_comment = strchr(ops->raw, arch->objdump.comment_char);
308+ c = validate_comma(c, ops);
309+
288310 /*
289311 * Examples of lines to parse for the _cpp_lex_token@@Base
290312 * function:
@@ -304,6 +326,7 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op · 13 unmodified lines
304326 ops->target.addr = strtoull(c, NULL, 16);
305327 if (!ops->target.addr) {
306328 c = strchr(c, ',');
329+ c = validate_comma(c, ops);
307330 if (c++ != NULL)
308331 ops->target.addr = strtoull(c, NULL, 16);
309332 }
@@ -361,9 +384,12 @@ static int jump__scnprintf(struct ins *ins, char *bf, size_t size, · 51 unmodified lines
361384 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
362385
363386 c = strchr(ops->raw, ',');
387+ c = validate_comma(c, ops);
388+
364389 if (c != NULL) {
365390 const char *c2 = strchr(c + 1, ',');
366391
392+ c2 = validate_comma(c2, ops);
367393 /* check for 3-op insn */
368394 if (c2 != NULL)
369395 c = c2;
tools/perf/util/annotate.h+1−0
@@ -22,6 +22,7 @@ struct ins { · 21 unmodified lines
2222
2323 struct ins_operands {
2424 char *raw;
25+ char *raw_comment;
2526 struct {
2627 char *raw;
2728 char *name;
tools/perf/util/evsel.c+3−2
@@ -251,8 +251,9 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) · 250 unmodified lines
251251 {
252252 struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
253253
254− if (evsel != NULL)
255− perf_evsel__init(evsel, attr, idx);
254+ if (!evsel)
255+ return NULL;
256+ perf_evsel__init(evsel, attr, idx);
256257
257258 if (perf_evsel__is_bpf_output(evsel)) {
258259 evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
tools/perf/util/trace-event-info.c+1−1
@@ -377,7 +377,7 @@ out: · 376 unmodified lines
377377
378378 static int record_saved_cmdline(void)
379379 {
380− unsigned int size;
380+ unsigned long long size;
381381 char *path;
382382 struct stat st;
383383 int ret, err = 0;
tools/perf/util/trace-event-parse.c+3−4
@@ -164,16 +164,15 @@ void parse_ftrace_printk(struct tep_handle *pevent, · 163 unmodified lines
164164 void parse_saved_cmdline(struct tep_handle *pevent,
165165 char *file, unsigned int size __maybe_unused)
166166 {
167− char *comm;
167+ char comm[17]; /* Max comm length in the kernel is 16. */
168168 char *line;
169169 char *next = NULL;
170170 int pid;
171171
172172 line = strtok_r(file, "\n", &next);
173173 while (line) {
174− sscanf(line, "%d %ms", &pid, &comm);
175− tep_register_comm(pevent, comm, pid);
176− free(comm);
174+ if (sscanf(line, "%d %16s", &pid, comm) == 2)
175+ tep_register_comm(pevent, comm, pid);
177176 line = strtok_r(NULL, "\n", &next);
178177 }
179178 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t