svn commit: r339876 - head/libexec/rtld-elf

Konstantin Belousov kostikbel at gmail.com
Fri Nov 2 18:50:27 UTC 2018


On Fri, Nov 02, 2018 at 10:38:08AM -0700, Mark Millard wrote:
> On 2018-Nov-2, at 8:52 AM, Konstantin Belousov <kostikbel at gmail.com> wrote:
> 
> > On Fri, Nov 02, 2018 at 08:30:17AM -0700, Mark Millard wrote:
> >> Breakpoint 4, reloc_non_plt (obj=0x41041000, obj_rtld=0x1801cc7, flags=4, lockstate=0x0) at /usr/src/libexec/rtld-elf/powerpc/reloc.c:338
> >> 338				__syncicache(obj->mapbase + phdr->p_vaddr,
> >> 1: x/i $pc
> >> => 0x1012b90 <reloc_non_plt+276>:	lwz     r0,36(r29)
> >> (gdb) print/x obj->mapbase+phdr->p_vaddr
> >> $17 = 0x3000000
> >> (gdb) print/x obj->mapbase              
> >> $18 = 0x1800000
> >> (gdb) print/x phdr->p_vaddr
> >> $19 = 0x1800000
> >> (gdb) c
> >> Continuing.
> >> 
> >> Program received signal SIGSEGV, Segmentation fault.
> >> __syncicache (from=0x3000000, len=34112) at /usr/src/lib/libc/powerpc/gen/syncicache.c:94
> >> 94			__asm __volatile ("dcbst 0,%0" :: "r"(p));
> >> 1: x/i $pc
> >> => 0x10228b8 <__syncicache+96>:	dcbst   0,r11
> >> 
> >> 
> >> 
> >> It looks to me like the 0x1800000 component of the
> >> overall figure was double counted. ( phdr->p_vaddr
> >> would vary but obj->mapbase would not. )
> >> 
> >> Omit "obj->mapbase + "?
> > I used the wrong addend.  Try this fix.
> > 
> > diff --git a/libexec/rtld-elf/powerpc/reloc.c b/libexec/rtld-elf/powerpc/reloc.c
> > index e921a4dc7d1..fae28dd9224 100644
> > --- a/libexec/rtld-elf/powerpc/reloc.c
> > +++ b/libexec/rtld-elf/powerpc/reloc.c
> > @@ -294,6 +294,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
> > {
> > 	const Elf_Rela *relalim;
> > 	const Elf_Rela *rela;
> > +	const Elf_Phdr *phdr;
> > 	SymCache *cache;
> > 	int r = -1;
> > 
> > @@ -327,8 +328,18 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
> > 	if (cache != NULL)
> > 		free(cache);
> > 
> > -	/* Synchronize icache for text seg in case we made any changes */
> > -	__syncicache(obj->mapbase, obj->textsize);
> > +	/*
> > +	 * Synchronize icache for executable segments in case we made
> > +	 * any changes.
> > +	 */
> > +	for (phdr = obj->phdr;
> > +	    (const char *)phdr < (const char *)obj->phdr + obj->phsize;
> > +	    phdr++) {
> > +		if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X) != 0) {
> > +			__syncicache(obj->relocbase + phdr->p_vaddr,
> > +			    phdr->p_memsz);
> > +		}
> > +	}
> > 
> > 	return (r);
> > }
> > diff --git a/libexec/rtld-elf/powerpc64/reloc.c b/libexec/rtld-elf/powerpc64/reloc.c
> > index c2d6dac13b1..15f31738ab7 100644
> > --- a/libexec/rtld-elf/powerpc64/reloc.c
> > +++ b/libexec/rtld-elf/powerpc64/reloc.c
> > @@ -291,6 +291,7 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
> > {
> > 	const Elf_Rela *relalim;
> > 	const Elf_Rela *rela;
> > +	const Elf_Phdr *phdr;
> > 	SymCache *cache;
> > 	int bytes = obj->dynsymcount * sizeof(SymCache);
> > 	int r = -1;
> > @@ -327,8 +328,18 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
> > 	if (cache)
> > 		munmap(cache, bytes);
> > 
> > -	/* Synchronize icache for text seg in case we made any changes */
> > -	__syncicache(obj->mapbase, obj->textsize);
> > +	/*
> > +	 * Synchronize icache for executable segments in case we made
> > +	 * any changes.
> > +	 */
> > +	for (phdr = obj->phdr;
> > +	    (const char *)phdr < (const char *)obj->phdr + obj->phsize;
> > +	    phdr++) {
> > +		if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X) != 0) {
> > +			__syncicache(obj->relocbase + phdr->p_vaddr,
> > +			    phdr->p_memsz);
> > +		}
> > +	}
> > 
> > 	return (r);
> > }
> 
> That seems better. But it crashes during /bin/ls execution
> ( 0x0180???? addresses ), apparently in a library routine
> ( 0x41?????? addresses ):
> 
> Program received signal SIGSEGV, Segmentation fault.
> 0x411220b4 in ?? ()
> (gdb) bt
> #0  0x411220b4 in ?? ()
> #1  0x4112200c in ?? ()
> #2  0x01803c84 in ?? ()
> #3  0x018023b4 in ?? ()
> #4  0x010121a0 in .rtld_start () at /usr/src/libexec/rtld-elf/powerpc/rtld_start.S:112
> 
> Using a normal gdb run of /bin/ls suggests:
> 
> #2  0x01803c84 in ?? () should be in main and seems to be: bl 0x1818914 <getopt_long at plt>
> #3  0x018023b4 in ?? () should be in _start
> 
> Looking in the test context:
> 
>    0x1803c80:	bl      0x1818914
>    0x1803c84:	cmpwi   cr7,r3,-1
> 
> and:
> 
>    0x1818914:	li      r11,59
>    0x1818918:	b       0x18186f4
> 
> and:
> 
>    0x18186f4:	rlwinm  r11,r11,2,0,29
>    0x18186f8:	addis   r11,r11,386
>    0x18186fc:	lwz     r11,-30316(r11)
>    0x1818700:	mtctr   r11
>    0x1818704:	bctr
> 
> Breaking at the bctr and using info reg:
> 
> r11            0x4125ffa0	1093009312
> 
> It looks like there is some amount of
> activity before the traceback addresses
> show up.
> 
> I've not found a good way to fill in the "in ??()"
> (or analogous) information. The addresses 0x411220??
> do not match up with a normal run of /bin/ls from
> gdb: the addresses can not be accessed.
> 
> 
> 
> It does appear that the code is in /lib/libc.so.7 in the
> test context:
> 
> Breakpoint 2, reloc_non_plt (obj=0x41041600, obj_rtld=0x41104b57, flags=4, lockstate=0x0) at /usr/src/libexec/rtld-elf/powerpc/reloc.c:338
> 338				__syncicache(obj->relocbase + phdr->p_vaddr,
> 1: /x obj->relocbase + phdr->p_vaddr = 0x410ec000
> 2: /x obj->relocbase + phdr->p_vaddr + phdr->p_memsz = 0x4127f9d0
> 4: *obj = {magic = 0, version = 0, next = {tqe_next = 0x0, tqe_prev = 0x41041408}, path = 0x4103f100 "/lib/libc.so.7", origin_path = 0x0, refcount = 1, holdcount = 0, dl_refcount = 0, 
>   mapbase = 0x410ec000 "\177ELF\001\002\001\t", mapsize = 1908736, textsize = 1908736, vaddrbase = 0, relocbase = 0x410ec000 "\177ELF\001\002\001\t", dynamic = 0x412938e0, 
>   entry = 0x41119d20 "\224!\377\340|\b\002\246H\027\374\001\223\301", phdr = 0x410ec034, phsize = 192, interp = 0x0, stack_flags = 6, tlsindex = 2, tlsinit = 0x4128f9d0, tlsinitsize = 2832, 
>   tlssize = 2860, tlsoffset = 8, tlsalign = 16, relro_page = 0x410ec000 "\177ELF\001\002\001\t", relro_size = 0, pltgot = 0x41299ba8, rel = 0x0, relsize = 0, rela = 0x41106530, relasize = 79800, 
>   pltrel = 0x0, pltrelsize = 0, pltrela = 0x41116d6c, pltrelasize = 12156, symtab = 0x410f12a0, strtab = 0x410fd8e0 "", strsize = 29303, verneed = 0x0, verneednum = 0, verdef = 0x41106420, 
>   verdefnum = 8, versyms = 0x41104b58, buckets = 0x410ec0fc, nbuckets = 2053, chains = 0x410ee110, nchains = 3172, nbuckets_gnu = 0, symndx_gnu = 0, maskwords_bm_gnu = 0, shift2_gnu = 0, 
>   dynsymcount = 3172, bloom_gnu = 0x0, buckets_gnu = 0x0, chain_zero_gnu = 0x0, rpath = 0x0, runpath = 0x0, needed = 0x0, needed_filtees = 0x0, needed_aux_filtees = 0x0, names = {
>     stqh_first = 0x4103f120, stqh_last = 0x4103f140}, vertab = 0x41040400, vernum = 9, init = 1091673320, fini = 1093063668, preinit_array = 0, init_array = 0, fini_array = 0, preinit_array_num = 0, 
>   init_array_num = 0, fini_array_num = 0, osrel = 0, mainprog = 0 '\000', rtld = 0 '\000', relocated = 1 '\001', ver_checked = 1 '\001', textrel = 0 '\000', symbolic = 0 '\000', bind_now = 0 '\000', 
>   traced = 0 '\000', jmpslots_done = 0 '\000', init_done = 0 '\000', tls_done = 1 '\001', phdr_alloc = 0 '\000', z_origin = 0 '\000', z_nodelete = 0 '\000', z_noopen = 0 '\000', 
>   z_loadfltr = 0 '\000', z_interpose = 0 '\000', z_nodeflib = 0 '\000', z_global = 0 '\000', ref_nodel = 0 '\000', init_scanned = 0 '\000', on_fini_list = 0 '\000', dag_inited = 0 '\000', 
>   filtees_loaded = 0 '\000', irelative = 0 '\000', gnu_ifunc = 0 '\000', non_plt_gnu_ifunc = 0 '\000', crt_no_init = 0 '\000', valid_hash_sysv = 1 '\001', valid_hash_gnu = 0 '\000', 
>   dlopened = 0 '\000', marker = 0 '\000', unholdfree = 0 '\000', doomed = 0 '\000', linkmap = {l_addr = 0x410ec000 "\177ELF\001\002\001\t", l_name = 0x4103f100 "/lib/libc.so.7", l_ld = 0x412938e0, 
>     l_next = 0x103ec1c <obj_rtld+308>, l_prev = 0x41041534}, dldags = {stqh_first = 0x0, stqh_last = 0x41041748}, dagmembers = {stqh_first = 0x0, stqh_last = 0x41041750}, dev = 137, ino = 3370513, 
>   priv = 0x0}
> (gdb) c
> Continuing.
> 
> Breakpoint 2, reloc_non_plt (obj=0x41041600, obj_rtld=0xffffff50, flags=4, lockstate=0x0) at /usr/src/libexec/rtld-elf/powerpc/reloc.c:338
> 338				__syncicache(obj->relocbase + phdr->p_vaddr,
> 1: /x obj->relocbase + phdr->p_vaddr = 0x4128f9d0
> 2: /x obj->relocbase + phdr->p_vaddr + phdr->p_memsz = 0x412bdef0
> 4: *obj = {magic = 0, version = 0, next = {tqe_next = 0x0, tqe_prev = 0x41041408}, path = 0x4103f100 "/lib/libc.so.7", origin_path = 0x0, refcount = 1, holdcount = 0, dl_refcount = 0, 
>   mapbase = 0x410ec000 "\177ELF\001\002\001\t", mapsize = 1908736, textsize = 1908736, vaddrbase = 0, relocbase = 0x410ec000 "\177ELF\001\002\001\t", dynamic = 0x412938e0, 
>   entry = 0x41119d20 "\224!\377\340|\b\002\246H\027\374\001\223\301", phdr = 0x410ec034, phsize = 192, interp = 0x0, stack_flags = 6, tlsindex = 2, tlsinit = 0x4128f9d0, tlsinitsize = 2832, 
>   tlssize = 2860, tlsoffset = 8, tlsalign = 16, relro_page = 0x410ec000 "\177ELF\001\002\001\t", relro_size = 0, pltgot = 0x41299ba8, rel = 0x0, relsize = 0, rela = 0x41106530, relasize = 79800, 
>   pltrel = 0x0, pltrelsize = 0, pltrela = 0x41116d6c, pltrelasize = 12156, symtab = 0x410f12a0, strtab = 0x410fd8e0 "", strsize = 29303, verneed = 0x0, verneednum = 0, verdef = 0x41106420, 
>   verdefnum = 8, versyms = 0x41104b58, buckets = 0x410ec0fc, nbuckets = 2053, chains = 0x410ee110, nchains = 3172, nbuckets_gnu = 0, symndx_gnu = 0, maskwords_bm_gnu = 0, shift2_gnu = 0, 
>   dynsymcount = 3172, bloom_gnu = 0x0, buckets_gnu = 0x0, chain_zero_gnu = 0x0, rpath = 0x0, runpath = 0x0, needed = 0x0, needed_filtees = 0x0, needed_aux_filtees = 0x0, names = {
>     stqh_first = 0x4103f120, stqh_last = 0x4103f140}, vertab = 0x41040400, vernum = 9, init = 1091673320, fini = 1093063668, preinit_array = 0, init_array = 0, fini_array = 0, preinit_array_num = 0, 
>   init_array_num = 0, fini_array_num = 0, osrel = 0, mainprog = 0 '\000', rtld = 0 '\000', relocated = 1 '\001', ver_checked = 1 '\001', textrel = 0 '\000', symbolic = 0 '\000', bind_now = 0 '\000', 
>   traced = 0 '\000', jmpslots_done = 0 '\000', init_done = 0 '\000', tls_done = 1 '\001', phdr_alloc = 0 '\000', z_origin = 0 '\000', z_nodelete = 0 '\000', z_noopen = 0 '\000', 
>   z_loadfltr = 0 '\000', z_interpose = 0 '\000', z_nodeflib = 0 '\000', z_global = 0 '\000', ref_nodel = 0 '\000', init_scanned = 0 '\000', on_fini_list = 0 '\000', dag_inited = 0 '\000', 
>   filtees_loaded = 0 '\000', irelative = 0 '\000', gnu_ifunc = 0 '\000', non_plt_gnu_ifunc = 0 '\000', crt_no_init = 0 '\000', valid_hash_sysv = 1 '\001', valid_hash_gnu = 0 '\000', 
>   dlopened = 0 '\000', marker = 0 '\000', unholdfree = 0 '\000', doomed = 0 '\000', linkmap = {l_addr = 0x410ec000 "\177ELF\001\002\001\t", l_name = 0x4103f100 "/lib/libc.so.7", l_ld = 0x412938e0, 
>     l_next = 0x103ec1c <obj_rtld+308>, l_prev = 0x41041534}, dldags = {stqh_first = 0x0, stqh_last = 0x41041748}, dagmembers = {stqh_first = 0x0, stqh_last = 0x41041750}, dev = 137, ino = 3370513, 
>   priv = 0x0}
> 
> 
> I'm going to at least go eat before investigating more.
> 
There seems to be an issue with the direct execution mode on ppc.
Even otherwise working ld-elf.so.1 segfaults if I try to use it as
standalone binary.

But if I specify patched ld-elf.so.1 as the interpreter for some program,
using 'cc -Wl,-I,<path>/ld-elf.so.1' it works.  So I see there two bugs,
one is regression due to textsize calculation, which should be fixed by
my patch.  Another is the direct exec problem.


More information about the svn-src-head mailing list