diff options
author | Wang Nan <wangnan0@huawei.com> | 2015-03-13 03:02:56 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-03-19 12:53:27 -0400 |
commit | 303cb89a6d708da9c24f6f3390ff68a2bd822a13 (patch) | |
tree | 64d09260d51b29b813b020eadc47300e35743bb3 /tools | |
parent | 1312c8a8fb126b9e7c45671813c39f8a435fadcb (diff) |
perf callchain: Separate eh/debug frame offset cache.
Commit f1f13af99a90 ("perf callchain: Cache eh/debug frame offset for
dwarf unwind") introduces a cache for .debug_frame and .eh_frame_hdr.
Unfortunately, it makes them share a same cache (dso->frame_offset).
Which causes unwind failure on ARM:
$ perf test unwind
Test dwarf unwind: FAILED!
The reason is that, if a dso has '.debug_frame' but doesn't have
'.eh_frame_hdr' (like ARM), dso->frame_offset will be filled by offset
of '.debug_frame' during the first time calling of find_proc_info() ->
read_unwind_spec_debug_frame(), and be regarded to '.eh_frame_hdr' when
the second time calling of find_proc_info() ->
read_unwind_spec_eh_frame(), since '.eh_frame_hdr' is checked prior to
'.debug_frame'.
This patch solves the problem by creating two cache fields for
'.eh_frame_hdr' and '.debug_frame'.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Li Zefan <lizefan@huawei.com>
Link: http://lkml.kernel.org/r/55028BA0.1030701@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/util/dso.h | 3 | ||||
-rw-r--r-- | tools/perf/util/unwind-libunwind.c | 8 |
2 files changed, 6 insertions, 5 deletions
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index ced92841ff97..408c65f1a757 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
@@ -139,7 +139,8 @@ 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 | u64 debug_frame_offset; |
143 | u64 eh_frame_hdr_offset; | ||
143 | } data; | 144 | } data; |
144 | 145 | ||
145 | union { /* Tool specific area */ | 146 | union { /* Tool specific area */ |
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index e3c40a520a25..7b09a443a280 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c | |||
@@ -266,7 +266,7 @@ 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 = dso->data.frame_offset; | 269 | u64 offset = dso->data.eh_frame_hdr_offset; |
270 | 270 | ||
271 | if (offset == 0) { | 271 | if (offset == 0) { |
272 | fd = dso__data_fd(dso, machine); | 272 | fd = dso__data_fd(dso, machine); |
@@ -275,7 +275,7 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine, | |||
275 | 275 | ||
276 | /* Check the .eh_frame section for unwinding info */ | 276 | /* Check the .eh_frame section for unwinding info */ |
277 | offset = elf_section_offset(fd, ".eh_frame_hdr"); | 277 | offset = elf_section_offset(fd, ".eh_frame_hdr"); |
278 | dso->data.frame_offset = offset; | 278 | dso->data.eh_frame_hdr_offset = offset; |
279 | } | 279 | } |
280 | 280 | ||
281 | if (offset) | 281 | if (offset) |
@@ -291,7 +291,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso, | |||
291 | struct machine *machine, u64 *offset) | 291 | struct machine *machine, u64 *offset) |
292 | { | 292 | { |
293 | int fd; | 293 | int fd; |
294 | u64 ofs = dso->data.frame_offset; | 294 | u64 ofs = dso->data.debug_frame_offset; |
295 | 295 | ||
296 | if (ofs == 0) { | 296 | if (ofs == 0) { |
297 | fd = dso__data_fd(dso, machine); | 297 | fd = dso__data_fd(dso, machine); |
@@ -300,7 +300,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso, | |||
300 | 300 | ||
301 | /* Check the .debug_frame section for unwinding info */ | 301 | /* Check the .debug_frame section for unwinding info */ |
302 | ofs = elf_section_offset(fd, ".debug_frame"); | 302 | ofs = elf_section_offset(fd, ".debug_frame"); |
303 | dso->data.frame_offset = ofs; | 303 | dso->data.debug_frame_offset = ofs; |
304 | } | 304 | } |
305 | 305 | ||
306 | *offset = ofs; | 306 | *offset = ofs; |