diff options
Diffstat (limited to 'tools/perf/util/unwind-libunwind.c')
| -rw-r--r-- | tools/perf/util/unwind-libunwind.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 371219a6daf1..6edf535f65c2 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c | |||
| @@ -185,6 +185,28 @@ static u64 elf_section_offset(int fd, const char *name) | |||
| 185 | return offset; | 185 | return offset; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | ||
| 189 | static int elf_is_exec(int fd, const char *name) | ||
| 190 | { | ||
| 191 | Elf *elf; | ||
| 192 | GElf_Ehdr ehdr; | ||
| 193 | int retval = 0; | ||
| 194 | |||
| 195 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
| 196 | if (elf == NULL) | ||
| 197 | return 0; | ||
| 198 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
| 199 | goto out; | ||
| 200 | |||
| 201 | retval = (ehdr.e_type == ET_EXEC); | ||
| 202 | |||
| 203 | out: | ||
| 204 | elf_end(elf); | ||
| 205 | pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval); | ||
| 206 | return retval; | ||
| 207 | } | ||
| 208 | #endif | ||
| 209 | |||
| 188 | struct table_entry { | 210 | struct table_entry { |
| 189 | u32 start_ip_offset; | 211 | u32 start_ip_offset; |
| 190 | u32 fde_offset; | 212 | u32 fde_offset; |
| @@ -322,8 +344,12 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, | |||
| 322 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | 344 | #ifndef NO_LIBUNWIND_DEBUG_FRAME |
| 323 | /* Check the .debug_frame section for unwinding info */ | 345 | /* Check the .debug_frame section for unwinding info */ |
| 324 | if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { | 346 | if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { |
| 347 | int fd = dso__data_fd(map->dso, ui->machine); | ||
| 348 | int is_exec = elf_is_exec(fd, map->dso->name); | ||
| 349 | unw_word_t base = is_exec ? 0 : map->start; | ||
| 350 | |||
| 325 | memset(&di, 0, sizeof(di)); | 351 | memset(&di, 0, sizeof(di)); |
| 326 | if (dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name, | 352 | if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name, |
| 327 | map->start, map->end)) | 353 | map->start, map->end)) |
| 328 | return dwarf_search_unwind_table(as, ip, &di, pi, | 354 | return dwarf_search_unwind_table(as, ip, &di, pi, |
| 329 | need_unwind_info, arg); | 355 | need_unwind_info, arg); |
