Bug 4499

Summary: assign file positions assumes segment offsets increasing
Product: binutils Reporter: Alan Modra <amodra>
Component: binutilsAssignee: Alan Modra <amodra>
Status: RESOLVED FIXED    
Severity: enhancement CC: bug-binutils
Priority: P2    
Version: 2.18   
Target Milestone: 2.34   
Host: Target:
Build: Last reconfirmed:
Bug Depends on: 25585    
Bug Blocks:    
Attachments: testcase

Description Alan Modra 2007-05-13 13:52:14 UTC
strip causes these warnings:

>BFD: test2: section .dynstr lma 0x804a62c overlaps previous sections
>BFD: test2: section .interp lma 0x8048114 overlaps previous sections
>BFD: test2: section .note.ABI-tag lma 0x8048128 overlaps previous sections
>BFD: test2: section .hash lma 0x8048148 overlaps previous sections
>BFD: test2: section .dynsym lma 0x804816c overlaps previous sections
>BFD: test2: section .olddynstr lma 0x80481ac overlaps previous sections
>BFD: test2: section .gnu.version lma 0x80481f2 overlaps previous sections
>BFD: test2: section .gnu.version_r lma 0x80481fc overlaps previous sections
>BFD: test2: section .rel.dyn lma 0x804821c overlaps previous sections
>BFD: test2: section .rel.plt lma 0x8048224 overlaps previous sections
>BFD: test2: section .init lma 0x8048234 overlaps previous sections
>BFD: test2: section .plt lma 0x804824c overlaps previous sections
>BFD: test2: section .text lma 0x8048280 overlaps previous sections
>BFD: test2: section .fini lma 0x8048404 overlaps previous sections
>BFD: test2: section .rodata lma 0x8048420 overlaps previous sections
>BFD: test2: section .eh_frame lma 0x8048428 overlaps previous sections
Comment 1 Alan Modra 2007-05-13 13:53:00 UTC
Created attachment 1833 [details]
testcase
Comment 2 Alan Modra 2007-05-13 14:04:30 UTC
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x00052c 0x0804a52c 0x0804a52c 0x00100 0x00100 R   0x4
  INTERP         0x000114 0x08048114 0x08048114 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x00052c 0x0804a52c 0x0804a52c 0x0014a 0x0014a R   0x1000
  LOAD           0x00042c 0x0804942c 0x0804942c 0x00100 0x00104 RW  0x1000
  DYNAMIC        0x000440 0x08049440 0x08049440 0x000c8 0x000c8 RW  0x4
  NOTE           0x000128 0x08048128 0x08048128 0x00020 0x00020 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
  LOAD           0x000000 0x08048000 0x08048000 0x0042c 0x0042c R E 0x1000

The basic problem here is that bfd can't cope with load segments that don't have
  increasing file offset.

What's more the first load segment contains the program headers, which tricks
these lines in elf.c
	  adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
	  off += adjust;
We ought to be using the phdr vma rather than m->sections[0]->vma in this case.
Comment 3 Quentin Godfroy 2007-05-13 18:01:43 UTC
>The basic problem here is that bfd can't cope with load segments that don't have
> increasing file offset.

I had to trick the linux kernel which also has problems to handle PT_PHDR
segments not in the first load, but even with the PT_LOAD segments in the good
order (that is sorted by p_vaddr as the norm requires), strip destroys the
executable.
Comment 4 Sourceware Commits 2019-10-25 04:50:10 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=30fe183248b2523ecff9da36853e2f893c4c4b91

commit 30fe183248b2523ecff9da36853e2f893c4c4b91
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Oct 23 17:40:51 2019 +1030

    PR4499, assign file positions assumes segment offsets increasing
    
    This rewrites much of assign_file_positions_for_non_load_sections to
    allow objcopy and strip to handle cases like that in PR4499 where
    program headers were not in their usual position immediately after the
    ELF file header, and PT_LOAD headers were not sorted by paddr.
    
    	PR 4499
    include/
    	* elf/internal.h (struct elf_segment_map): Delete header_size.
    	Add no_sort_lma and idx.
    bfd/
    	* elf-nacl.c (nacl_modify_segment_map): Set no_sort_lma for all
    	PT_LOAD segments.
    	* elf32-spu.c (spu_elf_modify_segment_map): Likewise on overlay
    	PT_LOAD segments.
    	* elf.c (elf_sort_segments): New function.
    	(assign_file_positions_except_relocs): Use shortcuts to elfheader
    	and elf_tdata.  Seek to e_phoff not sizeof_ehdr to write program
    	headers.  Move PT_PHDR check..
    	(assign_file_positions_for_non_load_sections): ..and code setting
    	PT_PHDR p_vaddr and p_paddr, and code setting __ehdr_start value..
    	(assign_file_positions_for_load_sections): ..to here.  Sort
    	PT_LOAD headers.  Delete header_pad code.  Use actual number of
    	headers rather than allocated in calculating size for program
    	headers.  Don't assume program headers follow ELF file header.
    	Simplify pt_load_count code.  Only set "off" for PT_LOAD or
    	PT_NOTE in cores.
    	(rewrite_elf_program_header): Set p_vaddr_offset for segments
    	that include file and program headers.
    	(copy_elf_program_header): Likewise, replacing header_size code.
Comment 5 Alan Modra 2019-10-25 05:18:36 UTC
Fixed.