diff options
| -rw-r--r-- | arch/x86/kernel/kprobes/core.c | 54 | ||||
| -rw-r--r-- | arch/x86/kernel/kprobes/opt.c | 2 | ||||
| -rw-r--r-- | tools/perf/bench/mem-memcpy.c | 4 | ||||
| -rw-r--r-- | tools/perf/config/Makefile.arch | 4 | ||||
| -rw-r--r-- | tools/perf/config/feature-checks/Makefile | 2 | ||||
| -rw-r--r-- | tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c | 3 | ||||
| -rw-r--r-- | tools/perf/util/cloexec.c | 18 | ||||
| -rw-r--r-- | tools/perf/util/evlist.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/symbol-elf.c | 5 |
9 files changed, 72 insertions, 22 deletions
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 6a1146ea4d4d..4e3d5a9621fe 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c | |||
| @@ -223,27 +223,48 @@ static unsigned long | |||
| 223 | __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) | 223 | __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) |
| 224 | { | 224 | { |
| 225 | struct kprobe *kp; | 225 | struct kprobe *kp; |
| 226 | unsigned long faddr; | ||
| 226 | 227 | ||
| 227 | kp = get_kprobe((void *)addr); | 228 | kp = get_kprobe((void *)addr); |
| 228 | /* There is no probe, return original address */ | 229 | faddr = ftrace_location(addr); |
| 229 | if (!kp) | 230 | /* |
| 231 | * Addresses inside the ftrace location are refused by | ||
| 232 | * arch_check_ftrace_location(). Something went terribly wrong | ||
| 233 | * if such an address is checked here. | ||
| 234 | */ | ||
| 235 | if (WARN_ON(faddr && faddr != addr)) | ||
| 236 | return 0UL; | ||
| 237 | /* | ||
| 238 | * Use the current code if it is not modified by Kprobe | ||
| 239 | * and it cannot be modified by ftrace. | ||
| 240 | */ | ||
| 241 | if (!kp && !faddr) | ||
| 230 | return addr; | 242 | return addr; |
| 231 | 243 | ||
| 232 | /* | 244 | /* |
| 233 | * Basically, kp->ainsn.insn has an original instruction. | 245 | * Basically, kp->ainsn.insn has an original instruction. |
| 234 | * However, RIP-relative instruction can not do single-stepping | 246 | * However, RIP-relative instruction can not do single-stepping |
| 235 | * at different place, __copy_instruction() tweaks the displacement of | 247 | * at different place, __copy_instruction() tweaks the displacement of |
| 236 | * that instruction. In that case, we can't recover the instruction | 248 | * that instruction. In that case, we can't recover the instruction |
| 237 | * from the kp->ainsn.insn. | 249 | * from the kp->ainsn.insn. |
| 238 | * | 250 | * |
| 239 | * On the other hand, kp->opcode has a copy of the first byte of | 251 | * On the other hand, in case on normal Kprobe, kp->opcode has a copy |
| 240 | * the probed instruction, which is overwritten by int3. And | 252 | * of the first byte of the probed instruction, which is overwritten |
| 241 | * the instruction at kp->addr is not modified by kprobes except | 253 | * by int3. And the instruction at kp->addr is not modified by kprobes |
| 242 | * for the first byte, we can recover the original instruction | 254 | * except for the first byte, we can recover the original instruction |
| 243 | * from it and kp->opcode. | 255 | * from it and kp->opcode. |
| 256 | * | ||
| 257 | * In case of Kprobes using ftrace, we do not have a copy of | ||
| 258 | * the original instruction. In fact, the ftrace location might | ||
| 259 | * be modified at anytime and even could be in an inconsistent state. | ||
| 260 | * Fortunately, we know that the original code is the ideal 5-byte | ||
| 261 | * long NOP. | ||
| 244 | */ | 262 | */ |
| 245 | memcpy(buf, kp->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | 263 | memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); |
| 246 | buf[0] = kp->opcode; | 264 | if (faddr) |
| 265 | memcpy(buf, ideal_nops[NOP_ATOMIC5], 5); | ||
| 266 | else | ||
| 267 | buf[0] = kp->opcode; | ||
| 247 | return (unsigned long)buf; | 268 | return (unsigned long)buf; |
| 248 | } | 269 | } |
| 249 | 270 | ||
| @@ -251,6 +272,7 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr) | |||
| 251 | * Recover the probed instruction at addr for further analysis. | 272 | * Recover the probed instruction at addr for further analysis. |
| 252 | * Caller must lock kprobes by kprobe_mutex, or disable preemption | 273 | * Caller must lock kprobes by kprobe_mutex, or disable preemption |
| 253 | * for preventing to release referencing kprobes. | 274 | * for preventing to release referencing kprobes. |
| 275 | * Returns zero if the instruction can not get recovered. | ||
| 254 | */ | 276 | */ |
| 255 | unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr) | 277 | unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr) |
| 256 | { | 278 | { |
| @@ -285,6 +307,8 @@ static int can_probe(unsigned long paddr) | |||
| 285 | * normally used, we just go through if there is no kprobe. | 307 | * normally used, we just go through if there is no kprobe. |
| 286 | */ | 308 | */ |
| 287 | __addr = recover_probed_instruction(buf, addr); | 309 | __addr = recover_probed_instruction(buf, addr); |
| 310 | if (!__addr) | ||
| 311 | return 0; | ||
| 288 | kernel_insn_init(&insn, (void *)__addr, MAX_INSN_SIZE); | 312 | kernel_insn_init(&insn, (void *)__addr, MAX_INSN_SIZE); |
| 289 | insn_get_length(&insn); | 313 | insn_get_length(&insn); |
| 290 | 314 | ||
| @@ -333,6 +357,8 @@ int __copy_instruction(u8 *dest, u8 *src) | |||
| 333 | unsigned long recovered_insn = | 357 | unsigned long recovered_insn = |
| 334 | recover_probed_instruction(buf, (unsigned long)src); | 358 | recover_probed_instruction(buf, (unsigned long)src); |
| 335 | 359 | ||
| 360 | if (!recovered_insn) | ||
| 361 | return 0; | ||
| 336 | kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); | 362 | kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); |
| 337 | insn_get_length(&insn); | 363 | insn_get_length(&insn); |
| 338 | /* Another subsystem puts a breakpoint, failed to recover */ | 364 | /* Another subsystem puts a breakpoint, failed to recover */ |
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 0dd8d089c315..7b3b9d15c47a 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c | |||
| @@ -259,6 +259,8 @@ static int can_optimize(unsigned long paddr) | |||
| 259 | */ | 259 | */ |
| 260 | return 0; | 260 | return 0; |
| 261 | recovered_insn = recover_probed_instruction(buf, addr); | 261 | recovered_insn = recover_probed_instruction(buf, addr); |
| 262 | if (!recovered_insn) | ||
| 263 | return 0; | ||
| 262 | kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); | 264 | kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE); |
| 263 | insn_get_length(&insn); | 265 | insn_get_length(&insn); |
| 264 | /* Another subsystem puts a breakpoint */ | 266 | /* Another subsystem puts a breakpoint */ |
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c index 6c14afe8c1b1..db1d3a29d97f 100644 --- a/tools/perf/bench/mem-memcpy.c +++ b/tools/perf/bench/mem-memcpy.c | |||
| @@ -289,7 +289,7 @@ static u64 do_memcpy_cycle(const struct routine *r, size_t len, bool prefault) | |||
| 289 | memcpy_t fn = r->fn.memcpy; | 289 | memcpy_t fn = r->fn.memcpy; |
| 290 | int i; | 290 | int i; |
| 291 | 291 | ||
| 292 | memcpy_alloc_mem(&src, &dst, len); | 292 | memcpy_alloc_mem(&dst, &src, len); |
| 293 | 293 | ||
| 294 | if (prefault) | 294 | if (prefault) |
| 295 | fn(dst, src, len); | 295 | fn(dst, src, len); |
| @@ -312,7 +312,7 @@ static double do_memcpy_gettimeofday(const struct routine *r, size_t len, | |||
| 312 | void *src = NULL, *dst = NULL; | 312 | void *src = NULL, *dst = NULL; |
| 313 | int i; | 313 | int i; |
| 314 | 314 | ||
| 315 | memcpy_alloc_mem(&src, &dst, len); | 315 | memcpy_alloc_mem(&dst, &src, len); |
| 316 | 316 | ||
| 317 | if (prefault) | 317 | if (prefault) |
| 318 | fn(dst, src, len); | 318 | fn(dst, src, len); |
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch index ff95a68741d1..ac8721ffa6c8 100644 --- a/tools/perf/config/Makefile.arch +++ b/tools/perf/config/Makefile.arch | |||
| @@ -21,6 +21,10 @@ ifeq ($(RAW_ARCH),x86_64) | |||
| 21 | endif | 21 | endif |
| 22 | endif | 22 | endif |
| 23 | 23 | ||
| 24 | ifeq ($(RAW_ARCH),sparc64) | ||
| 25 | ARCH ?= sparc | ||
| 26 | endif | ||
| 27 | |||
| 24 | ARCH ?= $(RAW_ARCH) | 28 | ARCH ?= $(RAW_ARCH) |
| 25 | 29 | ||
| 26 | LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) | 30 | LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) |
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile index 42ac05aaf8ac..b32ff3372514 100644 --- a/tools/perf/config/feature-checks/Makefile +++ b/tools/perf/config/feature-checks/Makefile | |||
| @@ -49,7 +49,7 @@ test-hello.bin: | |||
| 49 | $(BUILD) | 49 | $(BUILD) |
| 50 | 50 | ||
| 51 | test-pthread-attr-setaffinity-np.bin: | 51 | test-pthread-attr-setaffinity-np.bin: |
| 52 | $(BUILD) -Werror -lpthread | 52 | $(BUILD) -D_GNU_SOURCE -Werror -lpthread |
| 53 | 53 | ||
| 54 | test-stackprotector-all.bin: | 54 | test-stackprotector-all.bin: |
| 55 | $(BUILD) -Werror -fstack-protector-all | 55 | $(BUILD) -Werror -fstack-protector-all |
diff --git a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c b/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c index 0a0d3ecb4e8a..2b81b72eca23 100644 --- a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c +++ b/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c | |||
| @@ -5,10 +5,11 @@ int main(void) | |||
| 5 | { | 5 | { |
| 6 | int ret = 0; | 6 | int ret = 0; |
| 7 | pthread_attr_t thread_attr; | 7 | pthread_attr_t thread_attr; |
| 8 | cpu_set_t cs; | ||
| 8 | 9 | ||
| 9 | pthread_attr_init(&thread_attr); | 10 | pthread_attr_init(&thread_attr); |
| 10 | /* don't care abt exact args, just the API itself in libpthread */ | 11 | /* don't care abt exact args, just the API itself in libpthread */ |
| 11 | ret = pthread_attr_setaffinity_np(&thread_attr, 0, NULL); | 12 | ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cs), &cs); |
| 12 | 13 | ||
| 13 | return ret; | 14 | return ret; |
| 14 | } | 15 | } |
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c index 47b78b3f0325..6da965bdbc2c 100644 --- a/tools/perf/util/cloexec.c +++ b/tools/perf/util/cloexec.c | |||
| @@ -25,6 +25,10 @@ static int perf_flag_probe(void) | |||
| 25 | if (cpu < 0) | 25 | if (cpu < 0) |
| 26 | cpu = 0; | 26 | cpu = 0; |
| 27 | 27 | ||
| 28 | /* | ||
| 29 | * Using -1 for the pid is a workaround to avoid gratuitous jump label | ||
| 30 | * changes. | ||
| 31 | */ | ||
| 28 | while (1) { | 32 | while (1) { |
| 29 | /* check cloexec flag */ | 33 | /* check cloexec flag */ |
| 30 | fd = sys_perf_event_open(&attr, pid, cpu, -1, | 34 | fd = sys_perf_event_open(&attr, pid, cpu, -1, |
| @@ -47,16 +51,24 @@ static int perf_flag_probe(void) | |||
| 47 | err, strerror_r(err, sbuf, sizeof(sbuf))); | 51 | err, strerror_r(err, sbuf, sizeof(sbuf))); |
| 48 | 52 | ||
| 49 | /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ | 53 | /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ |
| 50 | fd = sys_perf_event_open(&attr, pid, cpu, -1, 0); | 54 | while (1) { |
| 55 | fd = sys_perf_event_open(&attr, pid, cpu, -1, 0); | ||
| 56 | if (fd < 0 && pid == -1 && errno == EACCES) { | ||
| 57 | pid = 0; | ||
| 58 | continue; | ||
| 59 | } | ||
| 60 | break; | ||
| 61 | } | ||
| 51 | err = errno; | 62 | err = errno; |
| 52 | 63 | ||
| 64 | if (fd >= 0) | ||
| 65 | close(fd); | ||
| 66 | |||
| 53 | if (WARN_ONCE(fd < 0 && err != EBUSY, | 67 | if (WARN_ONCE(fd < 0 && err != EBUSY, |
| 54 | "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", | 68 | "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", |
| 55 | err, strerror_r(err, sbuf, sizeof(sbuf)))) | 69 | err, strerror_r(err, sbuf, sizeof(sbuf)))) |
| 56 | return -1; | 70 | return -1; |
| 57 | 71 | ||
| 58 | close(fd); | ||
| 59 | |||
| 60 | return 0; | 72 | return 0; |
| 61 | } | 73 | } |
| 62 | 74 | ||
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index c94a9e03ecf1..e99a67632831 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
| @@ -28,7 +28,7 @@ struct perf_mmap { | |||
| 28 | int mask; | 28 | int mask; |
| 29 | int refcnt; | 29 | int refcnt; |
| 30 | unsigned int prev; | 30 | unsigned int prev; |
| 31 | char event_copy[PERF_SAMPLE_MAX_SIZE]; | 31 | char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); |
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | struct perf_evlist { | 34 | struct perf_evlist { |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index b24f9d8727a8..33b7a2aef713 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
| @@ -11,6 +11,11 @@ | |||
| 11 | #include <symbol/kallsyms.h> | 11 | #include <symbol/kallsyms.h> |
| 12 | #include "debug.h" | 12 | #include "debug.h" |
| 13 | 13 | ||
| 14 | #ifndef EM_AARCH64 | ||
| 15 | #define EM_AARCH64 183 /* ARM 64 bit */ | ||
| 16 | #endif | ||
| 17 | |||
| 18 | |||
| 14 | #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT | 19 | #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT |
| 15 | extern char *cplus_demangle(const char *, int); | 20 | extern char *cplus_demangle(const char *, int); |
| 16 | 21 | ||
