Skip to content

Commit fa94351

Browse files
author
Ingo Molnar
committed
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) Signed-off-by: Arnaldo Carvalho de Melo <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
2 parents 9a56827 + 4e67b2a commit fa94351

File tree

15 files changed

+282
-39
lines changed

15 files changed

+282
-39
lines changed

kernel/events/core.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2867,16 +2867,11 @@ static int perf_event_modify_breakpoint(struct perf_event *bp,
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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,8 @@ modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *a
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
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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -777,14 +777,12 @@ endif
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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@ PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
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

1819
# Create output directory if not already present
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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
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()
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()
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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,16 @@ bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
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,
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ struct test;
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ libperf-y += arch-tests.o
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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ struct test arch_tests[] = {
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

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

0 commit comments

Comments
 (0)