This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
fix strip & objcopy bug with foreign linker
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: binutils <binutils at sources dot redhat dot com>
- Date: Tue, 11 Nov 2008 17:22:38 +0000
- Subject: 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;