- Previous thread: [PATCH] net: Keep interface binding when sending packets with ipi_ifindex = 0
- Next thread: linux-next: Tree for July 2
- Threads sorted by date: kernel 200907
Commit-ID: 6cfcc53ed4f3ecb9319e73a03f34f1eddcb644dd
Gitweb: http://git.kernel.org/tip/6cfcc53ed4f3ecb9319e73a03f34f1eddcb644dd
Author: Mike Galbraith
AuthorDate: Thu, 2 Jul 2009 08:08:36 +0200
Committer: Ingo Molnar
CommitDate: Thu, 2 Jul 2009 08:42:21 +0200
perf_counter tools: Connect module support infrastructure to symbol loading infrastructure
Signed-off-by: Mike Galbraith
Cc: Peter Zijlstra
Cc: Paul Mackerras
Cc: Arnaldo Carvalho de Melo
LKML-Reference:
Signed-off-by: Ingo Molnar
---
tools/perf/builtin-annotate.c | 2 +-
tools/perf/builtin-report.c | 2 +-
tools/perf/builtin-top.c | 2 +-
tools/perf/util/symbol.c | 159 ++++++++++++++++++++++++++++++++++++++---
tools/perf/util/symbol.h | 5 +-
5 files changed, 156 insertions(+), 14 deletions(-)
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 3becc8a..8820568 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -171,7 +171,7 @@ static int load_kernel(void)
if (!kernel_dso)
return -1;
- err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose);
+ err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, 0);
if (err end = len ? start + len - 1 : start;
memcpy(self->name, name, namelen);
return self;
@@ -48,8 +48,12 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size)
static size_t symbol__fprintf(struct symbol *self, FILE *fp)
{
- return fprintf(fp, " %llx-%llx %s\n",
+ if (!self->module)
+ return fprintf(fp, " %llx-%llx %s\n",
self->start, self->end, self->name);
+ else
+ return fprintf(fp, " %llx-%llx %s \t[%s]\n",
+ self->start, self->end, self->name, self->module->name);
}
struct dso *dso__new(const char *name, unsigned int sym_priv_size)
@@ -310,6 +314,26 @@ static inline int elf_sym__is_function(const GElf_Sym *sym)
sym->st_size != 0;
}
+static inline int elf_sym__is_label(const GElf_Sym *sym)
+{
+ return elf_sym__type(sym) == STT_NOTYPE &&
+ sym->st_name != 0 &&
+ sym->st_shndx != SHN_UNDEF &&
+ sym->st_shndx != SHN_ABS;
+}
+
+static inline const char *elf_sec__name(const GElf_Shdr *shdr,
+ const Elf_Data *secstrs)
+{
+ return secstrs->d_buf + shdr->sh_name;
+}
+
+static inline int elf_sec__is_text(const GElf_Shdr *shdr,
+ const Elf_Data *secstrs)
+{
+ return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
+}
+
static inline const char *elf_sym__name(const GElf_Sym *sym,
const Elf_Data *symstrs)
{
@@ -451,9 +475,9 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
}
static int dso__load_sym(struct dso *self, int fd, const char *name,
- symbol_filter_t filter, int verbose)
+ symbol_filter_t filter, int verbose, struct module *mod)
{
- Elf_Data *symstrs;
+ Elf_Data *symstrs, *secstrs;
uint32_t nr_syms;
int err = -1;
uint32_t index;
@@ -461,7 +485,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
GElf_Shdr shdr;
Elf_Data *syms;
GElf_Sym sym;
- Elf_Scn *sec, *sec_dynsym;
+ Elf_Scn *sec, *sec_dynsym, *sec_strndx;
Elf *elf;
size_t dynsym_idx;
int nr = 0;
@@ -520,6 +544,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
if (symstrs == NULL)
goto out_elf_end;
+ sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
+ if (sec_strndx == NULL)
+ goto out_elf_end;
+
+ secstrs = elf_getdata(sec_strndx, NULL);
+ if (symstrs == NULL)
+ goto out_elf_end;
+
nr_syms = shdr.sh_size / shdr.sh_entsize;
memset(&sym, 0, sizeof(sym));
@@ -529,8 +561,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
struct symbol *f;
u64 obj_start;
+ struct section *section = NULL;
+ int is_label = elf_sym__is_label(&sym);
+ const char *section_name;
- if (!elf_sym__is_function(&sym))
+ if (!is_label && !elf_sym__is_function(&sym))
continue;
sec = elf_getscn(elf, sym.st_shndx);
@@ -538,6 +573,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
goto out_elf_end;
gelf_getshdr(sec, &shdr);
+
+ if (is_label && !elf_sec__is_text(&shdr, secstrs))
+ continue;
+
+ section_name = elf_sec__name(&shdr, secstrs);
obj_start = sym.st_value;
if (self->prelinked) {
@@ -548,6 +588,17 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
sym.st_value -= shdr.sh_addr - shdr.sh_offset;
}
+ if (mod) {
+ section = mod->sections->find_section(mod->sections, section_name);
+ if (section)
+ sym.st_value += section->vma;
+ else {
+ fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
+ mod->name, section_name);
+ goto out_elf_end;
+ }
+ }
+
f = symbol__new(sym.st_value, sym.st_size,
elf_sym__name(&sym, symstrs),
self->sym_priv_size, obj_start, verbose);
@@ -557,6 +608,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
if (filter && filter(self, f))
symbol__delete(f, self->sym_priv_size);
else {
+ f->module = mod;
dso__insert_symbol(self, f);
nr++;
}
@@ -606,7 +658,7 @@ more:
fd = open(name, O_RDONLY);
} while (fd < 0);
- ret = dso__load_sym(self, fd, name, filter, verbose);
+ ret = dso__load_sym(self, fd, name, filter, verbose, NULL);
close(fd);
/*
@@ -620,6 +672,86 @@ out:
return ret;
}
+static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
+ symbol_filter_t filter, int verbose)
+{
+ struct module *mod = mod_dso__find_module(mods, name);
+ int err = 0, fd;
+
+ if (mod == NULL || !mod->active)
+ return err;
+
+ fd = open(mod->path, O_RDONLY);
+
+ if (fd < 0)
+ return err;
+
+ err = dso__load_sym(self, fd, name, filter, verbose, mod);
+ close(fd);
+
+ return err;
+}
+
+int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose)
+{
+ struct mod_dso *mods = mod_dso__new_dso("modules");
+ struct module *pos;
+ struct rb_node *next;
+ int err;
+
+ err = mod_dso__load_modules(mods);
+
+ if (err mods);
+ while (next) {
+ pos = rb_entry(next, struct module, rb_node);
+ err = dso__load_module(self, mods, pos->name, filter, verbose);
+
+ if (err < 0)
+ break;
+
+ next = rb_next(&pos->rb_node);
+ }
+
+ if (err < 0) {
+ mod_dso__delete_modules(mods);
+ mod_dso__delete_self(mods);
+ }
+
+ return err;
+}
+
+static inline void dso__fill_symbol_holes(struct dso *self)
+{
+ struct symbol *prev = NULL;
+ struct rb_node *nd;
+
+ for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) {
+ struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
+
+ if (prev) {
+ u64 hole = 0;
+ int alias = pos->start == prev->start;
+
+ if (!alias)
+ hole = prev->start - pos->end - 1;
+
+ if (hole || alias) {
+ if (alias)
+ pos->end = prev->end;
+ else if (hole)
+ pos->end = prev->start - 1;
+ }
+ }
+ prev = pos;
+ }
+}
+
static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
symbol_filter_t filter, int verbose)
{
@@ -628,19 +760,26 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
if (fd < 0)
return -1;
- err = dso__load_sym(self, fd, vmlinux, filter, verbose);
+ err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL);
+
+ if (err > 0)
+ dso__fill_symbol_holes(self);
+
close(fd);
return err;
}
int dso__load_kernel(struct dso *self, const char *vmlinux,
- symbol_filter_t filter, int verbose)
+ symbol_filter_t filter, int verbose, int modules)
{
int err = -1;
- if (vmlinux)
+ if (vmlinux) {
err = dso__load_vmlinux(self, vmlinux, filter, verbose);
+ if (err > 0 && modules)
+ err = dso__load_modules(self, filter, verbose);
+ }
if (err
Gitweb: http://git.kernel.org/tip/6cfcc53ed4f3ecb9319e73a03f34f1eddcb644dd
Author: Mike Galbraith
AuthorDate: Thu, 2 Jul 2009 08:08:36 +0200
Committer: Ingo Molnar
CommitDate: Thu, 2 Jul 2009 08:42:21 +0200
perf_counter tools: Connect module support infrastructure to symbol loading infrastructure
Signed-off-by: Mike Galbraith
Cc: Peter Zijlstra
Cc: Paul Mackerras
Cc: Arnaldo Carvalho de Melo
LKML-Reference:
Signed-off-by: Ingo Molnar
---
tools/perf/builtin-annotate.c | 2 +-
tools/perf/builtin-report.c | 2 +-
tools/perf/builtin-top.c | 2 +-
tools/perf/util/symbol.c | 159 ++++++++++++++++++++++++++++++++++++++---
tools/perf/util/symbol.h | 5 +-
5 files changed, 156 insertions(+), 14 deletions(-)
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 3becc8a..8820568 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -171,7 +171,7 @@ static int load_kernel(void)
if (!kernel_dso)
return -1;
- err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose);
+ err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, 0);
if (err end = len ? start + len - 1 : start;
memcpy(self->name, name, namelen);
return self;
@@ -48,8 +48,12 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size)
static size_t symbol__fprintf(struct symbol *self, FILE *fp)
{
- return fprintf(fp, " %llx-%llx %s\n",
+ if (!self->module)
+ return fprintf(fp, " %llx-%llx %s\n",
self->start, self->end, self->name);
+ else
+ return fprintf(fp, " %llx-%llx %s \t[%s]\n",
+ self->start, self->end, self->name, self->module->name);
}
struct dso *dso__new(const char *name, unsigned int sym_priv_size)
@@ -310,6 +314,26 @@ static inline int elf_sym__is_function(const GElf_Sym *sym)
sym->st_size != 0;
}
+static inline int elf_sym__is_label(const GElf_Sym *sym)
+{
+ return elf_sym__type(sym) == STT_NOTYPE &&
+ sym->st_name != 0 &&
+ sym->st_shndx != SHN_UNDEF &&
+ sym->st_shndx != SHN_ABS;
+}
+
+static inline const char *elf_sec__name(const GElf_Shdr *shdr,
+ const Elf_Data *secstrs)
+{
+ return secstrs->d_buf + shdr->sh_name;
+}
+
+static inline int elf_sec__is_text(const GElf_Shdr *shdr,
+ const Elf_Data *secstrs)
+{
+ return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
+}
+
static inline const char *elf_sym__name(const GElf_Sym *sym,
const Elf_Data *symstrs)
{
@@ -451,9 +475,9 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
}
static int dso__load_sym(struct dso *self, int fd, const char *name,
- symbol_filter_t filter, int verbose)
+ symbol_filter_t filter, int verbose, struct module *mod)
{
- Elf_Data *symstrs;
+ Elf_Data *symstrs, *secstrs;
uint32_t nr_syms;
int err = -1;
uint32_t index;
@@ -461,7 +485,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
GElf_Shdr shdr;
Elf_Data *syms;
GElf_Sym sym;
- Elf_Scn *sec, *sec_dynsym;
+ Elf_Scn *sec, *sec_dynsym, *sec_strndx;
Elf *elf;
size_t dynsym_idx;
int nr = 0;
@@ -520,6 +544,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
if (symstrs == NULL)
goto out_elf_end;
+ sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
+ if (sec_strndx == NULL)
+ goto out_elf_end;
+
+ secstrs = elf_getdata(sec_strndx, NULL);
+ if (symstrs == NULL)
+ goto out_elf_end;
+
nr_syms = shdr.sh_size / shdr.sh_entsize;
memset(&sym, 0, sizeof(sym));
@@ -529,8 +561,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
struct symbol *f;
u64 obj_start;
+ struct section *section = NULL;
+ int is_label = elf_sym__is_label(&sym);
+ const char *section_name;
- if (!elf_sym__is_function(&sym))
+ if (!is_label && !elf_sym__is_function(&sym))
continue;
sec = elf_getscn(elf, sym.st_shndx);
@@ -538,6 +573,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
goto out_elf_end;
gelf_getshdr(sec, &shdr);
+
+ if (is_label && !elf_sec__is_text(&shdr, secstrs))
+ continue;
+
+ section_name = elf_sec__name(&shdr, secstrs);
obj_start = sym.st_value;
if (self->prelinked) {
@@ -548,6 +588,17 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
sym.st_value -= shdr.sh_addr - shdr.sh_offset;
}
+ if (mod) {
+ section = mod->sections->find_section(mod->sections, section_name);
+ if (section)
+ sym.st_value += section->vma;
+ else {
+ fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
+ mod->name, section_name);
+ goto out_elf_end;
+ }
+ }
+
f = symbol__new(sym.st_value, sym.st_size,
elf_sym__name(&sym, symstrs),
self->sym_priv_size, obj_start, verbose);
@@ -557,6 +608,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
if (filter && filter(self, f))
symbol__delete(f, self->sym_priv_size);
else {
+ f->module = mod;
dso__insert_symbol(self, f);
nr++;
}
@@ -606,7 +658,7 @@ more:
fd = open(name, O_RDONLY);
} while (fd < 0);
- ret = dso__load_sym(self, fd, name, filter, verbose);
+ ret = dso__load_sym(self, fd, name, filter, verbose, NULL);
close(fd);
/*
@@ -620,6 +672,86 @@ out:
return ret;
}
+static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
+ symbol_filter_t filter, int verbose)
+{
+ struct module *mod = mod_dso__find_module(mods, name);
+ int err = 0, fd;
+
+ if (mod == NULL || !mod->active)
+ return err;
+
+ fd = open(mod->path, O_RDONLY);
+
+ if (fd < 0)
+ return err;
+
+ err = dso__load_sym(self, fd, name, filter, verbose, mod);
+ close(fd);
+
+ return err;
+}
+
+int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose)
+{
+ struct mod_dso *mods = mod_dso__new_dso("modules");
+ struct module *pos;
+ struct rb_node *next;
+ int err;
+
+ err = mod_dso__load_modules(mods);
+
+ if (err mods);
+ while (next) {
+ pos = rb_entry(next, struct module, rb_node);
+ err = dso__load_module(self, mods, pos->name, filter, verbose);
+
+ if (err < 0)
+ break;
+
+ next = rb_next(&pos->rb_node);
+ }
+
+ if (err < 0) {
+ mod_dso__delete_modules(mods);
+ mod_dso__delete_self(mods);
+ }
+
+ return err;
+}
+
+static inline void dso__fill_symbol_holes(struct dso *self)
+{
+ struct symbol *prev = NULL;
+ struct rb_node *nd;
+
+ for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) {
+ struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
+
+ if (prev) {
+ u64 hole = 0;
+ int alias = pos->start == prev->start;
+
+ if (!alias)
+ hole = prev->start - pos->end - 1;
+
+ if (hole || alias) {
+ if (alias)
+ pos->end = prev->end;
+ else if (hole)
+ pos->end = prev->start - 1;
+ }
+ }
+ prev = pos;
+ }
+}
+
static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
symbol_filter_t filter, int verbose)
{
@@ -628,19 +760,26 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
if (fd < 0)
return -1;
- err = dso__load_sym(self, fd, vmlinux, filter, verbose);
+ err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL);
+
+ if (err > 0)
+ dso__fill_symbol_holes(self);
+
close(fd);
return err;
}
int dso__load_kernel(struct dso *self, const char *vmlinux,
- symbol_filter_t filter, int verbose)
+ symbol_filter_t filter, int verbose, int modules)
{
int err = -1;
- if (vmlinux)
+ if (vmlinux) {
err = dso__load_vmlinux(self, vmlinux, filter, verbose);
+ if (err > 0 && modules)
+ err = dso__load_modules(self, filter, verbose);
+ }
if (err
Conversations: [patch 0/4] perf_counter tools: support annotation of live kernel modules
- [patch 0/4] perf_counter tools: support annotation of live kernel modules by Mike Galbraith on 2009-07-02T06:04:29+00:00
- [patch 1/4] perf_counter tools: Make symbol loading consistently return number of loaded symbols by Mike Galbraith on 2009-07-02T06:06:27+00:00
- [patch 2/4] perf_counter tools: Add infrastructure to support loading of kernel module symbols by Mike Galbraith on 2009-07-02T06:07:38+00:00
- [patch 3/4] perf_counter tools: connect module support infrastructure to symbol loading infrastructure by Mike Galbraith on 2009-07-02T06:08:57+00:00
- [patch 4/4] perf_counter tools: Enable kernel module symbol loading in tools by Mike Galbraith on 2009-07-02T06:10:08+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Ingo Molnar on 2009-07-02T06:47:40+00:00
- [tip:perfcounters/urgent] perf_counter tools: Make symbol loading consistently return number of loaded symbols by tip-bot for Mike Galbraith on 2009-07-02T07:07:44+00:00
- [tip:perfcounters/urgent] perf_counter tools: Add infrastructure to support loading of kernel module symbols by tip-bot for Mike Galbraith on 2009-07-02T07:08:08+00:00
- [tip:perfcounters/urgent] perf_counter tools: Enable kernel module symbol loading in tools by tip-bot for Mike Galbraith on 2009-07-02T07:08:08+00:00
- [tip:perfcounters/urgent] perf_counter tools: Connect module support infrastructure to symbol loading infrastructure by tip-bot for Mike Galbraith on 2009-07-02T07:08:40+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Mike Galbraith on 2009-07-02T07:18:27+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Ingo Molnar on 2009-07-02T07:42:45+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Mike Galbraith on 2009-07-02T07:56:05+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Mike Galbraith on 2009-07-02T08:43:21+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Mike Galbraith on 2009-07-02T08:54:02+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Peter Zijlstra on 2009-07-02T12:11:17+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Mike Galbraith on 2009-07-03T07:18:01+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Ingo Molnar on 2009-07-03T07:24:33+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Ingo Molnar on 2009-07-03T07:27:50+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Ingo Molnar on 2009-07-03T07:30:09+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Jaswinder Singh Rajput on 2009-07-03T07:33:04+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Mike Galbraith on 2009-07-03T07:36:46+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Mike Galbraith on 2009-07-03T08:01:26+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Ingo Molnar on 2009-07-03T08:16:42+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Mike Galbraith on 2009-07-03T08:35:56+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Frederic Weisbecker on 2009-07-03T08:41:36+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Ingo Molnar on 2009-07-03T08:54:07+00:00
- Re: [patch 0/4] perf_counter tools: support annotation of live kernel modules by Frederic Weisbecker on 2009-07-03T08:54:25+00:00
Related Threads
- PATCH 00/65 - Merge from the Graphite branch to trunk - gcc
- Hendrix - unitled fucking windows!!! - firefox
- Countries, States and Cities: Which relations i'm dealing with? - cakephp
- osol-discuss - Using multiple page sizes - opensolaris
- iceweasel and its missing libraries. - debian
- PHP - It's Friday (a MySQL Question) - php
- FreeBSD port: blender_2.49b_5 - freebsd
- Buffered input MinGW/Cygwin - - gcc
- which C standard - ruby
- Final CFP: ISWC'10 workshop on Ontology Matching (OM-2010): submission deadline is approaching - 15 days left - web
- webkit-dev - Web Audio API - webkit
- svn commit: r990948 - /activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/transport/failover/FailoverTransport.cpp - activemq