bfd/
authorAlan Modra <amodra@gmail.com>
Sat, 27 May 2006 00:47:45 +0000 (00:47 +0000)
committerAlan Modra <amodra@gmail.com>
Sat, 27 May 2006 00:47:45 +0000 (00:47 +0000)
* 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 (elf_segment_map): Add p_align and p_align_valid.

bfd/ChangeLog
bfd/elf.c
include/elf/ChangeLog
include/elf/internal.h

index 2d7203123a2794a4a81e87c71ef03112a9de0266..97302a72bf3695befa00af1b99e4d9ab45aa9bf6 100644 (file)
@@ -1,3 +1,11 @@
+2006-05-27  Alan Modra  <amodra@bigpond.net.au>
+           H.J. Lu  <hongjiu.lu@intel.com>
+
+       * 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.
+
 2006-05-26  H.J. Lu  <hongjiu.lu@intel.com>
 
        * elf64-x86-64.c (ELF_MINPAGESIZE): Changed to 0x1000.
index d2124fd4f3e90e104c0e620c08d40b863294435b..7db3a2728eca033682dd0b579a3e9bd844193983 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -4111,6 +4111,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
   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 (bfd *abfd,
   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 (bfd *abfd,
       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 (bfd *abfd,
            }
          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 (bfd *abfd,
          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 (bfd *abfd,
 
          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 (bfd *abfd,
                  /* 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 (bfd *abfd,
 
              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 *obfd)
       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 f88b4137c45dd9d3945c81dca5b7f3b21cb660f2..fb3476cf60935da993801082a60f536513953e1b 100644 (file)
@@ -1,3 +1,7 @@
+2006-05-27  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * internal.h (struct elf_segment_map): Add p_align and p_align_valid.
+
 2006-05-24  Carlos O'Donell  <carlos@systemhalted.org>
            Randolph Chung  <randolph@tausq.org>
        * hppa.h (R_PARISC_TLS_GD21L, R_PARISC_TLS_GD14R, R_PARISC_TLS_GDCALL,
index e4eba7d6cb348a81ec343448c0441a72885f90c1..ff27c88bd441ff13a46448ebf0093411f0b06a98 100644 (file)
@@ -1,6 +1,6 @@
 /* ELF support for BFD.
    Copyright 1991, 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002,
-   2003 Free Software Foundation, Inc.
+   2003, 2006 Free Software Foundation, Inc.
 
    Written by Fred Fish @ Cygnus Support, from information published
    in "UNIX System V Release 4, Programmers Guide: ANSI C and
@@ -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.  */