2010-05-04 Roland McGrath <roland@redhat.com>
+ * 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.
/* 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;
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;
}
}
/* 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,