From: Roland McGrath Date: Wed, 5 May 2010 01:05:22 +0000 (-0700) Subject: dwfl_link_map_report: Handle PIE-generated core. X-Git-Tag: elfutils-0.148~60 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d05c596d2a97326259b4f91861487feed63d4946;p=thirdparty%2Felfutils.git dwfl_link_map_report: Handle PIE-generated core. --- diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 9f4a745db..f7a3b8471 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,5 +1,8 @@ 2010-05-04 Roland McGrath + * link_map.c (dwfl_link_map_report): Detect bias of embedded phdrs and + apply it to PT_DYNAMIC p_vaddr so we handle a PIE correctly. + * core-file.c (dwfl_core_file_report): Return any nonzero count of modules reported, even if link_map grovelling failed and only sniffing found anything. diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c index fe7f40cee..403b2df68 100644 --- a/libdwfl/link_map.c +++ b/libdwfl/link_map.c @@ -684,6 +684,33 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC. */ GElf_Addr dyn_vaddr = 0; GElf_Xword dyn_filesz = 0; + GElf_Addr dyn_bias = (GElf_Addr) -1; + + inline bool consider_phdr (GElf_Word type, + GElf_Addr vaddr, GElf_Xword filesz) + { + switch (type) + { + case PT_PHDR: + if (dyn_bias == (GElf_Addr) -1 + /* Do a sanity check on the putative address. */ + && ((vaddr & (dwfl->segment_align - 1)) + == (phdr & (dwfl->segment_align - 1)))) + { + dyn_bias = phdr - vaddr; + return dyn_vaddr != 0; + } + break; + + case PT_DYNAMIC: + dyn_vaddr = vaddr; + dyn_filesz = filesz; + return dyn_bias != (GElf_Addr) -1; + } + + return false; + } + if (phdr != 0 && phnum != 0) { Dwfl_Module *phdr_mod; @@ -725,22 +752,18 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, if (elfclass == ELFCLASS32) { for (size_t i = 0; i < phnum; ++i) - if (u->p32[i].p_type == PT_DYNAMIC) - { - dyn_vaddr = u->p32[i].p_vaddr; - dyn_filesz = u->p32[i].p_filesz; - break; - } + if (consider_phdr (u->p32[i].p_type, + u->p32[i].p_vaddr, + u->p32[i].p_filesz)) + break; } else { for (size_t i = 0; i < phnum; ++i) - if (u->p64[i].p_type == PT_DYNAMIC) - { - dyn_vaddr = u->p64[i].p_vaddr; - dyn_filesz = u->p64[i].p_filesz; - break; - } + if (consider_phdr (u->p64[i].p_type, + u->p64[i].p_vaddr, + u->p64[i].p_filesz)) + break; } } @@ -775,6 +798,9 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, /* If we found PT_DYNAMIC, search it for DT_DEBUG. */ if (dyn_filesz != 0) { + if (dyn_bias != (GElf_Addr) -1) + dyn_vaddr += dyn_bias; + Elf_Data in = { .d_type = ELF_T_DYN,