This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

fix strip & objcopy bug with foreign linker


This patch fixes a problem encountered with stripping vxworks RTPs generated by
the Diab linker.

Diab places padding after the program headers before the first section in a
loadable segment.  We were failing to maintain this padding, resulting in the
following change to an executable upon stripping:

before:
   Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
   PHDR           0x000034 0x10000034 0x00000000 0x00080 0x00080 R   0x4
   LOAD           0x000000 0x10000000 0x00000000 0x09404 0x09404 R E 0x1
   LOAD           0x009404 0x1000a404 0x00000000 0x00174 0x004e8 RW  0x1
   DYNAMIC        0x009404 0x1000a404 0x00000000 0x00088 0x00088 R   0x4

after:
   Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
   PHDR           0x000034 0x10000040 0x10000040 0x00080 0x00080 R   0x4
   LOAD           0x000000 0x1000000c 0x1000000c 0x093f8 0x093f8 R E 0x1
   LOAD           0x0093f8 0x1000a404 0x1000a404 0x00174 0x004e8 RW  0x1
   DYNAMIC        0x0093f8 0x1000a404 0x1000a404 0x00088 0x00088 R   0x4

You can see that the first loadable segment is still at file offset zero, but is
now loaded at address 0x1000000c.  So the file header is loaded 12 bytes further
on than expected.

The rtp loader is now setting an absolute symbol at the file-header's load
address, and expects strip to not break that.

This patch determines the space used for file and program headers in the input
file, and then uses this to create the same space in the output file.  If that's
insufficient we'll get the same kind of error as we currently get -- no changes
are necessary.  With this patch, the stripped segments become:

   Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
   PHDR           0x000034 0x10000034 0x10000034 0x00080 0x00080 R   0x4
   LOAD           0x000000 0x10000000 0x10000000 0x09404 0x09404 R E 0x1
   LOAD           0x009404 0x1000a404 0x1000a404 0x00174 0x004e8 RW  0x1
   DYNAMIC        0x009404 0x1000a404 0x1000a404 0x00088 0x00088 R   0x4

which as you can see is the same as the original file.

tested with powerpc-elf and i686-pc-linux-gnu. ok?

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::         CodeSourcery


2008-11-11  Nathan Sidwell  <nathan@codesourcery.com>

	bfd/
	* elf.c (assign_file_positions_for_load_sections): Use header_size
	to avoid moving the load address of file headers.
	(assign_file_positions_for_load_sections): Set header_size for
	segments containing the file header.

	include/elf/
	* internal.h (struct elf_segment_map): Add header_size field.
 
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.468
diff -c -3 -p -r1.468 elf.c
*** bfd/elf.c	11 Nov 2008 04:26:13 -0000	1.468
--- bfd/elf.c	11 Nov 2008 17:19:26 -0000
*************** assign_file_positions_for_load_sections 
*** 4156,4161 ****
--- 4156,4162 ----
    bfd_size_type maxpagesize;
    unsigned int alloc;
    unsigned int i, j;
+   bfd_vma header_pad = 0;
  
    if (link_info == NULL
        && !_bfd_elf_map_sections_to_segments (abfd, link_info))
*************** assign_file_positions_for_load_sections 
*** 4163,4169 ****
  
    alloc = 0;
    for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
!     ++alloc;
  
    elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
    elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
--- 4164,4174 ----
  
    alloc = 0;
    for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
!     {
!       ++alloc;
!       if (m->header_size)
! 	header_pad = m->header_size;
!     }
  
    elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
    elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
*************** assign_file_positions_for_load_sections 
*** 4192,4197 ****
--- 4197,4207 ----
  
    off = bed->s->sizeof_ehdr;
    off += alloc * bed->s->sizeof_phdr;
+   if (header_pad < off)
+     header_pad = 0;
+   else
+     header_pad -= off;
+   off += header_pad;
  
    for (m = elf_tdata (abfd)->segment_map, p = phdrs, j = 0;
         m != NULL;
*************** assign_file_positions_for_load_sections 
*** 4379,4384 ****
--- 4389,4399 ----
  
  	  p->p_filesz += alloc * bed->s->sizeof_phdr;
  	  p->p_memsz += alloc * bed->s->sizeof_phdr;
+ 	  if (m->count)
+ 	    {
+ 	      p->p_filesz += header_pad;
+ 	      p->p_memsz += header_pad;
+ 	    }
  	}
  
        if (p->p_type == PT_LOAD
*************** copy_elf_program_header (bfd *ibfd, bfd 
*** 5861,5866 ****
--- 5878,5887 ----
  	    phdr_included = TRUE;
  	}
  
+       if (map->includes_filehdr && first_section)
+ 	/* We need to keep the space used by the headers fixed.  */
+ 	map->header_size = first_section->vma - segment->p_vaddr;
+       
        if (!map->includes_phdrs
  	  && !map->includes_filehdr
  	  && map->p_paddr_valid)
Index: include/elf/internal.h
===================================================================
RCS file: /cvs/src/src/include/elf/internal.h,v
retrieving revision 1.21
diff -c -3 -p -r1.21 internal.h
*** include/elf/internal.h	13 Mar 2008 05:27:41 -0000	1.21
--- include/elf/internal.h	11 Nov 2008 17:19:32 -0000
*************** struct elf_segment_map
*** 266,271 ****
--- 266,273 ----
    bfd_vma p_align;
    /* Segment size in file and memory */
    bfd_vma p_size;
+   /* Required size of filehdr + phdrs, if non-zero */
+   bfd_vma header_size;
    /* Whether the p_flags field is valid; if not, the flags are based
       on the section flags.  */
    unsigned int p_flags_valid : 1;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]