diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-03-01 14:56:13 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-03-01 14:56:13 -0500 |
| commit | d7b48fec3520da075a4093d3aa37ce4daff7510b (patch) | |
| tree | e67cf00d4c3712e41b2e97e45507de0467b5c44d | |
| parent | 2ea51b884b07ac7fbb49eb91860eb05c13161ad2 (diff) | |
| parent | 021f5f12f2ab44874193c68fb19eea154493f83a (diff) | |
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar:
"Two kprobes fixes and a handful of tooling fixes"
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf tools: Make sparc64 arch point to sparc
perf symbols: Define EM_AARCH64 for older OSes
perf top: Fix SIGBUS on sparc64
perf tools: Fix probing for PERF_FLAG_FD_CLOEXEC flag
perf tools: Fix pthread_attr_setaffinity_np build error
perf tools: Define _GNU_SOURCE on pthread_attr_setaffinity_np feature check
perf bench: Fix order of arguments to memcpy_alloc_mem
kprobes/x86: Check for invalid ftrace location in __recover_probed_insn()
kprobes/x86: Use 5-byte NOP when the code might be modified by ftrace
| -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 | { | ||
