PR 2995, PR 6473
authorAlan Modra <amodra@gmail.com>
Thu, 1 May 2008 14:13:58 +0000 (14:13 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 1 May 2008 14:13:58 +0000 (14:13 +0000)
* elf.c (_bfd_elf_make_section_from_shdr): Always set lma from p_paddr.
(assign_file_positions_for_load_sections): Combine nested "if".
(copy_elf_program_header): Don't set p_paddr_valid or p_vaddr_offset
when all header p_paddr fields are zero.

bfd/ChangeLog
bfd/elf.c

index e178d333d3ded1280336d63a2a5ed63519406306..8d994a8c6ae45d109465aab62464921879022722 100644 (file)
@@ -1,3 +1,11 @@
+2008-05-01  Alan Modra  <amodra@bigpond.net.au>
+
+       PR 2995, PR 6473
+       * elf.c (_bfd_elf_make_section_from_shdr): Always set lma from p_paddr.
+       (assign_file_positions_for_load_sections): Combine nested "if".
+       (copy_elf_program_header): Don't set p_paddr_valid or p_vaddr_offset
+       when all header p_paddr fields are zero.
+
 2008-04-30  Edmar Wienskoski  <edmar@freescale.com>
 
        * cpu-powerpc.c (bfd_powerpc_archs): Add e500mc entry.
index c4a88ee2db304482936d5faaf8b015116347edca..2f1ec37972c96ff2617ca6bbd4a5d056fddd787b 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -946,63 +946,51 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       Elf_Internal_Phdr *phdr;
       unsigned int i;
 
-      /* Look through the phdrs to see if we need to adjust the lma.
-        If all the p_paddr fields are zero, we ignore them, since
-        some ELF linkers produce such output.  */
       phdr = elf_tdata (abfd)->phdr;
       for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
        {
-         if (phdr->p_paddr != 0)
-           break;
-       }
-      if (i < elf_elfheader (abfd)->e_phnum)
-       {
-         phdr = elf_tdata (abfd)->phdr;
-         for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
+         /* This section is part of this segment if its file
+            offset plus size lies within the segment's memory
+            span and, if the section is loaded, the extent of the
+            loaded data lies within the extent of the segment.
+
+            Note - we used to check the p_paddr field as well, and
+            refuse to set the LMA if it was 0.  This is wrong
+            though, as a perfectly valid initialised segment can
+            have a p_paddr of zero.  Some architectures, eg ARM,
+            place special significance on the address 0 and
+            executables need to be able to have a segment which
+            covers this address.  */
+         if (phdr->p_type == PT_LOAD
+             && (bfd_vma) hdr->sh_offset >= phdr->p_offset
+             && (hdr->sh_offset + hdr->sh_size
+                 <= phdr->p_offset + phdr->p_memsz)
+             && ((flags & SEC_LOAD) == 0
+                 || (hdr->sh_offset + hdr->sh_size
+                     <= phdr->p_offset + phdr->p_filesz)))
            {
-             /* This section is part of this segment if its file
-                offset plus size lies within the segment's memory
-                span and, if the section is loaded, the extent of the
-                loaded data lies within the extent of the segment.
-
-                Note - we used to check the p_paddr field as well, and
-                refuse to set the LMA if it was 0.  This is wrong
-                though, as a perfectly valid initialised segment can
-                have a p_paddr of zero.  Some architectures, eg ARM,
-                place special significance on the address 0 and
-                executables need to be able to have a segment which
-                covers this address.  */
-             if (phdr->p_type == PT_LOAD
-                 && (bfd_vma) hdr->sh_offset >= phdr->p_offset
-                 && (hdr->sh_offset + hdr->sh_size
-                     <= phdr->p_offset + phdr->p_memsz)
-                 && ((flags & SEC_LOAD) == 0
-                     || (hdr->sh_offset + hdr->sh_size
-                         <= phdr->p_offset + phdr->p_filesz)))
-               {
-                 if ((flags & SEC_LOAD) == 0)
-                   newsect->lma = (phdr->p_paddr
-                                   + hdr->sh_addr - phdr->p_vaddr);
-                 else
-                   /* We used to use the same adjustment for SEC_LOAD
-                      sections, but that doesn't work if the segment
-                      is packed with code from multiple VMAs.
-                      Instead we calculate the section LMA based on
-                      the segment LMA.  It is assumed that the
-                      segment will contain sections with contiguous
-                      LMAs, even if the VMAs are not.  */
-                   newsect->lma = (phdr->p_paddr
-                                   + hdr->sh_offset - phdr->p_offset);
-
-                 /* With contiguous segments, we can't tell from file
-                    offsets whether a section with zero size should
-                    be placed at the end of one segment or the
-                    beginning of the next.  Decide based on vaddr.  */
-                 if (hdr->sh_addr >= phdr->p_vaddr
-                     && (hdr->sh_addr + hdr->sh_size
-                         <= phdr->p_vaddr + phdr->p_memsz))
-                   break;
-               }
+             if ((flags & SEC_LOAD) == 0)
+               newsect->lma = (phdr->p_paddr
+                               + hdr->sh_addr - phdr->p_vaddr);
+             else
+               /* We used to use the same adjustment for SEC_LOAD
+                  sections, but that doesn't work if the segment
+                  is packed with code from multiple VMAs.
+                  Instead we calculate the section LMA based on
+                  the segment LMA.  It is assumed that the
+                  segment will contain sections with contiguous
+                  LMAs, even if the VMAs are not.  */
+               newsect->lma = (phdr->p_paddr
+                               + hdr->sh_offset - phdr->p_offset);
+
+             /* With contiguous segments, we can't tell from file
+                offsets whether a section with zero size should
+                be placed at the end of one segment or the
+                beginning of the next.  Decide based on vaddr.  */
+             if (hdr->sh_addr >= phdr->p_vaddr
+                 && (hdr->sh_addr + hdr->sh_size
+                     <= phdr->p_vaddr + phdr->p_memsz))
+               break;
            }
        }
     }
