Skip to content

Commit

Permalink
perf: Move arch specific code into separate arch directory
Browse files Browse the repository at this point in the history
The perf userspace tool included some architecture specific code to map
registers from the DWARF register number into the names used by the regs
and stack access API.

This moves the architecture specific code out into a separate
arch/x86 directory along with the infrastructure required to use it.

Signed-off-by: Ian Munsie <imunsie@au.ibm.com>
Acked-by: Masami Hiramatsu <mhiramat@redhat.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
  • Loading branch information
Ian Munsie authored and Paul Mackerras committed Apr 22, 2010
1 parent 6eca8cc commit cd932c5
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 59 deletions.
36 changes: 30 additions & 6 deletions tools/perf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,20 @@ uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')

ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ -e s/parisc64/parisc/ \
-e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-e s/sh[234].*/sh/ )

# Additional ARCH settings for x86
ifeq ($(ARCH),i386)
ARCH := x86
endif
ifeq ($(ARCH),x86_64)
ARCH := x86
endif

# CFLAGS and LDFLAGS are for the users to override from the command line.

#
Expand Down Expand Up @@ -285,7 +299,7 @@ endif
# Those must not be GNU-specific; they are shared with perl/ which may
# be built by a different compiler. (Note that this is an artifact now
# but it still might be nice to keep that distinction.)
BASIC_CFLAGS = -Iutil/include
BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include
BASIC_LDFLAGS =

# Guard against environment variables
Expand Down Expand Up @@ -367,6 +381,7 @@ LIB_H += util/include/asm/byteorder.h
LIB_H += util/include/asm/swab.h
LIB_H += util/include/asm/system.h
LIB_H += util/include/asm/uaccess.h
LIB_H += util/include/dwarf-regs.h
LIB_H += perf.h
LIB_H += util/cache.h
LIB_H += util/callchain.h
Expand Down Expand Up @@ -487,6 +502,15 @@ PERFLIBS = $(LIB_FILE)
-include config.mak.autogen
-include config.mak

ifndef NO_DWARF
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)
msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev);
NO_DWARF := 1
endif # Dwarf support
endif # NO_DWARF

-include arch/$(ARCH)/Makefile

ifeq ($(uname_S),Darwin)
ifndef NO_FINK
ifeq ($(shell test -d /sw/lib && echo y),y)
Expand Down Expand Up @@ -519,15 +543,15 @@ else
msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
endif

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)
msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev);
else
ifndef NO_DWARF
ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
else
BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT
EXTLIBS += -lelf -ldw
LIB_OBJS += $(OUTPUT)util/probe-finder.o
endif
endif
endif # PERF_HAVE_DWARF_REGS
endif # NO_DWARF

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)
msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev);
Expand Down
4 changes: 4 additions & 0 deletions tools/perf/arch/x86/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
endif
75 changes: 75 additions & 0 deletions tools/perf/arch/x86/util/dwarf-regs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* dwarf-regs.c : Mapping of DWARF debug register numbers into register names.
* Extracted from probe-finder.c
*
* Written by Masami Hiramatsu <mhiramat@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/

#include <libio.h>
#include <dwarf-regs.h>

/*
* Generic dwarf analysis helpers
*/

#define X86_32_MAX_REGS 8
const char *x86_32_regs_table[X86_32_MAX_REGS] = {
"%ax",
"%cx",
"%dx",
"%bx",
"$stack", /* Stack address instead of %sp */
"%bp",
"%si",
"%di",
};

#define X86_64_MAX_REGS 16
const char *x86_64_regs_table[X86_64_MAX_REGS] = {
"%ax",
"%dx",
"%cx",
"%bx",
"%si",
"%di",
"%bp",
"%sp",
"%r8",
"%r9",
"%r10",
"%r11",
"%r12",
"%r13",
"%r14",
"%r15",
};

/* TODO: switching by dwarf address size */
#ifdef __x86_64__
#define ARCH_MAX_REGS X86_64_MAX_REGS
#define arch_regs_table x86_64_regs_table
#else
#define ARCH_MAX_REGS X86_32_MAX_REGS
#define arch_regs_table x86_32_regs_table
#endif

/* Return architecture dependent register string (for kprobe-tracer) */
const char *get_arch_regstr(unsigned int n)
{
return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
}
8 changes: 8 additions & 0 deletions tools/perf/util/include/dwarf-regs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _PERF_DWARF_REGS_H_
#define _PERF_DWARF_REGS_H_

#ifdef DWARF_SUPPORT
const char *get_arch_regstr(unsigned int n);
#endif

#endif
55 changes: 2 additions & 53 deletions tools/perf/util/probe-finder.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,68 +31,17 @@
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <dwarf-regs.h>

#include "string.h"
#include "event.h"
#include "debug.h"
#include "util.h"
#include "probe-finder.h"


/*
* Generic dwarf analysis helpers
*/

#define X86_32_MAX_REGS 8
const char *x86_32_regs_table[X86_32_MAX_REGS] = {
"%ax",
"%cx",
"%dx",
"%bx",
"$stack", /* Stack address instead of %sp */
"%bp",
"%si",
"%di",
};

#define X86_64_MAX_REGS 16
const char *x86_64_regs_table[X86_64_MAX_REGS] = {
"%ax",
"%dx",
"%cx",
"%bx",
"%si",
"%di",
"%bp",
"%sp",
"%r8",
"%r9",
"%r10",
"%r11",
"%r12",
"%r13",
"%r14",
"%r15",
};

/* TODO: switching by dwarf address size */
#ifdef __x86_64__
#define ARCH_MAX_REGS X86_64_MAX_REGS
#define arch_regs_table x86_64_regs_table
#else
#define ARCH_MAX_REGS X86_32_MAX_REGS
#define arch_regs_table x86_32_regs_table
#endif

/* Kprobe tracer basic type is up to u64 */
#define MAX_BASIC_TYPE_BITS 64

/* Return architecture dependent register string (for kprobe-tracer) */
static const char *get_arch_regstr(unsigned int n)
{
return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
}

/*
* Compare the tail of two strings.
* Return 0 if whole of either string is same as another's tail part.
Expand Down Expand Up @@ -447,7 +396,7 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf)

regs = get_arch_regstr(regn);
if (!regs) {
pr_warning("%u exceeds max register number.\n", regn);
pr_warning("Mapping for DWARF register number %u missing on this architecture.", regn);
return -ERANGE;
}

Expand Down

0 comments on commit cd932c5

Please sign in to comment.