ppc64 vDSO update

Alan Modra amodra at bigpond.net.au
Wed Jan 5 10:31:32 EST 2005


On Tue, Jan 04, 2005 at 04:02:04PM -0600, Steve Munroe wrote:
> First it seems that glibc is expecting a (fairly normal) DSO image 
> including two (2) LOAD entries in the program header. The current PPC64 
> kernel vdso images only contain one (1) LOAD entry:
> 
> Program Headers:
>   Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
>   LOAD           0x000000 0x00100000 0x00100000 0x00e10 0x00e10 R E 
> 0x10000
>   DYNAMIC        0x000d98 0x00100d98 0x00100d98 0x00078 0x00078 R   0x4
>   GNU_EH_FRAME   0x000000 0x00000000 0x00000000 0x00000 0x00000     0x4

There's absolutely nothing wrong with an executable or shared lib having
just one PT_LOAD segment.  It's a glibc bug if ld.so can't handle it.

> This caused problems for the code in libc/elf/rtld.c that attempts to 
> extract l_map_start/l_map_end for the vdso:
> 
>               else if (ph->p_type == PT_LOAD)
>                 {
>                   if (! l->l_addr)
>                     l->l_addr = ph->p_vaddr;
>                   else if (ph->p_vaddr + ph->p_memsz >= l->l_map_end)
>                     l->l_map_end = ph->p_vaddr + ph->p_memsz;
>                   else if ((ph->p_flags & PF_X)
>                            && ph->p_vaddr + ph->p_memsz >= l->l_text_end)
>                     l->l_text_end = ph->p_vaddr + ph->p_memsz;
>                 }
> 
> This code will set l_addr but not l_map_end or l_text_end because it 
> grabbed the p_vaddr from the 1st and only LOAD entry then continue the 
> loop looking for the 2nd LOAD entry (which is not there!). On PPC32 this 
> causes the "assert (mapend > mapstart)" in __elf_preferred_address to 
> fail. I hacked around this by removing the "else" from the "else if" but 
> it just fails later.

Buggy code.  All the "else" keywords should be removed.  ie.

		  if (! l->l_addr)
		    l->l_addr = ph->p_vaddr;
		  if (ph->p_vaddr + ph->p_memsz >= l->l_map_end)
		    l->l_map_end = ph->p_vaddr + ph->p_memsz;
		  if ((ph->p_flags & PF_X)
		      && ph->p_vaddr + ph->p_memsz >= l->l_text_end)
		    l->l_text_end = ph->p_vaddr + ph->p_memsz;

> The remaining problem is we are getting into dl_iterate_phdr and taking a 
> wild branch. This could be from the callback in dl_iterate_phdr and due to 
> the incomplete nature of our vsdo. This is difficult to debug as the stack 
> point (and TOC pointer in PPC64) are both clobbered by this point and 
> GDB-6.1 gets totally confused.

I don't know what to suggest, other than brute force debugging by poking
.long 0 over code paths you suspect might be executed.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Linuxppc64-dev mailing list