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/