mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

Use symbol table lookups by default if DWARF is not necessary, since powerpc ABIv2 encodes local entry points in the symbol table and the function entry address in DWARF may not be appropriate for kprobes, as described here: https://sourceware.org/bugzilla/show_bug.cgi?id=17638 "The DWARF address ranges deliberately include the *whole* function, both global and local entry points." ... "If you want to set probes on a local entry point, you should look up the symbol in the main symbol table (not DWARF), and check the st_other bits; they will indicate whether the function has a local entry point, and what its offset from the global entry point is. Note that GDB does the same when setting a breakpoint on a function entry." 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/88a10e22f4aaba2aef812824ca4b10d7beeea012.1430217967.git.naveen.n.rao@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
67 lines
1.4 KiB
C
67 lines
1.4 KiB
C
/*
|
|
* 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"
|
|
#include "map.h"
|
|
#include "probe-event.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;
|
|
}
|
|
|
|
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
|
void arch__elf_sym_adjust(GElf_Sym *sym)
|
|
{
|
|
sym->st_value += PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined(_CALL_ELF) || _CALL_ELF != 2
|
|
int arch__choose_best_symbol(struct symbol *syma,
|
|
struct symbol *symb __maybe_unused)
|
|
{
|
|
char *sym = syma->name;
|
|
|
|
/* Skip over any initial dot */
|
|
if (*sym == '.')
|
|
sym++;
|
|
|
|
/* Avoid "SyS" kernel syscall aliases */
|
|
if (strlen(sym) >= 3 && !strncmp(sym, "SyS", 3))
|
|
return SYMBOL_B;
|
|
if (strlen(sym) >= 10 && !strncmp(sym, "compat_SyS", 10))
|
|
return SYMBOL_B;
|
|
|
|
return SYMBOL_A;
|
|
}
|
|
|
|
/* Allow matching against dot variants */
|
|
int arch__compare_symbol_names(const char *namea, const char *nameb)
|
|
{
|
|
/* Skip over initial dot */
|
|
if (*namea == '.')
|
|
namea++;
|
|
if (*nameb == '.')
|
|
nameb++;
|
|
|
|
return strcmp(namea, nameb);
|
|
}
|
|
#endif
|
|
|
|
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
|
bool arch__prefers_symtab(void)
|
|
{
|
|
return true;
|
|
}
|
|
#endif
|