Bug 225775 - btxld does not handle input with other than 2 PT_LOAD segments
Summary: btxld does not handle input with other than 2 PT_LOAD segments
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: Ed Maste
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-02-08 21:18 UTC by Ed Maste
Modified: 2019-05-31 08:30 UTC (History)
1 user (show)

See Also:
koobs: mfc-stable11+


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ed Maste freebsd_committer freebsd_triage 2018-02-08 21:18:53 UTC
Linking e.g. zfsloader reports (whitespace added for clarity):

cc -O2 -pipe -I/usr/home/emaste/src/freebsd-wip/stand/i386/btx/lib -nostdinc -I/usr/obj/usr/home/emaste/src/freebsd-wip/amd64.amd64/stand/libsa32 -I/usr/home/emaste/src/freebsd-wip/stand/libsa -D_STANDALONE -I/usr/home/emaste/src/freebsd-wip/sys -DLOADER_GELI_SUPPORT -I/usr/home/emaste/src/freebsd-wip/stand/geli -DLOADER_DISK_SUPPORT -m32 -mcpu=i386 -ffreestanding -mno-mmx -mno-sse -mno-avx -mno-avx2 -msoft-float -march=i386 -I. -I/usr/home/emaste/src/freebsd-wip/stand/common -I/usr/home/emaste/src/freebsd-wip/stand/ficl -I/usr/home/emaste/src/freebsd-wip/stand/ficl/i386 -I/usr/home/emaste/src/freebsd-wip/stand/common -DBF_DICTSIZE=15000 -DLOADER_UFS_SUPPORT -DLOADER_GZIP_SUPPORT -DLOADER_BZIP2_SUPPORT -DLOADER_NET_SUPPORT -DLOADER_NFS_SUPPORT -DLOADER_TFTP_SUPPORT -DLOADER_GPT_SUPPORT -DLOADER_MBR_SUPPORT -DLOADER_ZFS_SUPPORT -I/usr/home/emaste/src/freebsd-wip/stand/zfs -I/usr/home/emaste/src/freebsd-wip/sys/cddl/boot/zfs -Wall -I/usr/home/emaste/src/freebsd-wip/stand/i386 -DLOADER_PREFER_AMD64 -std=gnu99 -Wsystem-headers -Werror -Wno-pointer-sign -Wno-empty-body -Wno-string-plus-int -Wno-unused-const-variable -Wno-tautological-compare -Wno-unused-value -Wno-parentheses-equality -Wno-unused-function -Wno-enum-conversion -Wno-unused-local-typedef -Wno-address-of-packed-member -Wno-switch -Wno-switch-enum -Wno-knr-promoted-parameter -Wno-parentheses -Qunused-arguments  -nostdlib -Wl,-z,norelro -static -Ttext 0x0 -Wl,-z,norelro -o zfsloader.sym /usr/obj/usr/home/emaste/src/freebsd-wip/amd64.amd64/stand/i386/btx/lib/crt0.o main.o conf.o vers.o chain.o boot.o commands.o console.o devopen.o interp.o interp_backslash.o interp_parse.o ls.o misc.o module.o load_elf32.o load_elf32_obj.o reloc_elf32.o load_elf64.o load_elf64_obj.o reloc_elf64.o disk.o part.o dev_net.o bcache.o isapnp.o pnp.o interp_forth.o  /usr/obj/usr/home/emaste/src/freebsd-wip/amd64.amd64/stand/ficl32/libficl.a  /usr/obj/usr/home/emaste/src/freebsd-wip/amd64.amd64/stand/zfs32/libzfsboot.a /usr/obj/usr/home/emaste/src/freebsd-wip/amd64.amd64/stand/i386/libi386/libi386.a /usr/obj/usr/home/emaste/src/freebsd-wip/amd64.amd64/stand/geli/libgeliboot.a /usr/obj/usr/home/emaste/src/freebsd-wip/amd64.amd64/stand/libsa32/libsa32.a

strip -R .comment -R .note -o zfsloader.bin zfsloader.sym

btxld -v -f aout -e 0x200000 -o zfsloader -l /usr/obj/usr/home/emaste/src/freebsd-wip/amd64.amd64/stand/i386/btx/btxldr/btxldr  -b /usr/obj/usr/home/emaste/src/freebsd-wip/amd64.amd64/stand/i386/btx/btx/btx zfsloader.bin

