Hi Mark, this problem happens on RHEL-5 as it has no build-id. On build-id system the files get re-aligned correctly.
That is if you generate core file, re-prelink you system (which happens nightly) and try to load the core file some shared libraries may no longer load at their right place. It happens even during "make check" for jankratochvil/unwindx86 which I am not sure why now. But the code was clearly wrong wrt prelink anyway. Fortunately link_map->l_ld is absolute address so one can recompute new l_addr according to it, ignoring former link_map->l_addr. There is no test case, though. Thanks, Jan
libdwfl/ 2013-11-01 Jan Kratochvil <[email protected]> Fix core files for re-prelink-ed files. * core-file.c (dynamic_vaddr_get): New function. (dwfl_core_file_report): New variable file_dynamic_vaddr. Call dynamic_vaddr_get instead of using L_ADDR. * libdwflP.h (struct r_debug_info_module): Remove field l_addr. * link_map.c (report_r_debug): Do not initialize l_addr. --- a/libdwfl/core-file.c +++ b/libdwfl/core-file.c @@ -397,6 +397,27 @@ clear_r_debug_info (struct r_debug_info *r_debug_info) } } +static bool +dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp) +{ + size_t phnum; + if (unlikely (elf_getphdrnum (elf, &phnum) != 0)) + return false; + for (size_t i = 0; i < phnum; ++i) + { + GElf_Phdr phdr_mem; + GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); + if (unlikely (phdr == NULL)) + return false; + if (phdr->p_type == PT_DYNAMIC) + { + *vaddrp = phdr->p_vaddr; + return true; + } + } + return false; +} + int dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable) { @@ -503,9 +524,13 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable) { if (module->elf == NULL) continue; + GElf_Addr file_dynamic_vaddr; + if (! dynamic_vaddr_get (module->elf, &file_dynamic_vaddr)) + continue; Dwfl_Module *mod; mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name, - module->fd, module->elf, module->l_addr, + module->fd, module->elf, + module->l_ld - file_dynamic_vaddr, true, true); if (mod == NULL) continue; --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -467,7 +467,7 @@ struct r_debug_info_module /* FD is -1 iff ELF is NULL. */ int fd; Elf *elf; - GElf_Addr l_addr, l_ld; + GElf_Addr l_ld; /* START and END are both zero if not valid. */ GElf_Addr start, end; bool disk_file_has_build_id; --- a/libdwfl/link_map.c +++ b/libdwfl/link_map.c @@ -369,7 +369,6 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, return release_buffer (result); r_debug_info_module->fd = -1; r_debug_info_module->elf = NULL; - r_debug_info_module->l_addr = l_addr; r_debug_info_module->l_ld = l_ld; r_debug_info_module->start = 0; r_debug_info_module->end = 0;
