diff options
Diffstat (limited to 'tools/perf')
| -rw-r--r-- | tools/perf/Makefile | 36 | ||||
| -rw-r--r-- | tools/perf/arch/powerpc/Makefile | 4 | ||||
| -rw-r--r-- | tools/perf/arch/powerpc/util/dwarf-regs.c | 88 | ||||
| -rw-r--r-- | tools/perf/arch/x86/Makefile | 4 | ||||
| -rw-r--r-- | tools/perf/arch/x86/util/dwarf-regs.c | 75 | ||||
| -rw-r--r-- | tools/perf/util/include/dwarf-regs.h | 8 | ||||
| -rw-r--r-- | tools/perf/util/probe-finder.c | 55 |
7 files changed, 211 insertions, 59 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 3cb3449a9645..e8bf2e1ab497 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
| @@ -173,6 +173,20 @@ uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') | |||
| 173 | uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not') | 173 | uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not') |
| 174 | uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not') | 174 | uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not') |
| 175 | 175 | ||
| 176 | ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | ||
| 177 | -e s/arm.*/arm/ -e s/sa110/arm/ \ | ||
| 178 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ | ||
| 179 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ | ||
| 180 | -e s/sh[234].*/sh/ ) | ||
| 181 | |||
| 182 | # Additional ARCH settings for x86 | ||
| 183 | ifeq ($(ARCH),i386) | ||
| 184 | ARCH := x86 | ||
| 185 | endif | ||
| 186 | ifeq ($(ARCH),x86_64) | ||
| 187 | ARCH := x86 | ||
| 188 | endif | ||
| 189 | |||
| 176 | # CFLAGS and LDFLAGS are for the users to override from the command line. | 190 | # CFLAGS and LDFLAGS are for the users to override from the command line. |
| 177 | 191 | ||
| 178 | # | 192 | # |
| @@ -285,7 +299,7 @@ endif | |||
| 285 | # Those must not be GNU-specific; they are shared with perl/ which may | 299 | # Those must not be GNU-specific; they are shared with perl/ which may |
| 286 | # be built by a different compiler. (Note that this is an artifact now | 300 | # be built by a different compiler. (Note that this is an artifact now |
| 287 | # but it still might be nice to keep that distinction.) | 301 | # but it still might be nice to keep that distinction.) |
| 288 | BASIC_CFLAGS = -Iutil/include | 302 | BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include |
| 289 | BASIC_LDFLAGS = | 303 | BASIC_LDFLAGS = |
| 290 | 304 | ||
| 291 | # Guard against environment variables | 305 | # Guard against environment variables |
| @@ -367,6 +381,7 @@ LIB_H += util/include/asm/byteorder.h | |||
| 367 | LIB_H += util/include/asm/swab.h | 381 | LIB_H += util/include/asm/swab.h |
| 368 | LIB_H += util/include/asm/system.h | 382 | LIB_H += util/include/asm/system.h |
| 369 | LIB_H += util/include/asm/uaccess.h | 383 | LIB_H += util/include/asm/uaccess.h |
| 384 | LIB_H += util/include/dwarf-regs.h | ||
| 370 | LIB_H += perf.h | 385 | LIB_H += perf.h |
| 371 | LIB_H += util/cache.h | 386 | LIB_H += util/cache.h |
| 372 | LIB_H += util/callchain.h | 387 | LIB_H += util/callchain.h |
| @@ -487,6 +502,15 @@ PERFLIBS = $(LIB_FILE) | |||
| 487 | -include config.mak.autogen | 502 | -include config.mak.autogen |
| 488 | -include config.mak | 503 | -include config.mak |
| 489 | 504 | ||
| 505 | ifndef NO_DWARF | ||
| 506 | ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) | ||
| 507 | msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev); | ||
| 508 | NO_DWARF := 1 | ||
| 509 | endif # Dwarf support | ||
| 510 | endif # NO_DWARF | ||
| 511 | |||
| 512 | -include arch/$(ARCH)/Makefile | ||
| 513 | |||
| 490 | ifeq ($(uname_S),Darwin) | 514 | ifeq ($(uname_S),Darwin) |
| 491 | ifndef NO_FINK | 515 | ifndef NO_FINK |
| 492 | ifeq ($(shell test -d /sw/lib && echo y),y) | 516 | ifeq ($(shell test -d /sw/lib && echo y),y) |
| @@ -519,15 +543,15 @@ else | |||
| 519 | msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]); | 543 | msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]); |
| 520 | endif | 544 | endif |
| 521 | 545 | ||
| 522 | ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) | ||
| 523 | msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev); | ||
| 524 | else | ||
| 525 | ifndef NO_DWARF | 546 | ifndef NO_DWARF |
| 547 | ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) | ||
| 548 | msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); | ||
| 549 | else | ||
| 526 | BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT | 550 | BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT |
| 527 | EXTLIBS += -lelf -ldw | 551 | EXTLIBS += -lelf -ldw |
| 528 | LIB_OBJS += $(OUTPUT)util/probe-finder.o | 552 | LIB_OBJS += $(OUTPUT)util/probe-finder.o |
| 529 | endif | 553 | endif # PERF_HAVE_DWARF_REGS |
| 530 | endif | 554 | endif # NO_DWARF |
| 531 | 555 | ||
| 532 | ifneq ($(shell sh -c "(echo '\#include <newt.h>'; echo 'int main(void) { newtInit(); newtCls(); return newtFinished(); }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -lnewt -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) | 556 | ifneq ($(shell sh -c "(echo '\#include <newt.h>'; echo 'int main(void) { newtInit(); newtCls(); return newtFinished(); }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -lnewt -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) |
| 533 | msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); | 557 | msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); |
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile new file mode 100644 index 000000000000..15130b50dfe3 --- /dev/null +++ b/tools/perf/arch/powerpc/Makefile | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | ifndef NO_DWARF | ||
| 2 | PERF_HAVE_DWARF_REGS := 1 | ||
| 3 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o | ||
| 4 | endif | ||
diff --git a/tools/perf/arch/powerpc/util/dwarf-regs.c b/tools/perf/arch/powerpc/util/dwarf-regs.c new file mode 100644 index 000000000000..48ae0c5e3f73 --- /dev/null +++ b/tools/perf/arch/powerpc/util/dwarf-regs.c | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | /* | ||
| 2 | * Mapping of DWARF debug register numbers into register names. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Ian Munsie, IBM Corporation. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <libio.h> | ||
| 13 | #include <dwarf-regs.h> | ||
| 14 | |||
| 15 | |||
| 16 | struct pt_regs_dwarfnum { | ||
| 17 | const char *name; | ||
| 18 | unsigned int dwarfnum; | ||
| 19 | }; | ||
| 20 | |||
| 21 | #define STR(s) #s | ||
| 22 | #define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num} | ||
| 23 | #define GPR_DWARFNUM_NAME(num) \ | ||
| 24 | {.name = STR(%gpr##num), .dwarfnum = num} | ||
| 25 | #define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0} | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Reference: | ||
| 29 | * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html | ||
| 30 | */ | ||
| 31 | static const struct pt_regs_dwarfnum regdwarfnum_table[] = { | ||
| 32 | GPR_DWARFNUM_NAME(0), | ||
| 33 | GPR_DWARFNUM_NAME(1), | ||
| 34 | GPR_DWARFNUM_NAME(2), | ||
| 35 | GPR_DWARFNUM_NAME(3), | ||
| 36 | GPR_DWARFNUM_NAME(4), | ||
| 37 | GPR_DWARFNUM_NAME(5), | ||
| 38 | GPR_DWARFNUM_NAME(6), | ||
| 39 | GPR_DWARFNUM_NAME(7), | ||
| 40 | GPR_DWARFNUM_NAME(8), | ||
| 41 | GPR_DWARFNUM_NAME(9), | ||
| 42 | GPR_DWARFNUM_NAME(10), | ||
| 43 | GPR_DWARFNUM_NAME(11), | ||
| 44 | GPR_DWARFNUM_NAME(12), | ||
| 45 | GPR_DWARFNUM_NAME(13), | ||
| 46 | GPR_DWARFNUM_NAME(14), | ||
| 47 | GPR_DWARFNUM_NAME(15), | ||
| 48 | GPR_DWARFNUM_NAME(16), | ||
| 49 | GPR_DWARFNUM_NAME(17), | ||
| 50 | GPR_DWARFNUM_NAME(18), | ||
| 51 | GPR_DWARFNUM_NAME(19), | ||
| 52 | GPR_DWARFNUM_NAME(20), | ||
| 53 | GPR_DWARFNUM_NAME(21), | ||
| 54 | GPR_DWARFNUM_NAME(22), | ||
| 55 | GPR_DWARFNUM_NAME(23), | ||
| 56 | GPR_DWARFNUM_NAME(24), | ||
| 57 | GPR_DWARFNUM_NAME(25), | ||
| 58 | GPR_DWARFNUM_NAME(26), | ||
| 59 | GPR_DWARFNUM_NAME(27), | ||
| 60 | GPR_DWARFNUM_NAME(28), | ||
| 61 | GPR_DWARFNUM_NAME(29), | ||
| 62 | GPR_DWARFNUM_NAME(30), | ||
| 63 | GPR_DWARFNUM_NAME(31), | ||
| 64 | REG_DWARFNUM_NAME("%msr", 66), | ||
| 65 | REG_DWARFNUM_NAME("%ctr", 109), | ||
| 66 | REG_DWARFNUM_NAME("%link", 108), | ||
| 67 | REG_DWARFNUM_NAME("%xer", 101), | ||
| 68 | REG_DWARFNUM_NAME("%dar", 119), | ||
| 69 | REG_DWARFNUM_NAME("%dsisr", 118), | ||
| 70 | REG_DWARFNUM_END, | ||
| 71 | }; | ||
| 72 | |||
| 73 | /** | ||
| 74 | * get_arch_regstr() - lookup register name from it's DWARF register number | ||
| 75 | * @n: the DWARF register number | ||
| 76 | * | ||
| 77 | * get_arch_regstr() returns the name of the register in struct | ||
| 78 | * regdwarfnum_table from it's DWARF register number. If the register is not | ||
| 79 | * found in the table, this returns NULL; | ||
| 80 | */ | ||
| 81 | const char *get_arch_regstr(unsigned int n) | ||
| 82 | { | ||
| 83 | const struct pt_regs_dwarfnum *roff; | ||
| 84 | for (roff = regdwarfnum_table; roff->name != NULL; roff++) | ||
| 85 | if (roff->dwarfnum == n) | ||
| 86 | return roff->name; | ||
| 87 | return NULL; | ||
| 88 | } | ||
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile new file mode 100644 index 000000000000..15130b50dfe3 --- /dev/null +++ b/tools/perf/arch/x86/Makefile | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | ifndef NO_DWARF | ||
| 2 | PERF_HAVE_DWARF_REGS := 1 | ||
| 3 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o | ||
| 4 | endif | ||
diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c new file mode 100644 index 000000000000..a794d3081928 --- /dev/null +++ b/tools/perf/arch/x86/util/dwarf-regs.c | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | /* | ||
| 2 | * dwarf-regs.c : Mapping of DWARF debug register numbers into register names. | ||
| 3 | * Extracted from probe-finder.c | ||
| 4 | * | ||
| 5 | * Written by Masami Hiramatsu <mhiramat@redhat.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <libio.h> | ||
| 24 | #include <dwarf-regs.h> | ||
| 25 | |||
| 26 | /* | ||
| 27 | * Generic dwarf analysis helpers | ||
| 28 | */ | ||
| 29 | |||
| 30 | #define X86_32_MAX_REGS 8 | ||
| 31 | const char *x86_32_regs_table[X86_32_MAX_REGS] = { | ||
| 32 | "%ax", | ||
| 33 | "%cx", | ||
| 34 | "%dx", | ||
| 35 | "%bx", | ||
| 36 | "$stack", /* Stack address instead of %sp */ | ||
| 37 | "%bp", | ||
| 38 | "%si", | ||
| 39 | "%di", | ||
| 40 | }; | ||
| 41 | |||
| 42 | #define X86_64_MAX_REGS 16 | ||
| 43 | const char *x86_64_regs_table[X86_64_MAX_REGS] = { | ||
| 44 | "%ax", | ||
| 45 | "%dx", | ||
| 46 | "%cx", | ||
| 47 | "%bx", | ||
| 48 | "%si", | ||
| 49 | "%di", | ||
| 50 | "%bp", | ||
| 51 | "%sp", | ||
| 52 | "%r8", | ||
| 53 | "%r9", | ||
| 54 | "%r10", | ||
| 55 | "%r11", | ||
| 56 | "%r12", | ||
| 57 | "%r13", | ||
| 58 | "%r14", | ||
| 59 | "%r15", | ||
| 60 | }; | ||
| 61 | |||
| 62 | /* TODO: switching by dwarf address size */ | ||
| 63 | #ifdef __x86_64__ | ||
| 64 | #define ARCH_MAX_REGS X86_64_MAX_REGS | ||
| 65 | #define arch_regs_table x86_64_regs_table | ||
| 66 | #else | ||
| 67 | #define ARCH_MAX_REGS X86_32_MAX_REGS | ||
| 68 | #define arch_regs_table x86_32_regs_table | ||
| 69 | #endif | ||
| 70 | |||
| 71 | /* Return architecture dependent register string (for kprobe-tracer) */ | ||
| 72 | const char *get_arch_regstr(unsigned int n) | ||
| 73 | { | ||
| 74 | return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL; | ||
| 75 | } | ||
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h new file mode 100644 index 000000000000..cf6727e99c44 --- /dev/null +++ b/tools/perf/util/include/dwarf-regs.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #ifndef _PERF_DWARF_REGS_H_ | ||
| 2 | #define _PERF_DWARF_REGS_H_ | ||
| 3 | |||
| 4 | #ifdef DWARF_SUPPORT | ||
| 5 | const char *get_arch_regstr(unsigned int n); | ||
| 6 | #endif | ||
| 7 | |||
| 8 | #endif | ||
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 3e7977560be5..e7ee52fd0e09 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <string.h> | 31 | #include <string.h> |
| 32 | #include <stdarg.h> | 32 | #include <stdarg.h> |
| 33 | #include <ctype.h> | 33 | #include <ctype.h> |
| 34 | #include <dwarf-regs.h> | ||
| 34 | 35 | ||
| 35 | #include "string.h" | 36 | #include "string.h" |
| 36 | #include "event.h" | 37 | #include "event.h" |
| @@ -38,61 +39,9 @@ | |||
| 38 | #include "util.h" | 39 | #include "util.h" |
| 39 | #include "probe-finder.h" | 40 | #include "probe-finder.h" |
| 40 | 41 | ||
| 41 | |||
| 42 | /* | ||
| 43 | * Generic dwarf analysis helpers | ||
| 44 | */ | ||
| 45 | |||
| 46 | #define X86_32_MAX_REGS 8 | ||
| 47 | const char *x86_32_regs_table[X86_32_MAX_REGS] = { | ||
| 48 | "%ax", | ||
| 49 | "%cx", | ||
| 50 | "%dx", | ||
| 51 | "%bx", | ||
| 52 | "$stack", /* Stack address instead of %sp */ | ||
| 53 | "%bp", | ||
| 54 | "%si", | ||
| 55 | "%di", | ||
| 56 | }; | ||
| 57 | |||
| 58 | #define X86_64_MAX_REGS 16 | ||
| 59 | const char *x86_64_regs_table[X86_64_MAX_REGS] = { | ||
| 60 | "%ax", | ||
| 61 | "%dx", | ||
| 62 | "%cx", | ||
| 63 | "%bx", | ||
| 64 | "%si", | ||
| 65 | "%di", | ||
| 66 | "%bp", | ||
| 67 | "%sp", | ||
| 68 | "%r8", | ||
| 69 | "%r9", | ||
| 70 | "%r10", | ||
| 71 | "%r11", | ||
| 72 | "%r12", | ||
| 73 | "%r13", | ||
| 74 | "%r14", | ||
| 75 | "%r15", | ||
| 76 | }; | ||
| 77 | |||
| 78 | /* TODO: switching by dwarf address size */ | ||
| 79 | #ifdef __x86_64__ | ||
| 80 | #define ARCH_MAX_REGS X86_64_MAX_REGS | ||
| 81 | #define arch_regs_table x86_64_regs_table | ||
| 82 | #else | ||
| 83 | #define ARCH_MAX_REGS X86_32_MAX_REGS | ||
| 84 | #define arch_regs_table x86_32_regs_table | ||
| 85 | #endif | ||
| 86 | |||
| 87 | /* Kprobe tracer basic type is up to u64 */ | 42 | /* Kprobe tracer basic type is up to u64 */ |
| 88 | #define MAX_BASIC_TYPE_BITS 64 | 43 | #define MAX_BASIC_TYPE_BITS 64 |
| 89 | 44 | ||
| 90 | /* Return architecture dependent register string (for kprobe-tracer) */ | ||
| 91 | static const char *get_arch_regstr(unsigned int n) | ||
| 92 | { | ||
| 93 | return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL; | ||
| 94 | } | ||
| 95 | |||
| 96 | /* | 45 | /* |
| 97 | * Compare the tail of two strings. | 46 | * Compare the tail of two strings. |
| 98 | * Return 0 if whole of either string is same as another's tail part. | 47 | * Return 0 if whole of either string is same as another's tail part. |
| @@ -447,7 +396,7 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf) | |||
| 447 | 396 | ||
| 448 | regs = get_arch_regstr(regn); | 397 | regs = get_arch_regstr(regn); |
| 449 | if (!regs) { | 398 | if (!regs) { |
| 450 | pr_warning("%u exceeds max register number.\n", regn); | 399 | pr_warning("Mapping for DWARF register number %u missing on this architecture.", regn); |
| 451 | return -ERANGE; | 400 | return -ERANGE; |
| 452 | } | 401 | } |
| 453 | 402 | ||