btxld: zfsloader.bin: Warning: Ignoring extra elf PT_LOAD segments

kernel: ver=1.02 size=690 load=9000 entry=9010 map=16M pgctl=0:59
client: fmt=elf size=6bcd0 text=58834 data=afec bss=0 entry=0
output: fmt=aout size=6f000 text=1000 data=6d000 org=200000 entry=200000

btxld has:

                        case 2:
                            Warn(fname,
                                 "Ignoring extra %s PT_LOAD segments",
                                 fmtlist[fmt]);

i.e., it expects two PT_LOADs with a specific format, and just ignores the third or later ones.
Comment 1 Andriy Gapon freebsd_committer freebsd_triage 2018-02-08 23:14:03 UTC
Just curious, why the boot code may need more than two segments.
It would be interesting to see readelf or objdump output for zfsloader.bin.
Comment 2 Ed Maste freebsd_committer freebsd_triage 2018-02-09 00:05:51 UTC
It is because lld collects read-only contents into a separate segment, for example:

% readelf -l zfsloader.sym

Elf file type is EXEC (Executable file)
Entry point 0x0
There are 5 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0x00000000 0x00000000 0x58694 0x58694 R E 0x1000
  LOAD           0x05a000 0x00059000 0x00059000 0x0afcc 0x0afcc R   0x1000
  LOAD           0x065000 0x00064000 0x00064000 0x07854 0x14c9c RW  0x1000
  GNU_RELRO      0x06c000 0x0006b000 0x0006b000 0x00854 0x01000 R   0x1
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0

 Section to Segment mapping:
  Segment Sections...
   00     .text .gnu_debuglink .comment .debug_str .debug_loc .debug_abbrev .debug_info .debug_ranges .debug_macinfo .debug_pubnames .debug_pubtypes .debug_frame .debug_line .debug_aranges .symtab .shstrtab .strtab 
   01     .rodata set_Xcommand_set 
   02     .data set_Xficl_compile_set .data.rel.ro .got .bss 
   03     .data.rel.ro .got 
   04     

Linking with -z norelro leaves the three PT_LOADs, just the PT_GNU_RELRO is not emitted. From the output above btxld should coalesce two PT_LOADs, and discarding a PT_LOAD should be an error not a warning.
Comment 3 Ed Maste freebsd_committer freebsd_triage 2018-04-04 12:06:41 UTC
See https://reviews.freebsd.org/D14956, which stops lld from generating > 2 PT_LOADs. The underlying issue in btxld will still exist.

IMO we should upgrade the warning
  btxld: zfsloader.bin: Warning: Ignoring extra elf PT_LOAD segments
to an error to ensure we won't silently ignore segments in the future, and such a change is sufficient to resolve this.
Comment 4 commit-hook freebsd_committer freebsd_triage 2018-04-06 02:58:36 UTC
A commit references this bug:

Author: emaste
Date: Fri Apr  6 02:57:59 UTC 2018
New revision: 332090
URL: https://svnweb.freebsd.org/changeset/base/332090

Log:
  stand: pass --no-rosegment for i386 bits when linking with lld

  btxld does not correctly handle input with other than 2 PT_LOAD
  segments.  Passing --no-rosegment lets lld produce output eqivalent to
  ld.bfd: 2 PT_LOAD segments and no PT_GNU_RELRO.

  PR:		225775
  MFC after:	3 weeks
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D14956

Changes:
  head/stand/i386/Makefile.inc
Comment 5 commit-hook freebsd_committer freebsd_triage 2018-04-27 01:21:56 UTC
A commit references this bug:

Author: emaste
Date: Fri Apr 27 01:21:52 UTC 2018
New revision: 333048
URL: https://svnweb.freebsd.org/changeset/base/333048

Log:
  MFC r332090: stand: pass --no-rosegment for i386 bits when linking with lld

  btxld does not correctly handle input with other than 2 PT_LOAD
  segments.  Passing --no-rosegment lets lld produce output eqivalent to
  ld.bfd: 2 PT_LOAD segments and no PT_GNU_RELRO.

  PR:		225775
  Sponsored by:	The FreeBSD Foundation

Changes:
_U  stable/11/
  stable/11/stand/i386/Makefile.inc
Comment 6 Warner Losh freebsd_committer freebsd_triage 2019-01-08 19:37:24 UTC
Fix commited, closing