Em Fri, Nov 07, 2014 at 02:20:05PM +0900, Namhyung Kim escreveu:
> It'll be used to show (userspace) symbol names when libelf isn't (or
> cannot be) linked.

Does this deals with prelink, etc?

- Arnaldo
 
>   # Overhead  Command     Shared Object      Symbol
>   # ........  ..........  .................  .........................
>   #
>       37.01%  mem-memcpy  libc-2.17.so       [.] __memcpy_ssse3_back
>       24.25%  perf        ld-2.17.so         [.] _dl_relocate_object
>       22.16%  perf        [kernel.kallsyms]  [k] kmem_cache_alloc
>       14.29%  mem-memset  libc-2.17.so       [.] __memset_sse2
>        2.21%  perf        [kernel.kallsyms]  [k] flush_signal_handlers
>        0.07%  perf        [kernel.kallsyms]  [k] intel_pmu_enable_all
> 
> Cc: Adrian Hunter <adrian.hun...@intel.com>
> Signed-off-by: Namhyung Kim <namhy...@kernel.org>
> ---
>  tools/perf/util/symbol-minimal.c | 143 
> ++++++++++++++++++++++++++++++++++++---
>  tools/perf/util/symbol-minimal.h |  64 ++++++++++++++++++
>  tools/perf/util/symbol.h         |  10 ++-
>  3 files changed, 208 insertions(+), 9 deletions(-)
>  create mode 100644 tools/perf/util/symbol-minimal.h
> 
> diff --git a/tools/perf/util/symbol-minimal.c 
> b/tools/perf/util/symbol-minimal.c
> index 226cf41ed7e6..9da571d83a25 100644
> --- a/tools/perf/util/symbol-minimal.c
> +++ b/tools/perf/util/symbol-minimal.c
> @@ -1,11 +1,13 @@
>  #include "symbol.h"
>  #include "util.h"
> +#include "debug.h"
>  
>  #include <stdio.h>
>  #include <fcntl.h>
>  #include <string.h>
>  #include <byteswap.h>
>  #include <sys/stat.h>
> +#include <sys/mman.h>
>  
>  
>  static bool check_need_swap(int file_endian)
> @@ -242,22 +244,81 @@ int sysfs__read_build_id(const char *filename, void 
> *build_id, size_t size)
>       return ret;
>  }
>  
> +static const char *symsrc__symname(struct symsrc *ss, Elf_Shdr *strsec, int 
> idx)
> +{
> +     return ss->ptr + strsec->sh_offset + idx;
> +}
> +
>  int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
>                const char *name,
>                enum dso_binary_type type)
>  {
> -     int fd = open(name, O_RDONLY);
> +     int fd;
> +     unsigned i;
> +     Elf_Ehdr ehdr;
> +     struct stat stbuf;
> +     void *ptr;
> +
> +     fd = open(name, O_RDONLY);
>       if (fd < 0)
>               return -1;
>  
>       ss->name = strdup(name);
> -     if (!ss->name)
> -             goto out_close;
> +     if (!ss->name) {
> +             close(fd);
> +             return -1;
> +     }
>  
>       ss->fd = fd;
>       ss->type = type;
>  
> +     /* only consider native case (no swap) */
> +     if (read(fd, &ehdr, sizeof(ehdr)) < 0)
> +             goto out_close;
> +
> +     if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) ||
> +         ehdr.e_ident[EI_VERSION] != EV_CURRENT)
> +             goto out_close;
> +
> +     if (ehdr.e_ident[EI_CLASS] != ELFCLASS)
> +             goto out_close;
> +
> +     if (check_need_swap(ehdr.e_ident[EI_DATA]))
> +             goto out_close;
> +
> +     if (ehdr.e_shentsize != sizeof(Elf_Shdr))
> +             goto out_close;
> +
> +     if (fstat(fd, &stbuf) < 0)
> +             goto out_close;
> +
> +     ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
> +     if (ptr == MAP_FAILED)
> +             goto out_close;
> +
> +     ss->ptr = ptr;
> +     ss->len = stbuf.st_size;
> +     ss->sec = ptr + ehdr.e_shoff;
> +
> +     ss->symtab = NULL;
> +     for (i = 0; i < ehdr.e_shnum; i++) {
> +             Elf_Shdr *shdrp = &ss->sec[i];
> +             const char *shname;
> +
> +             shname = symsrc__symname(ss, &ss->sec[ehdr.e_shstrndx],
> +                                      shdrp->sh_name);
> +
> +             if (!strcmp(shname, ".text"))
> +                     ss->adjust_offset = shdrp->sh_addr - shdrp->sh_offset;
> +
> +             if (shdrp->sh_type == SHT_SYMTAB) {
> +                     ss->symtab = shdrp;
> +                     ss->strtab = &ss->sec[shdrp->sh_link];
> +             }
> +     }
> +
>       return 0;
> +
>  out_close:
>       close(fd);
>       return -1;
> @@ -276,6 +337,7 @@ bool symsrc__has_symtab(struct symsrc *ss __maybe_unused)
>  
>  void symsrc__destroy(struct symsrc *ss)
>  {
> +     munmap(ss->ptr, ss->len);
>       zfree(&ss->name);
>       close(ss->fd);
>  }
> @@ -332,7 +394,9 @@ int dso__load_sym(struct dso *dso, struct map *map 
> __maybe_unused,
>                 symbol_filter_t filter __maybe_unused,
>                 int kmodule __maybe_unused)
>  {
> -     unsigned char *build_id[BUILD_ID_SIZE];
> +     Elf_Ehdr *ehdr = ss->ptr;
> +     Elf_Sym *symtab;
> +     size_t i, nr_sym;
>       int ret;
>  
>       if (dso->kernel)
> @@ -342,11 +406,74 @@ int dso__load_sym(struct dso *dso, struct map *map 
> __maybe_unused,
>       if (ret >= 0)
>               dso->is_64_bit = ret;
>  
> -     if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
> -             dso__set_build_id(dso, build_id);
> -             return 1;
> +     if (dso->has_build_id) {
> +             u8 build_id[BUILD_ID_SIZE];
> +
> +             if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) 
> < 0)
> +                     return -1;
> +
> +             if (!dso__build_id_equal(dso, build_id))
> +                     return -1;
>       }
> -     return 0;
> +
> +     if (map->type != MAP__FUNCTION)
> +             return 0;
> +
> +     if (!ss->symtab)
> +             return 0;
> +
> +     symtab = ss->ptr + ss->symtab->sh_offset;
> +     nr_sym = ss->symtab->sh_size / ss->symtab->sh_entsize;
> +
> +     pr_debug4("loading symbols from %s\n", ss->name);
> +     ret = 0;
> +     for (i = 0; i < nr_sym; i++) {
> +             struct symbol *s;
> +             Elf_Sym *sym = &symtab[i];
> +             const char *symname = symsrc__symname(ss, ss->strtab, 
> sym->st_name);
> +             unsigned long sym_addr = sym->st_value;
> +
> +             if (ELF_ST_TYPE(sym->st_info) != STT_FUNC)
> +                     continue;
> +
> +             if (sym->st_shndx == SHN_UNDEF)
> +                     continue;
> +
> +             if (ehdr->e_machine == EM_ARM) {
> +                     /* Reject ARM ELF "mapping symbols": these aren't unique
> +                      * and don't identify functions, so will confuse the
> +                      * profile output: */
> +                     if (!strcmp(symname, "$a") ||
> +                         !strcmp(symname, "$d") ||
> +                         !strcmp(symname, "$t"))
> +                             continue;
> +
> +                     /* On ARM, symbols for thumb functions have 1 added to
> +                      * the symbol address as a flag - remove it */
> +                     if (sym->st_value & 1)
> +                             sym_addr--;
> +             }
> +             sym_addr -= ss->adjust_offset;
> +
> +             pr_debug4("sym: %s (%lx+%lu)\n", symname, sym_addr, 
> sym->st_size);
> +             s = symbol__new(sym_addr, sym->st_size,
> +                             ELF_ST_BIND(sym->st_info), symname);
> +             if (!s)
> +                     break;
> +
> +             if (filter && filter(map, s))
> +                     symbol__delete(s);
> +             else {
> +                     symbols__insert(&dso->symbols[map->type], s);
> +                     ret++;
> +             }
> +     }
> +
> +     if (ret > 0) {
> +             symbols__fixup_duplicate(&dso->symbols[map->type]);
> +             symbols__fixup_end(&dso->symbols[map->type]);
> +     }
> +     return ret;
>  }
>  
>  int file__read_maps(int fd __maybe_unused, bool exe __maybe_unused,
> diff --git a/tools/perf/util/symbol-minimal.h 
> b/tools/perf/util/symbol-minimal.h
> new file mode 100644
> index 000000000000..7b8b38426359
> --- /dev/null
> +++ b/tools/perf/util/symbol-minimal.h
> @@ -0,0 +1,64 @@
> +#ifndef __PERF_SYMBOL_MINIMAL_H
> +#define __PERF_SYMBOL_MINIMAL_H
> +
> +#include <elf.h>
> +#include <linux/bitops.h>
> +
> +#if BITS_PER_LONG == 32
> +
> +# define ELFCLASS    ELFCLASS32
> +
> +# define Elf_Half    Elf32_Half
> +# define Elf_Word    Elf32_Word
> +# define Elf_Sword   Elf32_Sword
> +# define Elf_Xword   Elf32_Xword
> +# define Elf_Sxword  Elf32_Sxword
> +# define Elf_Addr    Elf32_Addr
> +# define Elf_Off     Elf32_Off
> +# define Elf_Section Elf32_Section
> +# define Elf_Versym  Elf32_Versym
> +
> +# define Elf_Ehdr    Elf32_Ehdr
> +# define Elf_Phdr    Elf32_Phdr
> +# define Elf_Shdr    Elf32_Shdr
> +# define Elf_Nhdr    Elf32_Nhdr
> +# define Elf_Sym     Elf32_Sym
> +# define Elf_Syminfo Elf32_Syminfo
> +# define Elf_Rel     Elf32_Rel
> +# define Elf_Rela    Elf32_Rela
> +# define Elf_Dyn     Elf32_Dyn
> +
> +# define ELF_ST_BIND(val)            ELF32_ST_BIND(val)
> +# define ELF_ST_TYPE(val)            ELF32_ST_TYPE(val)
> +# define ELF_ST_INFO(bind, type)     ELF32_ST_INFO(bind, type)
> +
> +#else /* BITS_PER_LONG == 64 */
> +
> +# define ELFCLASS    ELFCLASS64
> +
> +# define Elf_Half    Elf64_Half
> +# define Elf_Word    Elf64_Word
> +# define Elf_Sword   Elf64_Sword
> +# define Elf_Xword   Elf64_Xword
> +# define Elf_Sxword  Elf64_Sxword
> +# define Elf_Addr    Elf64_Addr
> +# define Elf_Off     Elf64_Off
> +# define Elf_Section Elf64_Section
> +# define Elf_Versym  Elf64_Versym
> +
> +# define Elf_Ehdr    Elf64_Ehdr
> +# define Elf_Phdr    Elf64_Phdr
> +# define Elf_Shdr    Elf64_Shdr
> +# define Elf_Nhdr    Elf64_Nhdr
> +# define Elf_Sym     Elf64_Sym
> +# define Elf_Syminfo Elf64_Syminfo
> +# define Elf_Rel     Elf64_Rel
> +# define Elf_Rela    Elf64_Rela
> +# define Elf_Dyn     Elf64_Dyn
> +
> +# define ELF_ST_BIND(val)            ELF64_ST_BIND(val)
> +# define ELF_ST_TYPE(val)            ELF64_ST_TYPE(val)
> +# define ELF_ST_INFO(bind, type)     ELF64_ST_INFO(bind, type)
> +
> +#endif /* BITS_PER_LONG == 64 */
> +#endif /* __PERF_SYMBOL_MINIMAL_H */
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index ded3ca7266de..1c1dc5b9b3f8 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -18,8 +18,9 @@
>  #ifdef HAVE_LIBELF_SUPPORT
>  #include <libelf.h>
>  #include <gelf.h>
> +#else
> +#include "symbol-minimal.h"
>  #endif
> -#include <elf.h>
>  
>  #include "dso.h"
>  
> @@ -229,6 +230,13 @@ struct symsrc {
>  
>       bool adjust_symbols;
>       bool is_64_bit;
> +#else
> +     void *ptr;
> +     size_t len;
> +     Elf_Shdr *sec;
> +     Elf_Shdr *symtab;
> +     Elf_Shdr *strtab;
> +     long adjust_offset;
>  #endif
>  };
>  
> -- 
> 2.1.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to