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)
Unified · Split
| @@ -2867,16 +2867,11 @@ static int perf_event_modify_breakpoint(struct perf_event *bp, · 2866 unmodified lines | ||
| 2867 | 2867 | _perf_event_disable(bp); |
| 2868 | 2868 | |
| 2869 | 2869 | err = modify_user_hw_breakpoint_check(bp, attr, true); |
| 2870 | − if (err) { | |
| 2871 | − if (!bp->attr.disabled) | |
| 2872 | − _perf_event_enable(bp); | |
| 2873 | 2870 | |
| 2874 | − return err; | |
| 2875 | − } | |
| 2876 | − | |
| 2877 | − if (!attr->disabled) | |
| 2871 | + if (!bp->attr.disabled) | |
| 2878 | 2872 | _perf_event_enable(bp); |
| 2879 | − return 0; | |
| 2873 | + | |
| 2874 | + return err; | |
| 2880 | 2875 | } |
| 2881 | 2876 | |
| 2882 | 2877 | static int perf_event_modify_attr(struct perf_event *event, |
| @@ -509,6 +509,8 @@ modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *a · 508 unmodified lines | ||
| 509 | 509 | */ |
| 510 | 510 | int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) |
| 511 | 511 | { |
| 512 | + int err; | |
| 513 | + | |
| 512 | 514 | /* |
| 513 | 515 | * modify_user_hw_breakpoint can be invoked with IRQs disabled and hence it |
| 514 | 516 | * 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 | ||
| 520 | 522 | else |
| 521 | 523 | perf_event_disable(bp); |
| 522 | 524 | |
| 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); | |
| 525 | 526 | |
| 526 | − if (err) | |
| 527 | − return err; | |
| 527 | + if (!bp->attr.disabled) | |
| 528 | 528 | perf_event_enable(bp); |
| 529 | − bp->attr.disabled = 0; | |
| 530 | − } | |
| 531 | − return 0; | |
| 529 | + | |
| 530 | + return err; | |
| 532 | 531 | } |
| 533 | 532 | EXPORT_SYMBOL_GPL(modify_user_hw_breakpoint); |
| 534 | 533 | |
| @@ -777,14 +777,12 @@ endif · 776 unmodified lines | ||
| 777 | 777 | $(call QUIET_INSTALL, libexec) \ |
| 778 | 778 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' |
| 779 | 779 | 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' | |
| 788 | 786 | endif |
| 789 | 787 | $(call QUIET_INSTALL, perf-archive) \ |
| 790 | 788 | $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' |
| @@ -11,7 +11,8 @@ PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | out := $(OUTPUT)arch/arm64/include/generated/asm |
| 13 | 13 | 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 | |
| 15 | 16 | sysprf := $(srctree)/tools/perf/arch/arm64/entry/syscalls/ |
| 16 | 17 | systbl := $(sysprf)/mksyscalltbl |
| 17 | 18 | |
| @@ -19,7 +20,7 @@ systbl := $(sysprf)/mksyscalltbl · 1 unmodified line | ||
| 19 | 20 | _dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)') |
| 20 | 21 | |
| 21 | 22 | $(header): $(sysdef) $(systbl) |
| 22 | − $(Q)$(SHELL) '$(systbl)' '$(CC)' '$(HOSTCC)' $(sysdef) > $@ | |
| 23 | + $(Q)$(SHELL) '$(systbl)' '$(CC)' '$(HOSTCC)' $(incpath) $(sysdef) > $@ | |
| 23 | 24 | |
| 24 | 25 | clean:: |
| 25 | 26 | $(call QUIET_CLEAN, arm64) $(RM) $(header) |
| @@ -11,7 +11,8 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | gcc=$1 |
| 13 | 13 | hostcc=$2 |
| 14 | −input=$3 | |
| 14 | +incpath=$3 | |
| 15 | +input=$4 | |
| 15 | 16 | |
| 16 | 17 | if ! test -r $input; then |
| 17 | 18 | echo "Could not read input file" >&2 |
| @@ -28,7 +29,6 @@ create_table_from_c() · 10 unmodified lines | ||
| 28 | 29 | |
| 29 | 30 | cat <<-_EoHEADER |
| 30 | 31 | #include <stdio.h> |
| 31 | − #define __ARCH_WANT_RENAMEAT | |
| 32 | 32 | #include "$input" |
| 33 | 33 | int main(int argc, char *argv[]) |
| 34 | 34 | { |
| @@ -42,7 +42,7 @@ create_table_from_c() · 7 unmodified lines | ||
| 42 | 42 | printf "%s\n" " printf(\"#define SYSCALLTBL_ARM64_MAX_ID %d\\n\", __NR_$last_sc);" |
| 43 | 43 | printf "}\n" |
| 44 | 44 | |
| 45 | − } | $hostcc -o $create_table_exe -x c - | |
| 45 | + } | $hostcc -I $incpath/include/uapi -o $create_table_exe -x c - | |
| 46 | 46 | |
| 47 | 47 | $create_table_exe |
| 48 | 48 | |
| @@ -22,15 +22,16 @@ bool elf__needs_adjust_symbols(GElf_Ehdr ehdr) · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | #endif |
| 24 | 24 | |
| 25 | −#if !defined(_CALL_ELF) || _CALL_ELF != 2 | |
| 26 | 25 | int arch__choose_best_symbol(struct symbol *syma, |
| 27 | 26 | struct symbol *symb __maybe_unused) |
| 28 | 27 | { |
| 29 | 28 | char *sym = syma->name; |
| 30 | 29 | |
| 30 | +#if !defined(_CALL_ELF) || _CALL_ELF != 2 | |
| 31 | 31 | /* Skip over any initial dot */ |
| 32 | 32 | if (*sym == '.') |
| 33 | 33 | sym++; |
| 34 | +#endif | |
| 34 | 35 | |
| 35 | 36 | /* Avoid "SyS" kernel syscall aliases */ |
| 36 | 37 | if (strlen(sym) >= 3 && !strncmp(sym, "SyS", 3)) |
| @@ -41,6 +42,7 @@ int arch__choose_best_symbol(struct symbol *syma, · 4 unmodified lines | ||
| 41 | 42 | return SYMBOL_A; |
| 42 | 43 | } |
| 43 | 44 | |
| 45 | +#if !defined(_CALL_ELF) || _CALL_ELF != 2 | |
| 44 | 46 | /* Allow matching against dot variants */ |
| 45 | 47 | int arch__compare_symbol_names(const char *namea, const char *nameb) |
| 46 | 48 | { |
| @@ -9,6 +9,7 @@ struct test; · 8 unmodified lines | ||
| 9 | 9 | int test__rdpmc(struct test *test __maybe_unused, int subtest); |
| 10 | 10 | int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest); |
| 11 | 11 | int test__insn_x86(struct test *test __maybe_unused, int subtest); |
| 12 | +int test__bp_modify(struct test *test, int subtest); | |
| 12 | 13 | |
| 13 | 14 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
| 14 | 15 | struct thread; |
| @@ -5,3 +5,4 @@ libperf-y += arch-tests.o · 4 unmodified lines | ||
| 5 | 5 | libperf-y += rdpmc.o |
| 6 | 6 | libperf-y += perf-time-to-tsc.o |
| 7 | 7 | libperf-$(CONFIG_AUXTRACE) += insn-x86.o |
| 8 | +libperf-$(CONFIG_X86_64) += bp-modify.o | |
| @@ -23,6 +23,12 @@ struct test arch_tests[] = { · 22 unmodified lines | ||
| 23 | 23 | .desc = "x86 instruction decoder - new instructions", |
| 24 | 24 | .func = test__insn_x86, |
| 25 | 25 | }, |
| 26 | +#endif | |
| 27 | +#if defined(__x86_64__) | |
| 28 | + { | |
| 29 | + .desc = "x86 bp modify", | |
| 30 | + .func = test__bp_modify, | |
| 31 | + }, | |
| 26 | 32 | #endif |
| 27 | 33 | { |
| 28 | 34 | .func = NULL, |
| @@ -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 | +} | |
| @@ -246,8 +246,14 @@ find_target: · 245 unmodified lines | ||
| 246 | 246 | |
| 247 | 247 | indirect_call: |
| 248 | 248 | 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 | + } | |
| 251 | 257 | goto find_target; |
| 252 | 258 | } |
| 253 | 259 | |
| @@ -276,7 +282,19 @@ bool ins__is_call(const struct ins *ins) · 22 unmodified lines | ||
| 276 | 282 | return ins->ops == &call_ops || ins->ops == &s390_call_ops; |
| 277 | 283 | } |
| 278 | 284 | |
| 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) | |
| 280 | 298 | { |
| 281 | 299 | struct map *map = ms->map; |
| 282 | 300 | 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 | ||
| 285 | 303 | }; |
| 286 | 304 | const char *c = strchr(ops->raw, ','); |
| 287 | 305 | u64 start, end; |
| 306 | + | |
| 307 | + ops->raw_comment = strchr(ops->raw, arch->objdump.comment_char); | |
| 308 | + c = validate_comma(c, ops); | |
| 309 | + | |
| 288 | 310 | /* |
| 289 | 311 | * Examples of lines to parse for the _cpp_lex_token@@Base |
| 290 | 312 | * function: |
| @@ -304,6 +326,7 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op · 13 unmodified lines | ||
| 304 | 326 | ops->target.addr = strtoull(c, NULL, 16); |
| 305 | 327 | if (!ops->target.addr) { |
| 306 | 328 | c = strchr(c, ','); |
| 329 | + c = validate_comma(c, ops); | |
| 307 | 330 | if (c++ != NULL) |
| 308 | 331 | ops->target.addr = strtoull(c, NULL, 16); |
| 309 | 332 | } |
| @@ -361,9 +384,12 @@ static int jump__scnprintf(struct ins *ins, char *bf, size_t size, · 51 unmodified lines | ||
| 361 | 384 | return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name); |
| 362 | 385 | |
| 363 | 386 | c = strchr(ops->raw, ','); |
| 387 | + c = validate_comma(c, ops); | |
| 388 | + | |
| 364 | 389 | if (c != NULL) { |
| 365 | 390 | const char *c2 = strchr(c + 1, ','); |
| 366 | 391 | |
| 392 | + c2 = validate_comma(c2, ops); | |
| 367 | 393 | /* check for 3-op insn */ |
| 368 | 394 | if (c2 != NULL) |
| 369 | 395 | c = c2; |
| @@ -22,6 +22,7 @@ struct ins { · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | struct ins_operands { |
| 24 | 24 | char *raw; |
| 25 | + char *raw_comment; | |
| 25 | 26 | struct { |
| 26 | 27 | char *raw; |
| 27 | 28 | char *name; |
| @@ -251,8 +251,9 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) · 250 unmodified lines | ||
| 251 | 251 | { |
| 252 | 252 | struct perf_evsel *evsel = zalloc(perf_evsel__object.size); |
| 253 | 253 | |
| 254 | − if (evsel != NULL) | |
| 255 | − perf_evsel__init(evsel, attr, idx); | |
| 254 | + if (!evsel) | |
| 255 | + return NULL; | |
| 256 | + perf_evsel__init(evsel, attr, idx); | |
| 256 | 257 | |
| 257 | 258 | if (perf_evsel__is_bpf_output(evsel)) { |
| 258 | 259 | evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | |
| @@ -377,7 +377,7 @@ out: · 376 unmodified lines | ||
| 377 | 377 | |
| 378 | 378 | static int record_saved_cmdline(void) |
| 379 | 379 | { |
| 380 | − unsigned int size; | |
| 380 | + unsigned long long size; | |
| 381 | 381 | char *path; |
| 382 | 382 | struct stat st; |
| 383 | 383 | int ret, err = 0; |
| @@ -164,16 +164,15 @@ void parse_ftrace_printk(struct tep_handle *pevent, · 163 unmodified lines | ||
| 164 | 164 | void parse_saved_cmdline(struct tep_handle *pevent, |
| 165 | 165 | char *file, unsigned int size __maybe_unused) |
| 166 | 166 | { |
| 167 | − char *comm; | |
| 167 | + char comm[17]; /* Max comm length in the kernel is 16. */ | |
| 168 | 168 | char *line; |
| 169 | 169 | char *next = NULL; |
| 170 | 170 | int pid; |
| 171 | 171 | |
| 172 | 172 | line = strtok_r(file, "\n", &next); |
| 173 | 173 | 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); | |
| 177 | 176 | line = strtok_r(NULL, "\n", &next); |
| 178 | 177 | } |
| 179 | 178 | } |