@@ -4359,30 +4347,28 @@ assign_file_positions_for_load_sections (bfd *abfd,
          this_hdr = &elf_section_data (sec)->this_hdr;
          align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec);
 
-         if (p->p_type == PT_LOAD
-             || p->p_type == PT_TLS)
+         if ((p->p_type == PT_LOAD
+              || p->p_type == PT_TLS)
+             && (this_hdr->sh_type != SHT_NOBITS
+                 || ((this_hdr->sh_flags & SHF_ALLOC) != 0
+                     && ((this_hdr->sh_flags & SHF_TLS) == 0
+                         || p->p_type == PT_TLS))))
            {
              bfd_signed_vma adjust = sec->lma - (p->p_paddr + p->p_memsz);
 
-             if (this_hdr->sh_type != SHT_NOBITS
-                 || ((this_hdr->sh_flags & SHF_ALLOC) != 0
-                     && ((this_hdr->sh_flags & SHF_TLS) == 0
-                         || p->p_type == PT_TLS)))
+             if (adjust < 0)
                {
-                 if (adjust < 0)
-                   {
-                     (*_bfd_error_handler)
-                       (_("%B: section %A lma 0x%lx overlaps previous sections"),
-                        abfd, sec, (unsigned long) sec->lma);
-                     adjust = 0;
-                   }
-                 p->p_memsz += adjust;
+                 (*_bfd_error_handler)
+                   (_("%B: section %A lma 0x%lx overlaps previous sections"),
+                    abfd, sec, (unsigned long) sec->lma);
+                 adjust = 0;
+               }
+             p->p_memsz += adjust;
 
-                 if (this_hdr->sh_type != SHT_NOBITS)
-                   {
-                     off += adjust;
-                     p->p_filesz += adjust;
-                   }
+             if (this_hdr->sh_type != SHT_NOBITS)
+               {
+                 off += adjust;
+                 p->p_filesz += adjust;
                }
            }
 
@@ -5709,13 +5695,26 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
   unsigned int i;
   unsigned int num_segments;
   bfd_boolean phdr_included = FALSE;
+  bfd_boolean p_paddr_valid;
 
   iehdr = elf_elfheader (ibfd);
 
   map_first = NULL;
   pointer_to_map = &map_first;
 
+  /* If all the segment p_paddr fields are zero, don't set
+     map->p_paddr_valid.  */
+  p_paddr_valid = FALSE;
   num_segments = elf_elfheader (ibfd)->e_phnum;
+  for (i = 0, segment = elf_tdata (ibfd)->phdr;
+       i < num_segments;
+       i++, segment++)
+    if (segment->p_paddr != 0)
+      {
+       p_paddr_valid = TRUE;
+       break;
+      }
+
   for (i = 0, segment = elf_tdata (ibfd)->phdr;
        i < num_segments;
        i++, segment++)
@@ -5759,7 +5758,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
       map->p_flags = segment->p_flags;
       map->p_flags_valid = 1;
       map->p_paddr = segment->p_paddr;
-      map->p_paddr_valid = 1;
+      map->p_paddr_valid = p_paddr_valid;
       map->p_align = segment->p_align;
       map->p_align_valid = 1;
       map->p_vaddr_offset = 0;
@@ -5793,7 +5792,9 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
            phdr_included = TRUE;
        }
 
-      if (!map->includes_phdrs && !map->includes_filehdr)
+      if (!map->includes_phdrs
+         && !map->includes_filehdr
+         && map->p_paddr_valid)
        /* There is some other padding before the first section.  */
        map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
                               - segment->p_paddr);