aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2015-01-29 03:07:21 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-01-29 14:20:42 -0500
commitf1f13af99a903ae873f5373e965508e0486c1c29 (patch)
tree183674eba3f82637bc6270ac15960cf6e31fa9c2 /tools
parent459a3df76c99124fd222586be7f10f862547e7a9 (diff)
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>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/dso.h1
-rw-r--r--tools/perf/util/unwind-libunwind.c31
2 files changed, 21 insertions, 11 deletions
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 3782c82c6e44..ced92841ff97 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -139,6 +139,7 @@ struct dso {
139 u32 status_seen; 139 u32 status_seen;
140 size_t file_size; 140 size_t file_size;
141 struct list_head open_entry; 141 struct list_head open_entry;
142 u64 frame_offset;
142 } data; 143 } data;
143 144
144 union { /* Tool specific area */ 145 union { /* Tool specific area */
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 6edf535f65c2..e3c40a520a25 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -266,14 +266,17 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
266 u64 *fde_count) 266 u64 *fde_count)
267{ 267{
268 int ret = -EINVAL, fd; 268 int ret = -EINVAL, fd;
269 u64 offset; 269 u64 offset = dso->data.frame_offset;
270 270
271 fd = dso__data_fd(dso, machine); 271 if (offset == 0) {
272 if (fd < 0) 272 fd = dso__data_fd(dso, machine);
273 return -EINVAL; 273 if (fd < 0)
274 return -EINVAL;
274 275
275 /* Check the .eh_frame section for unwinding info */ 276 /* Check the .eh_frame section for unwinding info */
276 offset = elf_section_offset(fd, ".eh_frame_hdr"); 277 offset = elf_section_offset(fd, ".eh_frame_hdr");
278 dso->data.frame_offset = offset;
279 }
277 280
278 if (offset) 281 if (offset)
279 ret = unwind_spec_ehframe(dso, machine, offset, 282 ret = unwind_spec_ehframe(dso, machine, offset,
@@ -287,14 +290,20 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
287static int read_unwind_spec_debug_frame(struct dso *dso, 290static int read_unwind_spec_debug_frame(struct dso *dso,
288 struct machine *machine, u64 *offset) 291 struct machine *machine, u64 *offset)
289{ 292{
290 int fd = dso__data_fd(dso, machine); 293 int fd;
294 u64 ofs = dso->data.frame_offset;
291 295
292 if (fd < 0) 296 if (ofs == 0) {
293 return -EINVAL; 297 fd = dso__data_fd(dso, machine);
298 if (fd < 0)
299 return -EINVAL;
294 300
295 /* Check the .debug_frame section for unwinding info */ 301 /* Check the .debug_frame section for unwinding info */
296 *offset = elf_section_offset(fd, ".debug_frame"); 302 ofs = elf_section_offset(fd, ".debug_frame");
303 dso->data.frame_offset = ofs;
304 }
297 305
306 *offset = ofs;
298 if (*offset) 307 if (*offset)
299 return 0; 308 return 0;
300 309