This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH: Preserve ELF program header
- From: "H. J. Lu" <hjl at lucon dot org>
- To: binutils at sources dot redhat dot com
- Date: Thu, 25 May 2006 14:44:16 -0700
- Subject: PATCH: Preserve ELF program header
When an ELF executable/shared object is created with different
maximum page size, strip may change ELF program header if it uses
different maximum page size. This patch preserves ELF program header
when copying executable/shared object.
H.J.
----
bfd/
2006-05-25 H.J. Lu <hongjiu.lu@intel.com>
* elf.c (assign_file_positions_for_load_sections): Set
p->p_vaddr with m->p_vaddr if it is valid. Set p->p_align with
m->p_align if it is valid. Adjust p->p_vaddr only if m->p_vaddr
isn't valid.
(copy_elf_program_header): Copy p_vaddr and p_align. Set
p_vaddr_valid and p_align_valid to 1.
include/elf/
2006-05-25 H.J. Lu <hongjiu.lu@intel.com>
* internal.h (elf_segment_map): Add p_vaddr, p_align,
p_vaddr_valid and p_align_valid.
--- binutils/bfd/elf.c.pagesize 2006-05-22 12:36:40.000000000 -0700
+++ binutils/bfd/elf.c 2006-05-22 16:24:05.000000000 -0700
@@ -4292,7 +4292,9 @@ assign_file_positions_for_load_sections
return FALSE;
}
- if (m->count == 0)
+ if (m->p_vaddr_valid)
+ p->p_vaddr = m->p_vaddr;
+ else if (m->count == 0)
p->p_vaddr = 0;
else
p->p_vaddr = m->sections[0]->vma;
@@ -4304,7 +4306,9 @@ assign_file_positions_for_load_sections
else
p->p_paddr = m->sections[0]->lma;
- if (p->p_type == PT_LOAD
+ if (m->p_align_valid)
+ p->p_align = m->p_align;
+ else if (p->p_type == PT_LOAD
&& (abfd->flags & D_PAGED) != 0)
p->p_align = bed->maxpagesize;
else if (m->count == 0)
@@ -4327,16 +4331,18 @@ assign_file_positions_for_load_sections
{
BFD_ASSERT (p->p_type == PT_LOAD);
- if (p->p_vaddr < (bfd_vma) off)
+ if (!m->p_vaddr_valid)
{
- (*_bfd_error_handler)
- (_("%B: Not enough room for program headers, try linking with -N"),
- abfd);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ if (p->p_vaddr < (bfd_vma) off)
+ {
+ (*_bfd_error_handler)
+ (_("%B: Not enough room for program headers, try linking with -N"),
+ abfd);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ p->p_vaddr -= off;
}
-
- p->p_vaddr -= off;
if (! m->p_paddr_valid)
p->p_paddr -= off;
}
@@ -5805,6 +5811,10 @@ copy_elf_program_header (bfd *ibfd, bfd
map->p_flags_valid = 1;
map->p_paddr = segment->p_paddr;
map->p_paddr_valid = 1;
+ map->p_vaddr = segment->p_vaddr;
+ map->p_vaddr_valid = 1;
+ map->p_align = segment->p_align;
+ map->p_align_valid = 1;
/* Determine if this segment contains the ELF file header
and if it contains the program headers themselves. */
--- binutils/include/elf/internal.h 2006-05-22 12:47:06.000000000 -0700
+++ binutils/include/elf/internal.h 2006-05-22 12:47:06.000000000 -0700
@@ -235,12 +235,22 @@ struct elf_segment_map
unsigned long p_flags;
/* Program segment physical address. */
bfd_vma p_paddr;
+ /* Program segment virtual address. */
+ bfd_vma p_vaddr;
+ /* Program segment alignment. */
+ bfd_vma p_align;
/* Whether the p_flags field is valid; if not, the flags are based
on the section flags. */
unsigned int p_flags_valid : 1;
/* Whether the p_paddr field is valid; if not, the physical address
is based on the section lma values. */
unsigned int p_paddr_valid : 1;
+ /* Whether the p_vaddr field is valid; if not, the virtual address
+ is based on the section vma values. */
+ unsigned int p_vaddr_valid : 1;
+ /* Whether the p_align field is valid; if not, the segment alignment
+ is based on the default maximum page size. */
+ unsigned int p_align_valid : 1;
/* Whether this segment includes the file header. */
unsigned int includes_filehdr : 1;
/* Whether this segment includes the program headers. */