perf probe ppc: Fix symbol fixup issues due to ELF type

If using the symbol table, symbol addresses are not being fixed up
properly, resulting in probes being placed at wrong addresses:

  # perf probe do_fork
  Added new event:
    probe:do_fork        (on do_fork)

  You can now use it in all perf tools, such as:

	  perf record -e probe:do_fork -aR sleep 1

  # cat /sys/kernel/debug/tracing/kprobe_events
  p:probe/do_fork _text+635952
  # printf "%x" 635952
  9b430
  # grep do_fork /boot/System.map
  c0000000000ab430 T .do_fork

Fix by checking for ELF type ET_DYN used by ppc64 kernels.

Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Reviewed-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
Link: http://lkml.kernel.org/r/41392bb856ef62d929995e0b61967689b7915207.1430217967.git.naveen.n.rao@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Naveen N. Rao 2015-04-28 17:35:35 +05:30 committed by Arnaldo Carvalho de Melo
parent b64aa553d8
commit d233209833
4 changed files with 30 additions and 2 deletions

View File

@ -1,4 +1,5 @@
libperf-y += header.o libperf-y += header.o
libperf-y += sym-handling.o
libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-$(CONFIG_DWARF) += skip-callchain-idx.o libperf-$(CONFIG_DWARF) += skip-callchain-idx.o

View File

@ -0,0 +1,19 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* Copyright (C) 2015 Naveen N. Rao, IBM Corporation
*/
#include "debug.h"
#include "symbol.h"
#ifdef HAVE_LIBELF_SUPPORT
bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
{
return ehdr.e_type == ET_EXEC ||
ehdr.e_type == ET_REL ||
ehdr.e_type == ET_DYN;
}
#endif

View File

@ -630,6 +630,11 @@ void symsrc__destroy(struct symsrc *ss)
close(ss->fd); close(ss->fd);
} }
bool __weak elf__needs_adjust_symbols(GElf_Ehdr ehdr)
{
return ehdr.e_type == ET_EXEC || ehdr.e_type == ET_REL;
}
int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
enum dso_binary_type type) enum dso_binary_type type)
{ {
@ -711,8 +716,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
".gnu.prelink_undo", ".gnu.prelink_undo",
NULL) != NULL); NULL) != NULL);
} else { } else {
ss->adjust_symbols = ehdr.e_type == ET_EXEC || ss->adjust_symbols = elf__needs_adjust_symbols(ehdr);
ehdr.e_type == ET_REL;
} }
ss->name = strdup(name); ss->name = strdup(name);

View File

@ -303,4 +303,8 @@ int setup_list(struct strlist **list, const char *list_str,
int setup_intlist(struct intlist **list, const char *list_str, int setup_intlist(struct intlist **list, const char *list_str,
const char *list_name); const char *list_name);
#ifdef HAVE_LIBELF_SUPPORT
bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
#endif
#endif /* __PERF_SYMBOL */ #endif /* __PERF_SYMBOL */