diff options
| author | Jiri Olsa <jolsa@redhat.com> | 2014-01-07 07:47:29 -0500 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-02-18 07:34:49 -0500 |
| commit | c9b951c4d12f0b2e9a07dd459c554bc05628d092 (patch) | |
| tree | caa1bbe8ea8ccf5490589bf366215218068f0a4f | |
| parent | 9ff125d132001c02d32a193a9423be0690526e11 (diff) | |
perf callchain: Separate perf_reg_value function in perf_regs object
Making perf_reg_value function global (formely reg_value), because it's
going to be used globaly across all code providing the dwarf post unwind
feature.
Changing its prototype to be generic:
-int reg_value(unw_word_t *valp, struct regs_dump *regs, int id)
+int perf_reg_value(u64 *valp, struct regs_dump *regs, int id);
Changing the valp type from libunwind specific 'unw_word_t' to u64.
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Jean Pihet <jean.pihet@linaro.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1389098853-14466-13-git-send-email-jolsa@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | tools/perf/Makefile.perf | 1 | ||||
| -rw-r--r-- | tools/perf/util/perf_regs.c | 19 | ||||
| -rw-r--r-- | tools/perf/util/perf_regs.h | 13 | ||||
| -rw-r--r-- | tools/perf/util/unwind-libunwind.c | 38 |
4 files changed, 45 insertions, 26 deletions
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 9ef6b33bcfe3..f99a392d20be 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
| @@ -538,6 +538,7 @@ ifeq ($(NO_PERF_REGS),0) | |||
| 538 | ifeq ($(ARCH),x86) | 538 | ifeq ($(ARCH),x86) |
| 539 | LIB_H += arch/x86/include/perf_regs.h | 539 | LIB_H += arch/x86/include/perf_regs.h |
| 540 | endif | 540 | endif |
| 541 | LIB_OBJS += $(OUTPUT)util/perf_regs.o | ||
| 541 | endif | 542 | endif |
| 542 | 543 | ||
| 543 | ifndef NO_LIBNUMA | 544 | ifndef NO_LIBNUMA |
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c new file mode 100644 index 000000000000..a3539ef30b15 --- /dev/null +++ b/tools/perf/util/perf_regs.c | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | #include <errno.h> | ||
| 2 | #include "perf_regs.h" | ||
| 3 | |||
| 4 | int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) | ||
| 5 | { | ||
| 6 | int i, idx = 0; | ||
| 7 | u64 mask = regs->mask; | ||
| 8 | |||
| 9 | if (!(mask & (1 << id))) | ||
| 10 | return -EINVAL; | ||
| 11 | |||
| 12 | for (i = 0; i < id; i++) { | ||
| 13 | if (mask & (1 << i)) | ||
| 14 | idx++; | ||
| 15 | } | ||
| 16 | |||
| 17 | *valp = regs->regs[idx]; | ||
| 18 | return 0; | ||
| 19 | } | ||
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h index a3d42cd74919..d6e8b6a8d7f3 100644 --- a/tools/perf/util/perf_regs.h +++ b/tools/perf/util/perf_regs.h | |||
| @@ -1,8 +1,14 @@ | |||
| 1 | #ifndef __PERF_REGS_H | 1 | #ifndef __PERF_REGS_H |
| 2 | #define __PERF_REGS_H | 2 | #define __PERF_REGS_H |
| 3 | 3 | ||
| 4 | #include "types.h" | ||
| 5 | #include "event.h" | ||
| 6 | |||
| 4 | #ifdef HAVE_PERF_REGS_SUPPORT | 7 | #ifdef HAVE_PERF_REGS_SUPPORT |
| 5 | #include <perf_regs.h> | 8 | #include <perf_regs.h> |
| 9 | |||
| 10 | int perf_reg_value(u64 *valp, struct regs_dump *regs, int id); | ||
| 11 | |||
| 6 | #else | 12 | #else |
| 7 | #define PERF_REGS_MASK 0 | 13 | #define PERF_REGS_MASK 0 |
| 8 | 14 | ||
| @@ -10,5 +16,12 @@ static inline const char *perf_reg_name(int id __maybe_unused) | |||
| 10 | { | 16 | { |
| 11 | return NULL; | 17 | return NULL; |
| 12 | } | 18 | } |
| 19 | |||
| 20 | static inline int perf_reg_value(u64 *valp __maybe_unused, | ||
| 21 | struct regs_dump *regs __maybe_unused, | ||
| 22 | int id __maybe_unused) | ||
| 23 | { | ||
| 24 | return 0; | ||
| 25 | } | ||
| 13 | #endif /* HAVE_PERF_REGS_SUPPORT */ | 26 | #endif /* HAVE_PERF_REGS_SUPPORT */ |
| 14 | #endif /* __PERF_REGS_H */ | 27 | #endif /* __PERF_REGS_H */ |
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 79dbfbbeb5ed..bd5768d74f01 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c | |||
| @@ -390,30 +390,13 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, | |||
| 390 | return !(size == sizeof(*data)); | 390 | return !(size == sizeof(*data)); |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id) | ||
| 394 | { | ||
| 395 | int i, idx = 0; | ||
| 396 | u64 mask = regs->mask; | ||
| 397 | |||
| 398 | if (!(mask & (1 << id))) | ||
| 399 | return -EINVAL; | ||
| 400 | |||
| 401 | for (i = 0; i < id; i++) { | ||
| 402 | if (mask & (1 << i)) | ||
| 403 | idx++; | ||
| 404 | } | ||
| 405 | |||
| 406 | *valp = regs->regs[idx]; | ||
| 407 | return 0; | ||
| 408 | } | ||
| 409 | |||
| 410 | static int access_mem(unw_addr_space_t __maybe_unused as, | 393 | static int access_mem(unw_addr_space_t __maybe_unused as, |
| 411 | unw_word_t addr, unw_word_t *valp, | 394 | unw_word_t addr, unw_word_t *valp, |
| 412 | int __write, void *arg) | 395 | int __write, void *arg) |
| 413 | { | 396 | { |
| 414 | struct unwind_info *ui = arg; | 397 | struct unwind_info *ui = arg; |
| 415 | struct stack_dump *stack = &ui->sample->user_stack; | 398 | struct stack_dump *stack = &ui->sample->user_stack; |
| 416 | unw_word_t start, end; | 399 | u64 start, end; |
| 417 | int offset; | 400 | int offset; |
| 418 | int ret; | 401 | int ret; |
| 419 | 402 | ||
| @@ -423,7 +406,7 @@ static int access_mem(unw_addr_space_t __maybe_unused as, | |||
| 423 | return 0; | 406 | return 0; |
| 424 | } | 407 | } |
| 425 | 408 | ||
| 426 | ret = reg_value(&start, &ui->sample->user_regs, PERF_REG_SP); | 409 | ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP); |
| 427 | if (ret) | 410 | if (ret) |
| 428 | return ret; | 411 | return ret; |
| 429 | 412 | ||
| @@ -436,8 +419,9 @@ static int access_mem(unw_addr_space_t __maybe_unused as, | |||
| 436 | if (addr < start || addr + sizeof(unw_word_t) >= end) { | 419 | if (addr < start || addr + sizeof(unw_word_t) >= end) { |
| 437 | ret = access_dso_mem(ui, addr, valp); | 420 | ret = access_dso_mem(ui, addr, valp); |
| 438 | if (ret) { | 421 | if (ret) { |
| 439 | pr_debug("unwind: access_mem %p not inside range %p-%p\n", | 422 | pr_debug("unwind: access_mem %p not inside range" |
| 440 | (void *)addr, (void *)start, (void *)end); | 423 | " 0x%" PRIx64 "-0x%" PRIx64 "\n", |
| 424 | (void *) addr, start, end); | ||
| 441 | *valp = 0; | 425 | *valp = 0; |
| 442 | return ret; | 426 | return ret; |
| 443 | } | 427 | } |
| @@ -446,8 +430,8 @@ static int access_mem(unw_addr_space_t __maybe_unused as, | |||
| 446 | 430 | ||
| 447 | offset = addr - start; | 431 | offset = addr - start; |
| 448 | *valp = *(unw_word_t *)&stack->data[offset]; | 432 | *valp = *(unw_word_t *)&stack->data[offset]; |
| 449 | pr_debug("unwind: access_mem addr %p, val %lx, offset %d\n", | 433 | pr_debug("unwind: access_mem addr %p val %lx, offset %d\n", |
| 450 | (void *)addr, (unsigned long)*valp, offset); | 434 | (void *) addr, (unsigned long)*valp, offset); |
| 451 | return 0; | 435 | return 0; |
| 452 | } | 436 | } |
| 453 | 437 | ||
| @@ -457,6 +441,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as, | |||
| 457 | { | 441 | { |
| 458 | struct unwind_info *ui = arg; | 442 | struct unwind_info *ui = arg; |
| 459 | int id, ret; | 443 | int id, ret; |
| 444 | u64 val; | ||
| 460 | 445 | ||
| 461 | /* Don't support write, I suspect we don't need it. */ | 446 | /* Don't support write, I suspect we don't need it. */ |
| 462 | if (__write) { | 447 | if (__write) { |
| @@ -473,12 +458,13 @@ static int access_reg(unw_addr_space_t __maybe_unused as, | |||
| 473 | if (id < 0) | 458 | if (id < 0) |
| 474 | return -EINVAL; | 459 | return -EINVAL; |
| 475 | 460 | ||
| 476 | ret = reg_value(valp, &ui->sample->user_regs, id); | 461 | ret = perf_reg_value(&val, &ui->sample->user_regs, id); |
| 477 | if (ret) { | 462 | if (ret) { |
| 478 | pr_err("unwind: can't read reg %d\n", regnum); | 463 | pr_err("unwind: can't read reg %d\n", regnum); |
| 479 | return ret; | 464 | return ret; |
| 480 | } | 465 | } |
| 481 | 466 | ||
| 467 | *valp = (unw_word_t) val; | ||
| 482 | pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp); | 468 | pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp); |
| 483 | return 0; | 469 | return 0; |
| 484 | } | 470 | } |
| @@ -572,7 +558,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, | |||
| 572 | struct machine *machine, struct thread *thread, | 558 | struct machine *machine, struct thread *thread, |
| 573 | struct perf_sample *data, int max_stack) | 559 | struct perf_sample *data, int max_stack) |
| 574 | { | 560 | { |
| 575 | unw_word_t ip; | 561 | u64 ip; |
| 576 | struct unwind_info ui = { | 562 | struct unwind_info ui = { |
| 577 | .sample = data, | 563 | .sample = data, |
| 578 | .thread = thread, | 564 | .thread = thread, |
| @@ -583,7 +569,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, | |||
| 583 | if (!data->user_regs.regs) | 569 | if (!data->user_regs.regs) |
| 584 | return -EINVAL; | 570 | return -EINVAL; |
| 585 | 571 | ||
| 586 | ret = reg_value(&ip, &data->user_regs, PERF_REG_IP); | 572 | ret = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP); |
| 587 | if (ret) | 573 | if (ret) |
| 588 | return ret; | 574 | return ret; |
| 589 | 575 | ||
