Problem with objcopy phdrs and patch

David Heine dlheine@tensilica.com
Wed May 5 19:01:00 GMT 2004


I've run into problems with objcopy mapping PHDRS into a segment from a 
file that did not originally map PHDRS into a segment.  This only occurs 
when removing the last section from an object file on configurations 
with small MAXPAGESIZE.

I tracked the problem down to a FIXME in elf.c:5241
         /* Only set up the segments if there are no more SEC_ALLOC
            sections.  FIXME: This won't do the right thing if objcopy is
            used to remove the last SEC_ALLOC section, since objcopy
            won't call this routine in that case.  */

The problem is that the PHDRS are not copied from the input file, and 
when they are recreated, the default algorithm that regenerates the 
segments can map the FILEHDR and PHDRS into the first segment.

I was hoping to be able to reuse the "bfd_copy_private_bfd_data" hook to 
be able to copy PHDRS.  However, the PHDRs must be set up before setting 
section content and objcopy calls "bfd_copy_private_bfd_data" late (ref 
objcopy.c:1485).
    /* Allow the BFD backend to copy any private data it understands
      from the input BFD to the output BFD.  This is done last to
      permit the routine to look at the filtered symbol table, which is
      important for the ECOFF code at least.  */

I'm proposing a new bfd interface "bfd_copy_private_header_data" that 
should be called after setting up section data for each of the sections 
that will copy over phdr data.  I'm including a proposed patch for 
binutils and bfd and a Changelog for each.

I did not see a mechanism in the binutils testsuite to cleanly call the 
gnu linker, so I'm including a manual testcase to demonstrate the 
failure.  Use an elf target with small page sizes like avr-elf.
 > cat simple.s
         .section .first_data, "a"
         .p2align 2
         .word 0x1000
         .section .second_data, "a"
         .p2align 2
         .word 0x2000
 > cat simple.t
MEMORY {  MEM : ORIGIN = 0x40000000, LENGTH = 0x5000 }
PHDRS {  P1 PT_LOAD; }
SECTIONS {
   .text : { *(.literal .text) } > MEM : P1
   .data : { *(.data) } > MEM : P1
   .bss : { *(.bss) } > MEM : P1
   .first_data : { *(.first_data) } > MEM :P1
   .second_data : { *(.second_data) } > MEM :P1
}

 > as -o simple.o simple.s
 > ld -T simple.t -o simple.exe simple.o
 > objcopy -j .first_data simple.exe simple-first.bfd
 > objdump -p simple-first.bfd | grep "LOAD off.*0x00000000"

On failure, this will generate one line indicating the first  PHDR that 
maps FILEHDR and PHDR in the first segment at a virtual address just 
before the defined MEM address. It passes if no line is generated.




binutils ChangeLog

2004-05-05  David Heine  <dlheine@tensilica.com>

     * objcopy.c (setup_bfd_headers): New function.
     (copy_object): Call setup_bfd_headers.


bfd ChangeLog

2004-05-05  David Heine  <dlheine@tensilica.com>

     * bfd.c (bfd_copy_private_header_data): Define.
     * elf-bfd.h (_bfd_elf_copy_private_header_data): Declare.
     * elf.c (_bfd_elf_copy_private_section_data): Remove code to set up
     segments by calling copy_private_bfd_data.
     (_bfd_elf_copy_private_header_data): Define.
     * elf-xxtarget.h (bfd_elfNN_bfd_copy_private_header_data): Define.
     * libbfd-in.h (_bfd_generic_bfd_copy_private_header_data): Define.
     * targets.c (BFD_JUMP_TABLE_COPY): Add
     _bfd_copy_private_header_data.
     * bfd-in2.h: Regenerate.
     * libbfd.h: Regenerate.



More information about the Binutils mailing list