Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jiri Olsa and committed by
Arnaldo Carvalho de Melo
c9b951c4 9ff125d1

+45 -26
+1
tools/perf/Makefile.perf
··· 538 538 ifeq ($(ARCH),x86) 539 539 LIB_H += arch/x86/include/perf_regs.h 540 540 endif 541 + LIB_OBJS += $(OUTPUT)util/perf_regs.o 541 542 endif 542 543 543 544 ifndef NO_LIBNUMA
+19
tools/perf/util/perf_regs.c
··· 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 + }
+13
tools/perf/util/perf_regs.h
··· 1 1 #ifndef __PERF_REGS_H 2 2 #define __PERF_REGS_H 3 3 4 + #include "types.h" 5 + #include "event.h" 6 + 4 7 #ifdef HAVE_PERF_REGS_SUPPORT 5 8 #include <perf_regs.h> 9 + 10 + int perf_reg_value(u64 *valp, struct regs_dump *regs, int id); 11 + 6 12 #else 7 13 #define PERF_REGS_MASK 0 8 14 9 15 static inline const char *perf_reg_name(int id __maybe_unused) 10 16 { 11 17 return NULL; 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; 12 25 } 13 26 #endif /* HAVE_PERF_REGS_SUPPORT */ 14 27 #endif /* __PERF_REGS_H */
+12 -26
tools/perf/util/unwind-libunwind.c
··· 390 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 393 static int access_mem(unw_addr_space_t __maybe_unused as, 411 394 unw_word_t addr, unw_word_t *valp, 412 395 int __write, void *arg) 413 396 { 414 397 struct unwind_info *ui = arg; 415 398 struct stack_dump *stack = &ui->sample->user_stack; 416 - unw_word_t start, end; 399 + u64 start, end; 417 400 int offset; 418 401 int ret; 419 402 ··· 406 423 return 0; 407 424 } 408 425 409 - ret = reg_value(&start, &ui->sample->user_regs, PERF_REG_SP); 426 + ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP); 410 427 if (ret) 411 428 return ret; 412 429 ··· 419 436 if (addr < start || addr + sizeof(unw_word_t) >= end) { 420 437 ret = access_dso_mem(ui, addr, valp); 421 438 if (ret) { 422 - pr_debug("unwind: access_mem %p not inside range %p-%p\n", 423 - (void *)addr, (void *)start, (void *)end); 439 + pr_debug("unwind: access_mem %p not inside range" 440 + " 0x%" PRIx64 "-0x%" PRIx64 "\n", 441 + (void *) addr, start, end); 424 442 *valp = 0; 425 443 return ret; 426 444 } ··· 430 446 431 447 offset = addr - start; 432 448 *valp = *(unw_word_t *)&stack->data[offset]; 433 - pr_debug("unwind: access_mem addr %p, val %lx, offset %d\n", 434 - (void *)addr, (unsigned long)*valp, offset); 449 + pr_debug("unwind: access_mem addr %p val %lx, offset %d\n", 450 + (void *) addr, (unsigned long)*valp, offset); 435 451 return 0; 436 452 } 437 453 ··· 441 457 { 442 458 struct unwind_info *ui = arg; 443 459 int id, ret; 460 + u64 val; 444 461 445 462 /* Don't support write, I suspect we don't need it. */ 446 463 if (__write) { ··· 458 473 if (id < 0) 459 474 return -EINVAL; 460 475 461 - ret = reg_value(valp, &ui->sample->user_regs, id); 476 + ret = perf_reg_value(&val, &ui->sample->user_regs, id); 462 477 if (ret) { 463 478 pr_err("unwind: can't read reg %d\n", regnum); 464 479 return ret; 465 480 } 466 481 482 + *valp = (unw_word_t) val; 467 483 pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp); 468 484 return 0; 469 485 } ··· 558 572 struct machine *machine, struct thread *thread, 559 573 struct perf_sample *data, int max_stack) 560 574 { 561 - unw_word_t ip; 575 + u64 ip; 562 576 struct unwind_info ui = { 563 577 .sample = data, 564 578 .thread = thread, ··· 569 583 if (!data->user_regs.regs) 570 584 return -EINVAL; 571 585 572 - ret = reg_value(&ip, &data->user_regs, PERF_REG_IP); 586 + ret = perf_reg_value(&ip, &data->user_regs, PERF_REG_IP); 573 587 if (ret) 574 588 return ret; 575 589