diff options
Diffstat (limited to 'tools/perf/util/symbol-elf.c')
-rw-r--r-- | tools/perf/util/symbol-elf.c | 87 |
1 files changed, 81 insertions, 6 deletions
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index d75349979e65..06fcd1bf98b6 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -6,10 +6,32 @@ #include <inttypes.h> #include "symbol.h" +#include "machine.h" #include "vdso.h" #include <symbol/kallsyms.h> #include "debug.h" +#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT +extern char *cplus_demangle(const char *, int); + +static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i) +{ + return cplus_demangle(c, i); +} +#else +#ifdef NO_DEMANGLE +static inline char *bfd_demangle(void __maybe_unused *v, + const char __maybe_unused *c, + int __maybe_unused i) +{ + return NULL; +} +#else +#define PACKAGE 'perf' +#include <bfd.h> +#endif +#endif + #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT static int elf_getphdrnum(Elf *elf, size_t *dst) { @@ -545,6 +567,35 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata) return 0; } +static int decompress_kmodule(struct dso *dso, const char *name, + enum dso_binary_type type) +{ + int fd; + const char *ext = strrchr(name, '.'); + char tmpbuf[] = "/tmp/perf-kmod-XXXXXX"; + + if ((type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && + type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP) || + type != dso->symtab_type) + return -1; + + if (!ext || !is_supported_compression(ext + 1)) + return -1; + + fd = mkstemp(tmpbuf); + if (fd < 0) + return -1; + + if (!decompress_to_file(ext + 1, name, fd)) { + close(fd); + fd = -1; + } + + unlink(tmpbuf); + + return fd; +} + bool symsrc__possibly_runtime(struct symsrc *ss) { return ss->dynsym || ss->opdsec; @@ -570,7 +621,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, Elf *elf; int fd; - fd = open(name, O_RDONLY); + if (dso__needs_decompress(dso)) + fd = decompress_kmodule(dso, name, type); + else + fd = open(name, O_RDONLY); + if (fd < 0) return -1; @@ -680,6 +735,11 @@ static u64 ref_reloc(struct kmap *kmap) return 0; } +static bool want_demangle(bool is_kernel_sym) +{ + return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle; +} + int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, struct symsrc *runtime_ss, symbol_filter_t filter, int kmodule) @@ -712,6 +772,14 @@ int dso__load_sym(struct dso *dso, struct map *map, symbols__delete(&dso->symbols[map->type]); if (!syms_ss->symtab) { + /* + * If the vmlinux is stripped, fail so we will fall back + * to using kallsyms. The vmlinux runtime symbols aren't + * of much use. + */ + if (dso->kernel) + goto out_elf_end; + syms_ss->symtab = syms_ss->dynsym; syms_ss->symshdr = syms_ss->dynshdr; } @@ -736,7 +804,7 @@ int dso__load_sym(struct dso *dso, struct map *map, if (symstrs == NULL) goto out_elf_end; - sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); + sec_strndx = elf_getscn(runtime_ss->elf, runtime_ss->ehdr.e_shstrndx); if (sec_strndx == NULL) goto out_elf_end; @@ -916,7 +984,11 @@ int dso__load_sym(struct dso *dso, struct map *map, } curr_dso->symtab_type = dso->symtab_type; map_groups__insert(kmap->kmaps, curr_map); - dsos__add(&dso->node, curr_dso); + /* + * The new DSO should go to the kernel DSOS + */ + dsos__add(&map->groups->machine->kernel_dsos, + curr_dso); dso__set_loaded(curr_dso, map->type); } else curr_dso = curr_map->dso; @@ -938,9 +1010,12 @@ new_symbol: * DWARF DW_compile_unit has this, but we don't always have access * to it... */ - if (symbol_conf.demangle) { - demangled = bfd_demangle(NULL, elf_name, - DMGL_PARAMS | DMGL_ANSI); + if (want_demangle(dso->kernel || kmodule)) { + int demangle_flags = DMGL_NO_OPTS; + if (verbose) + demangle_flags = DMGL_PARAMS | DMGL_ANSI; + + demangled = bfd_demangle(NULL, elf_name, demangle_flags); if (demangled != NULL) elf_name = demangled; } |