Skip to content

Commit

Permalink
perf callchain: Cache eh/debug frame offset for dwarf unwind
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Namhyung Kim authored and Arnaldo Carvalho de Melo committed Jan 29, 2015
1 parent 459a3df commit f1f13af
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 11 deletions.
1 change: 1 addition & 0 deletions tools/perf/util/dso.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ struct dso {
u32 status_seen;
size_t file_size;
struct list_head open_entry;
u64 frame_offset;
} data;

union { /* Tool specific area */
Expand Down
31 changes: 20 additions & 11 deletions tools/perf/util/unwind-libunwind.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,14 +266,17 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
u64 *fde_count)
{
int ret = -EINVAL, fd;
u64 offset;
u64 offset = dso->data.frame_offset;

fd = dso__data_fd(dso, machine);
if (fd < 0)
return -EINVAL;
if (offset == 0) {
fd = dso__data_fd(dso, machine);
if (fd < 0)
return -EINVAL;

/* Check the .eh_frame section for unwinding info */
offset = elf_section_offset(fd, ".eh_frame_hdr");
/* Check the .eh_frame section for unwinding info */
offset = elf_section_offset(fd, ".eh_frame_hdr");
dso->data.frame_offset = offset;
}

if (offset)
ret = unwind_spec_ehframe(dso, machine, offset,
Expand All @@ -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,
struct machine *machine, u64 *offset)
{
int fd = dso__data_fd(dso, machine);
int fd;
u64 ofs = dso->data.frame_offset;

if (fd < 0)
return -EINVAL;
if (ofs == 0) {
fd = dso__data_fd(dso, machine);
if (fd < 0)
return -EINVAL;

/* Check the .debug_frame section for unwinding info */
*offset = elf_section_offset(fd, ".debug_frame");
/* Check the .debug_frame section for unwinding info */
ofs = elf_section_offset(fd, ".debug_frame");
dso->data.frame_offset = ofs;
}

*offset = ofs;
if (*offset)
return 0;

Expand Down

0 comments on commit f1f13af

Please sign in to comment.