* PATCH: Preserve ELF program header
@ 2006-05-26 3:05 H. J. Lu
2006-05-26 14:00 ` Alan Modra
0 siblings, 1 reply; 6+ messages in thread
From: H. J. Lu @ 2006-05-26 3:05 UTC (permalink / raw)
To: binutils
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. */
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PATCH: Preserve ELF program header
2006-05-26 3:05 PATCH: Preserve ELF program header H. J. Lu
@ 2006-05-26 14:00 ` Alan Modra
2006-05-26 17:28 ` H. J. Lu
0 siblings, 1 reply; 6+ messages in thread
From: Alan Modra @ 2006-05-26 14:00 UTC (permalink / raw)
To: H. J. Lu; +Cc: binutils
On Thu, May 25, 2006 at 02:44:16PM -0700, H. J. Lu wrote:
> --- 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;
I don't see the need for m->p_vaddr and m->p_vaddr_valid. How can you
get into a situation where m->sections[0]->vma or 0 is not the right
initialisation for p->p_vaddr?
--
Alan Modra
IBM OzLabs - Linux Technology Centre
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PATCH: Preserve ELF program header
2006-05-26 14:00 ` Alan Modra
@ 2006-05-26 17:28 ` H. J. Lu
2006-05-27 16:23 ` Alan Modra
0 siblings, 1 reply; 6+ messages in thread
From: H. J. Lu @ 2006-05-26 17:28 UTC (permalink / raw)
To: binutils
On Fri, May 26, 2006 at 10:21:00AM +0930, Alan Modra wrote:
> On Thu, May 25, 2006 at 02:44:16PM -0700, H. J. Lu wrote:
> > --- 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;
>
> I don't see the need for m->p_vaddr and m->p_vaddr_valid. How can you
> get into a situation where m->sections[0]->vma or 0 is not the right
> initialisation for p->p_vaddr?
>
Here is an x86 example, which is generated with 2MB maximum page size.
Due to
TEXT_START_ADDR=0x08048000
We got p->p_vaddr != m->sections[0]->vma to satisfy 2MB alignment.
H.J.
---
There are 6 section headers, starting at offset 0x480a4:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 08048074 048074 000004 00 AX 0 0 4
[ 2] .data PROGBITS 08248078 048078 000004 00 WA 0 0 4
[ 3] .shstrtab STRTAB 00000000 04807c 000027 00 0 0 1
[ 4] .symtab SYMTAB 00000000 048194 0000a0 10 5 6 4
[ 5] .strtab STRTAB 00000000 048234 000020 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Elf file type is EXEC (Executable file)
Entry point 0x8048074
There are 2 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08000000 0x08000000 0x48078 0x48078 R E 0x200000
LOAD 0x048078 0x08248078 0x08248078 0x00004 0x00004 RW 0x200000
Section to Segment mapping:
Segment Sections...
00 .text
01 .data
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PATCH: Preserve ELF program header
2006-05-26 17:28 ` H. J. Lu
@ 2006-05-27 16:23 ` Alan Modra
2006-05-27 16:23 ` H. J. Lu
0 siblings, 1 reply; 6+ messages in thread
From: Alan Modra @ 2006-05-27 16:23 UTC (permalink / raw)
To: H. J. Lu; +Cc: binutils
On Thu, May 25, 2006 at 07:30:23PM -0700, H. J. Lu wrote:
> On Fri, May 26, 2006 at 10:21:00AM +0930, Alan Modra wrote:
> > I don't see the need for m->p_vaddr and m->p_vaddr_valid. How can you
> > get into a situation where m->sections[0]->vma or 0 is not the right
> > initialisation for p->p_vaddr?
> >
>
> Here is an x86 example, which is generated with 2MB maximum page size.
> Due to
>
> TEXT_START_ADDR=0x08048000
>
> We got p->p_vaddr != m->sections[0]->vma to satisfy 2MB alignment.
Sure. Obviously you need to subtract off space for the headers then
align. I'm thinking that you can do this by modifying the assignments
to "align" in the function, particularly places that set "align" from
"bed->maxpagesize" to instead use your m->p_align. After all, the
problem you are trying to solve is one where alignment due to
bed->maxpagesize changes.
--
Alan Modra
IBM OzLabs - Linux Technology Centre
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PATCH: Preserve ELF program header
2006-05-27 16:23 ` Alan Modra
@ 2006-05-27 16:23 ` H. J. Lu
2006-05-27 16:33 ` Alan Modra
0 siblings, 1 reply; 6+ messages in thread
From: H. J. Lu @ 2006-05-27 16:23 UTC (permalink / raw)
To: binutils
On Fri, May 26, 2006 at 01:19:21PM +0930, Alan Modra wrote:
> On Thu, May 25, 2006 at 07:30:23PM -0700, H. J. Lu wrote:
> > On Fri, May 26, 2006 at 10:21:00AM +0930, Alan Modra wrote:
> > > I don't see the need for m->p_vaddr and m->p_vaddr_valid. How can you
> > > get into a situation where m->sections[0]->vma or 0 is not the right
> > > initialisation for p->p_vaddr?
> > >
> >
> > Here is an x86 example, which is generated with 2MB maximum page size.
> > Due to
> >
> > TEXT_START_ADDR=0x08048000
> >
> > We got p->p_vaddr != m->sections[0]->vma to satisfy 2MB alignment.
>
> Sure. Obviously you need to subtract off space for the headers then
> align. I'm thinking that you can do this by modifying the assignments
> to "align" in the function, particularly places that set "align" from
> "bed->maxpagesize" to instead use your m->p_align. After all, the
> problem you are trying to solve is one where alignment due to
> bed->maxpagesize changes.
>
Here is the updated patch.
H.J.
----
bfd/
2006-05-25 H.J. Lu <hongjiu.lu@intel.com>
* elf.c (assign_file_positions_for_load_sections): Align
segment and set p->p_align with m->p_align if it is valid.
(copy_elf_program_header): Copy p_align. Set p_align_valid to 1.
include/elf/
2006-05-25 H.J. Lu <hongjiu.lu@intel.com>
* internal.h (elf_segment_map): Add p_align and p_align_valid.
--- binutils/bfd/elf.c.phdr 2006-05-25 21:11:34.000000000 -0700
+++ binutils/bfd/elf.c 2006-05-25 21:26:44.000000000 -0700
@@ -4244,8 +4244,13 @@ assign_file_positions_for_load_sections
}
align = (bfd_size_type) 1 << align_power;
- if ((abfd->flags & D_PAGED) != 0 && bed->maxpagesize > align)
- align = bed->maxpagesize;
+ if ((abfd->flags & D_PAGED) != 0)
+ {
+ if (m->p_align_valid)
+ align = m->p_align;
+ else if (bed->maxpagesize > align)
+ align = bed->maxpagesize;
+ }
adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
off += adjust;
@@ -4298,7 +4303,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)
@@ -5800,6 +5807,8 @@ 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_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.phdr 2006-02-10 08:59:44.000000000 -0800
+++ binutils/include/elf/internal.h 2006-05-25 21:22:19.000000000 -0700
@@ -235,12 +235,17 @@ struct elf_segment_map
unsigned long p_flags;
/* Program segment physical address. */
bfd_vma p_paddr;
+ /* 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_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. */
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PATCH: Preserve ELF program header
2006-05-27 16:23 ` H. J. Lu
@ 2006-05-27 16:33 ` Alan Modra
0 siblings, 0 replies; 6+ messages in thread
From: Alan Modra @ 2006-05-27 16:33 UTC (permalink / raw)
To: H. J. Lu; +Cc: binutils
On Thu, May 25, 2006 at 09:32:39PM -0700, H. J. Lu wrote:
> On Fri, May 26, 2006 at 01:19:21PM +0930, Alan Modra wrote:
> > Sure. Obviously you need to subtract off space for the headers then
> > align. I'm thinking that you can do this by modifying the assignments
> > to "align" in the function, particularly places that set "align" from
> > "bed->maxpagesize" to instead use your m->p_align. After all, the
> > problem you are trying to solve is one where alignment due to
> > bed->maxpagesize changes.
>
> Here is the updated patch.
This still isn't correct. You ignored bed->maxpagesize used when
aligning PT_TLS segments. Applying the following.
bfd/
* elf.c (assign_file_positions_for_load_sections): Retrieve
maxpagesize from m->p_align if it is valid. Set p_vaddr,
p_paddr and p_align earlier. Revert 2006-05-19 change to p_align.
(copy_elf_program_header): Copy p_align. Set p_align_valid.
include/elf/
* internal.h (struct elf_segment_map): Add p_align and p_align_valid.
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.339
diff -u -p -r1.339 elf.c
--- bfd/elf.c 25 May 2006 15:08:28 -0000 1.339
+++ bfd/elf.c 27 May 2006 00:23:13 -0000
@@ -4111,6 +4111,7 @@ assign_file_positions_for_load_sections
Elf_Internal_Phdr *phdrs;
Elf_Internal_Phdr *p;
file_ptr off, voff;
+ bfd_size_type maxpagesize;
unsigned int count;
unsigned int alloc;
unsigned int i;
@@ -4196,6 +4197,10 @@ assign_file_positions_for_load_sections
if (phdrs == NULL)
return FALSE;
+ maxpagesize = 1;
+ if ((abfd->flags & D_PAGED) != 0)
+ maxpagesize = bed->maxpagesize;
+
off = bed->s->sizeof_ehdr;
off += alloc * bed->s->sizeof_phdr;
@@ -4227,6 +4232,39 @@ assign_file_positions_for_load_sections
p->p_type = m->p_type;
p->p_flags = m->p_flags;
+ if (m->count == 0)
+ p->p_vaddr = 0;
+ else
+ p->p_vaddr = m->sections[0]->vma;
+
+ if (m->p_paddr_valid)
+ p->p_paddr = m->p_paddr;
+ else if (m->count == 0)
+ p->p_paddr = 0;
+ else
+ p->p_paddr = m->sections[0]->lma;
+
+ if (p->p_type == PT_LOAD
+ && (abfd->flags & D_PAGED) != 0)
+ {
+ /* p_align in demand paged PT_LOAD segments effectively stores
+ the maximum page size. When copying an executable with
+ objcopy, we set m->p_align from the input file. Use this
+ value for maxpagesize rather than bed->maxpagesize, which
+ may be different. Note that we use maxpagesize for PT_TLS
+ segment alignment later in this function, so we are relying
+ on at least one PT_LOAD segment appearing before a PT_TLS
+ segment. */
+ if (m->p_align_valid)
+ maxpagesize = m->p_align;
+
+ p->p_align = maxpagesize;
+ }
+ else if (m->count == 0)
+ p->p_align = 1 << bed->s->log_file_align;
+ else
+ p->p_align = 0;
+
if (p->p_type == PT_LOAD
&& m->count > 0)
{
@@ -4244,8 +4282,8 @@ assign_file_positions_for_load_sections
}
align = (bfd_size_type) 1 << align_power;
- if ((abfd->flags & D_PAGED) != 0 && bed->maxpagesize > align)
- align = bed->maxpagesize;
+ if (align < maxpagesize)
+ align = maxpagesize;
adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
off += adjust;
@@ -4286,26 +4324,6 @@ assign_file_positions_for_load_sections
return FALSE;
}
- if (m->count == 0)
- p->p_vaddr = 0;
- else
- p->p_vaddr = m->sections[0]->vma;
-
- if (m->p_paddr_valid)
- p->p_paddr = m->p_paddr;
- else if (m->count == 0)
- p->p_paddr = 0;
- else
- p->p_paddr = m->sections[0]->lma;
-
- if (p->p_type == PT_LOAD
- && (abfd->flags & D_PAGED) != 0)
- p->p_align = bed->maxpagesize;
- else if (m->count == 0)
- p->p_align = 1 << bed->s->log_file_align;
- else
- p->p_align = 0;
-
p->p_offset = 0;
p->p_filesz = 0;
p->p_memsz = 0;
@@ -4386,7 +4404,7 @@ assign_file_positions_for_load_sections
sec = *secpp;
flags = sec->flags;
- align = 1 << bfd_get_section_alignment (abfd, sec);
+ align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec);
if (p->p_type == PT_LOAD
|| p->p_type == PT_TLS)
@@ -4416,8 +4434,8 @@ assign_file_positions_for_load_sections
/* The section VMA must equal the file position
modulo the page size. */
bfd_size_type page = align;
- if ((abfd->flags & D_PAGED) != 0 && bed->maxpagesize > page)
- page = bed->maxpagesize;
+ if (page < maxpagesize)
+ page = maxpagesize;
adjust = vma_page_aligned_bias (sec->vma,
p->p_vaddr + p->p_memsz,
page);
@@ -4494,8 +4512,7 @@ assign_file_positions_for_load_sections
if (align > p->p_align
&& (p->p_type != PT_LOAD
- || (abfd->flags & D_PAGED) == 0
- || ((p->p_vaddr - p->p_offset) & (align - 1)) == 0))
+ || (abfd->flags & D_PAGED) == 0))
p->p_align = align;
}
@@ -5800,6 +5817,8 @@ 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_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. */
Index: include/elf/internal.h
===================================================================
RCS file: /cvs/src/src/include/elf/internal.h,v
retrieving revision 1.13
diff -u -p -r1.13 internal.h
--- include/elf/internal.h 10 Feb 2006 15:04:19 -0000 1.13
+++ include/elf/internal.h 27 May 2006 00:23:13 -0000
@@ -235,12 +235,17 @@ struct elf_segment_map
unsigned long p_flags;
/* Program segment physical address. */
bfd_vma p_paddr;
+ /* 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_align field is valid; if not, PT_LOAD 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. */
--
Alan Modra
IBM OzLabs - Linux Technology Centre
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2006-05-27 0:47 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-05-26 3:05 PATCH: Preserve ELF program header H. J. Lu
2006-05-26 14:00 ` Alan Modra
2006-05-26 17:28 ` H. J. Lu
2006-05-27 16:23 ` Alan Modra
2006-05-27 16:23 ` H. J. Lu
2006-05-27 16:33 ` Alan Modra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).