svn commit: r339876 - head/libexec/rtld-elf
Mark Millard
marklmi26-fbsd at yahoo.com
Tue Oct 30 22:15:58 UTC 2018
On 2018-Oct-30, at 2:40 PM, Alexander Richardson <arichardson at freebsd.org> wrote:
> On Tue, 30 Oct 2018 at 21:32, Mark Millard <marklmi26-fbsd at yahoo.com> wrote:
>>
>>
>>
>> On 2018-Oct-30, at 2:23 PM, Alexander Richardson <arichardson at freebsd.org> wrote:
>>
>>> On Tue, 30 Oct 2018 at 18:19, Mark Millard <marklmi26-fbsd at yahoo.com> wrote:
>>>>
>>>> Alexander Richardson arichardson at freebsd.org wrote on
>>>> 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?
>>>>
>>>> The following is based on using devel/powerpc64-xtoolchain-gcc
>>>> to buildworld buildkernel on/for powerpc64. (I experiment with
>>>> using fairly modern tools to target powerpc64 and powerpc.)
>>>> The build context is head -r339076 based, both for what
>>>> did the build and for what it was building.
>>>>
>>>> I report from both elfdump and objdump output
>>>> because each seems to have some oddities in what
>>>> it outputs.
>>>>
>>>> I start with elfdump (which leaves sh_flags blank
>>>> and shows a section header with sh_name empty
>>>> that objdump does not list at all):
>>>>
>>>> # elfdump -pc /bin/ls | less
>>>>
>>>> . . .
>>>>
>>>> As for objdump on the same file (section
>>>> one less than elfdump listed, no empty sh_name
>>>> section listed):
>>>>
>>>> # objdump -ph /bin/ls | less
>>>>
>>>> /bin/ls: file format elf64-powerpc-freebsd
>>>>
>>>> Program Header:
>>>> PHDR off 0x0000000000000040 vaddr 0x0000000010000040 paddr 0x0000000010000040 align 2**3
>>>> filesz 0x0000000000000188 memsz 0x0000000000000188 flags r--
>>>> INTERP off 0x00000000000001c8 vaddr 0x00000000100001c8 paddr 0x00000000100001c8 align 2**0
>>>> filesz 0x0000000000000015 memsz 0x0000000000000015 flags r--
>>>> LOAD off 0x0000000000000000 vaddr 0x0000000010000000 paddr 0x0000000010000000 align 2**16
>>>> filesz 0x000000000000910c memsz 0x000000000000910c flags r-x
>>>> LOAD off 0x0000000000009110 vaddr 0x0000000010019110 paddr 0x0000000010019110 align 2**16
>>>> filesz 0x0000000000000ee0 memsz 0x00000000000010e8 flags rw-
>>>> DYNAMIC off 0x0000000000009138 vaddr 0x0000000010019138 paddr 0x0000000010019138 align 2**3
>>>> filesz 0x00000000000001c0 memsz 0x00000000000001c0 flags rw-
>>>> NOTE off 0x00000000000001e0 vaddr 0x00000000100001e0 paddr 0x00000000100001e0 align 2**2
>>>> filesz 0x0000000000000030 memsz 0x0000000000000030 flags r--
>>>> STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
>>>> filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
>>>>
>>>> Dynamic Section:
>>>> NEEDED libutil.so.9
>>>> NEEDED libncursesw.so.8
>>>> NEEDED libc.so.7
>>>> INIT 0x0000000010019328
>>>> FINI 0x0000000010019340
>>>> HASH 0x0000000010000210
>>>> STRTAB 0x0000000010000d00
>>>> SYMTAB 0x0000000010000490
>>>> STRSZ 0x000000000000035a
>>>> SYMENT 0x0000000000000018
>>>> DEBUG 0x0000000000000000
>>>> PLTGOT 0x0000000010019898
>>>> PLTRELSZ 0x00000000000006f0
>>>> PLTREL 0x0000000000000007
>>>> JMPREL 0x00000000100012f8
>>>> 0x70000000 0x00000000100089b4
>>>> RELA 0x0000000010001160
>>>> RELASZ 0x0000000000000198
>>>> RELAENT 0x0000000000000018
>>>> VERNEED 0x0000000010001110
>>>> VERNEEDNUM 0x0000000000000001
>>>> VERSYM 0x000000001000105a
>>>>
>>>> Version References:
>>>> required from libc.so.7:
>>>> 0x077a28b3 0x00 05 FBSD_1.3
>>>> 0x077a28b1 0x00 04 FBSD_1.1
>>>> 0x077a28b5 0x00 03 FBSD_1.5
>>>> 0x077a28b0 0x00 02 FBSD_1.0
>>>> private flags = 0x1: [abiv1]
>>>>
>>>> Sections:
>>>> Idx Name Size VMA LMA File off Algn
>>>> 0 .interp 00000015 00000000100001c8 00000000100001c8 000001c8 2**0
>>>> CONTENTS, ALLOC, LOAD, READONLY, DATA
>>>> 1 .note.tag 00000030 00000000100001e0 00000000100001e0 000001e0 2**2
>>>> CONTENTS, ALLOC, LOAD, READONLY, DATA
>>>> 2 .hash 0000027c 0000000010000210 0000000010000210 00000210 2**3
>>>> CONTENTS, ALLOC, LOAD, READONLY, DATA
>>>> 3 .dynsym 00000870 0000000010000490 0000000010000490 00000490 2**3
>>>> CONTENTS, ALLOC, LOAD, READONLY, DATA
>>>> 4 .dynstr 0000035a 0000000010000d00 0000000010000d00 00000d00 2**0
>>>> CONTENTS, ALLOC, LOAD, READONLY, DATA
>>>> 5 .gnu.version 000000b4 000000001000105a 000000001000105a 0000105a 2**1
>>>> CONTENTS, ALLOC, LOAD, READONLY, DATA
>>>> 6 .gnu.version_r 00000050 0000000010001110 0000000010001110 00001110 2**3
>>>> CONTENTS, ALLOC, LOAD, READONLY, DATA
>>>> 7 .rela.dyn 00000198 0000000010001160 0000000010001160 00001160 2**3
>>>> CONTENTS, ALLOC, LOAD, READONLY, DATA
>>>> 8 .rela.plt 000006f0 00000000100012f8 00000000100012f8 000012f8 2**3
>>>> CONTENTS, ALLOC, LOAD, READONLY, DATA
>>>> 9 .init 0000002c 00000000100019f0 00000000100019f0 000019f0 2**4
>>>> CONTENTS, ALLOC, LOAD, READONLY, CODE
>>>> 10 .text 00007204 0000000010001a20 0000000010001a20 00001a20 2**5
>>>> CONTENTS, ALLOC, LOAD, READONLY, CODE
>>>> 11 .fini 00000024 0000000010008c30 0000000010008c30 00008c30 2**4
>>>> CONTENTS, ALLOC, LOAD, READONLY, CODE
>>>> 12 .rodata 000004b0 0000000010008c58 0000000010008c58 00008c58 2**3
>>>> CONTENTS, ALLOC, LOAD, READONLY, DATA
>>>> 13 .eh_frame 00000004 0000000010009108 0000000010009108 00009108 2**2
>>>> CONTENTS, ALLOC, LOAD, READONLY, DATA
>>>> 14 .ctors 00000010 0000000010019110 0000000010019110 00009110 2**3
>>>> CONTENTS, ALLOC, LOAD, DATA
>>>> 15 .dtors 00000010 0000000010019120 0000000010019120 00009120 2**3
>>>> CONTENTS, ALLOC, LOAD, DATA
>>>> 16 .jcr 00000008 0000000010019130 0000000010019130 00009130 2**3
>>>> CONTENTS, ALLOC, LOAD, DATA
>>>> 17 .dynamic 000001c0 0000000010019138 0000000010019138 00009138 2**3
>>>> CONTENTS, ALLOC, LOAD, DATA
>>>> 18 .opd 00000468 00000000100192f8 00000000100192f8 000092f8 2**3
>>>> CONTENTS, ALLOC, LOAD, DATA
>>>> 19 .got 00000098 0000000010019800 0000000010019800 00009800 2**8
>>>> CONTENTS, ALLOC, LOAD, DATA
>>>> 20 .plt 00000708 0000000010019898 0000000010019898 00009898 2**3
>>>> ALLOC
>>>> 21 .data 00000050 0000000010019fa0 0000000010019fa0 00009fa0 2**3
>>>> CONTENTS, ALLOC, LOAD, DATA
>>>> 22 .bss 00000208 0000000010019ff0 0000000010019ff0 00009ff0 2**3
>>>> ALLOC
>>>> 23 .comment 000002b5 0000000000000000 0000000000000000 00009ff0 2**0
>>>> CONTENTS, READONLY
>>>> 24 .gnu_debuglink 00000010 0000000000000000 0000000000000000 0000a2a8 2**2
>>>> CONTENTS, READONLY
>>>>
>>>>
>>>
>>> The first PT_LOAD is also executable so there will be no be behaviour
>>> change. It must be one of the library dependencies that is different.
>>> The difference in section headers output doesn't matter here since all
>>> that RTLD looks at is the PHDRS.
>>>
>>
>> I think you missed the fact that the .got and .plt are in the
>> material from the 2nd PT_LOAD: there are writeable code areas
>> involved for powerpc64.
>>
>> So both PT_LOAD's contribute code areas and there is a space
>> between the two contributions. The first PT_LOAD loads most
>> code (the readonly code, to be specific). The 2nd contributes
>> a writable-code area.
>>
>> But may be i've misunderstood the assumptions that your change
>> is based on.
>
> Before my change the second PT would also not be included in
> obj->textsize since we were setting obj->textsize as end of
> PT_LOAD[0].
> After the change it will be end of last executable PT_LOAD (which will
> usually be PT_LOAD[0] but could also include more now).
> Since there is only one executable PT_LOAD which happens to be also be
> PT_LOAD[0], there will be no change to obj->textsize.
>
> The only time this commit could change anything is if there is a
> PT_LOAD that is executable but is not PT_LOAD[0] or if PT_LOAD[0] is
> not executable.
> I think it must be the former case since as far as I know ld.bfd will
> always create a read/execute segment as PT_LOAD[0] unless it is given
> a custom linker script.
I do not see any evidence that PF_X would match the tests for either
of the following from the 2nd PT_LOAD:
19 .got 00000098 0000000010019800 0000000010019800 00009800 2**8
CONTENTS, ALLOC, LOAD, DATA
20 .plt 00000708 0000000010019898 0000000010019898 00009898 2**3
ALLOC
in the likes of:
135 if ((segs[nsegs]->p_flags & PF_X) == PF_X) {
136 text_end = MAX(text_end,
137 round_page(segs[nsegs]->p_vaddr + segs[nsegs]->p_memsz));
138 }
in map_object.c
This is possibly to avoid:
467 if (elfflags & PF_X)
468 prot |= PROT_EXEC;
because of writable code.
rtld.c also, for:
1397 nsegs++;
1398 if ((ph->p_flags & PF_X) == PF_X) {
1399 obj->textsize = MAX(obj->textsize,
1400 round_page(ph->p_vaddr + ph->p_memsz) - obj->vaddrbase);
1401 }
Still, I may be missing something in my understanding.
===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)
More information about the svn-src-head
mailing list