perf callchain: Cache eh/debug frame offset for dwarf unwind

When libunwind tries to resolve callchains it needs to know the offset
of .eh_frame_hdr or .debug_frame to access the dso.

Since it will always return the same result for a given DSO, just cache
the result as an optimization.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1422518843-25818-41-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Namhyung Kim 2015-01-29 17:07:21 +09:00 committed by Arnaldo Carvalho de Melo
parent 459a3df76c
commit f1f13af99a
2 changed files with 21 additions and 11 deletions

View File

@ -139,6 +139,7 @@ struct dso {
u32 status_seen; u32 status_seen;
size_t file_size; size_t file_size;
struct list_head open_entry; struct list_head open_entry;
u64 frame_offset;
} data; } data;
union { /* Tool specific area */ union { /* Tool specific area */

View File

@ -266,14 +266,17 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
u64 *fde_count) u64 *fde_count)
{ {
int ret = -EINVAL, fd; int ret = -EINVAL, fd;
u64 offset; u64 offset = dso->data.frame_offset;
if (offset == 0) {
fd = dso__data_fd(dso, machine); fd = dso__data_fd(dso, machine);
if (fd < 0) if (fd < 0)
return -EINVAL; return -EINVAL;
/* Check the .eh_frame section for unwinding info */ /* Check the .eh_frame section for unwinding info */
offset = elf_section_offset(fd, ".eh_frame_hdr"); offset = elf_section_offset(fd, ".eh_frame_hdr");
dso->data.frame_offset = offset;
}
if (offset) if (offset)
ret = unwind_spec_ehframe(dso, machine, offset, ret = unwind_spec_ehframe(dso, machine, offset,
@ -287,14 +290,20 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
static int read_unwind_spec_debug_frame(struct dso *dso, static int read_unwind_spec_debug_frame(struct dso *dso,
struct machine *machine, u64 *offset) struct machine *machine, u64 *offset)
{ {
int fd = dso__data_fd(dso, machine); int fd;
u64 ofs = dso->data.frame_offset;
if (ofs == 0) {
fd = dso__data_fd(dso, machine);
if (fd < 0) if (fd < 0)
return -EINVAL; return -EINVAL;
/* Check the .debug_frame section for unwinding info */ /* Check the .debug_frame section for unwinding info */
*offset = elf_section_offset(fd, ".debug_frame"); ofs = elf_section_offset(fd, ".debug_frame");
dso->data.frame_offset = ofs;
}
*offset = ofs;
if (*offset) if (*offset)
return 0; return 0;