svn commit: r339876 - head/libexec/rtld-elf
Alexander Richardson
arichardson at freebsd.org
Tue Oct 30 15:33:00 UTC 2018
On Tue, 30 Oct 2018 at 10:17, Michael Tuexen
<Michael.Tuexen at macmic.franken.de> wrote:
>
> > On 29. Oct 2018, at 22:08, Alex Richardson <arichardson at FreeBSD.org> wrote:
> >
> > Author: arichardson
> > Date: Mon Oct 29 21:08:02 2018
> > New Revision: 339876
> > URL: https://svnweb.freebsd.org/changeset/base/339876
> >
> > Log:
> > rtld: set obj->textsize correctly
> >
> > With lld-generated binaries the first PT_LOAD will usually be a read-only
> > segment unless you pass --no-rosegment. For those binaries the textsize is
> > determined by the next PT_LOAD. To allow both LLD and bfd 2.17 binaries to
> > be parsed correctly use the end of the last PT_LOAD that is marked as
> > executable instead.
> >
> > I noticed that the value was wrong while adding some debug prints for some rtld
> > changes for CHERI binaries. `obj->textsize` only seems to be used by PPC so the
> > effect is untested. However, the value before was definitely wrong and the new
> > result matches the phdrs.
> I build kernel and world with a revision later than this on a PPC. Buildword
> ends up with a world where almost all binaries are segfaulting.... Especially gdb
> (but svn, ls or so all segfault).
>
> Best regards
> Michael
This is rather surprising since if anything the range of the icache
flush should increase rather than decrease after this change.
I can only see this causing a behaviour change if we actually need to
flush more than just the executable segments.
Is it possible that some binary/library contains a non-executable
segment as the first PT_LOAD?
Or is there some linker script that adds custom PHDRS?
Alex
> >
> > Reviewed By: kib
> > Approved By: brooks (mentor)
> > Differential Revision: https://reviews.freebsd.org/D17117
> >
> > Modified:
> > head/libexec/rtld-elf/map_object.c
> > head/libexec/rtld-elf/rtld.c
> >
> > Modified: head/libexec/rtld-elf/map_object.c
> > ==============================================================================
> > --- head/libexec/rtld-elf/map_object.c Mon Oct 29 21:03:43 2018 (r339875)
> > +++ head/libexec/rtld-elf/map_object.c Mon Oct 29 21:08:02 2018 (r339876)
> > @@ -93,6 +93,7 @@ map_object(int fd, const char *path, const struct stat
> > Elf_Addr note_end;
> > char *note_map;
> > size_t note_map_len;
> > + Elf_Addr text_end;
> >
> > hdr = get_elf_header(fd, path, sb);
> > if (hdr == NULL)
> > @@ -116,6 +117,7 @@ map_object(int fd, const char *path, const struct stat
> > note_map = NULL;
> > segs = alloca(sizeof(segs[0]) * hdr->e_phnum);
> > stack_flags = RTLD_DEFAULT_STACK_PF_EXEC | PF_R | PF_W;
> > + text_end = 0;
> > while (phdr < phlimit) {
> > switch (phdr->p_type) {
> >
> > @@ -130,6 +132,10 @@ map_object(int fd, const char *path, const struct stat
> > path, nsegs);
> > goto error;
> > }
> > + if ((segs[nsegs]->p_flags & PF_X) == PF_X) {
> > + text_end = MAX(text_end,
> > + round_page(segs[nsegs]->p_vaddr + segs[nsegs]->p_memsz));
> > + }
> > break;
> >
> > case PT_PHDR:
> > @@ -280,8 +286,7 @@ map_object(int fd, const char *path, const struct stat
> > }
> > obj->mapbase = mapbase;
> > obj->mapsize = mapsize;
> > - obj->textsize = round_page(segs[0]->p_vaddr + segs[0]->p_memsz) -
> > - base_vaddr;
> > + obj->textsize = text_end - base_vaddr;
> > obj->vaddrbase = base_vaddr;
> > obj->relocbase = mapbase - base_vaddr;
> > obj->dynamic = (const Elf_Dyn *) (obj->relocbase + phdyn->p_vaddr);
> >
> > Modified: head/libexec/rtld-elf/rtld.c
> > ==============================================================================
> > --- head/libexec/rtld-elf/rtld.c Mon Oct 29 21:03:43 2018 (r339875)
> > +++ head/libexec/rtld-elf/rtld.c Mon Oct 29 21:08:02 2018 (r339876)
> > @@ -1390,13 +1390,15 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t e
> > if (nsegs == 0) { /* First load segment */
> > obj->vaddrbase = trunc_page(ph->p_vaddr);
> > obj->mapbase = obj->vaddrbase + obj->relocbase;
> > - obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) -
> > - obj->vaddrbase;
> > } else { /* Last load segment */
> > obj->mapsize = round_page(ph->p_vaddr + ph->p_memsz) -
> > obj->vaddrbase;
> > }
> > nsegs++;
> > + if ((ph->p_flags & PF_X) == PF_X) {
> > + obj->textsize = MAX(obj->textsize,
> > + round_page(ph->p_vaddr + ph->p_memsz) - obj->vaddrbase);
> > + }
> > break;
> >
> > case PT_DYNAMIC:
> >
>
More information about the svn-src-head
mailing list