Partial fix for PR 15929 - Change physical address of segment when its
authorNick Clifton <nickc@redhat.com>
Fri, 29 May 1998 17:00:08 +0000 (17:00 +0000)
committerNick Clifton <nickc@redhat.com>
Fri, 29 May 1998 17:00:08 +0000 (17:00 +0000)
sections' LMAs have changed.

bfd/ChangeLog
bfd/elf.c

index b130f550519762faea66c1a44ea26e9c27bbe5c8..782cae6275adc69b9d739e855d683220d331f29a 100644 (file)
@@ -1,3 +1,8 @@
+Fri May 29 09:58:08 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * elf.c (copy_private_bfd_data): Adjust physical address of
+       segment in output BFD to contain LMAs of its sections.
+
 Tue May 26 19:37:47 1998  Stan Cox  <scox@equinox.cygnus.com>
 
        * elf32-sparc.c (_bfd_sparc_elf_howto_table, sparc_reloc_map,
@@ -520,8 +525,10 @@ Fri Mar 27 16:06:02 1998  Ian Lance Taylor  <ian@cygnus.com>
        * elf-bfd.h (elf_linker_section_t): Make alignment unsigned.
        (struct elf_obj_tdata): Make cverdefs and cverrefs unsigned.
        * elf.c (assign_file_positions_for_segments): Always set adjust.
+start-sanitize-d30v
        * elf32-d30v.c (bfd_elf_d30v_reloc): Initialize tmp_addr.  Fully
        parenthesize expression.
+end-sanitize-d30v
        * elf32-m32r.c (m32r_elf_relocate_section): Always initialize h.
        (m32r_elf_object_p): Return a value.
        (m32r_elf_print_private_bfd_data): Change fprintf format string.
index bb62b2ba052613de997135220a597d453e319245..b4bba4679884f87cb39a8b9e6012d4cc154f75e0 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2595,6 +2595,20 @@ assign_file_positions_for_segments (abfd)
          flags = sec->flags;
          align = 1 << bfd_get_section_alignment (abfd, sec);
 
+         /* The section may have artificial alignment forced by a 
+            link script.  Notice this case by the gap between the
+            cumulative phdr vma and the section's vma.  */
+         if (p->p_vaddr + p->p_memsz < sec->vma)
+           {
+             bfd_vma adjust = sec->vma - (p->p_vaddr + p->p_memsz);
+
+             p->p_memsz += adjust;
+             off += adjust;
+             voff += adjust;
+             if ((flags & SEC_LOAD) != 0)
+               p->p_filesz += adjust;
+           }
+
          if (p->p_type == PT_LOAD)
            {
              bfd_vma adjust;
@@ -3291,6 +3305,8 @@ copy_private_bfd_data (ibfd, obfd)
       m->p_type = p->p_type;
       m->p_flags = p->p_flags;
       m->p_flags_valid = 1;
+      /* Default to using the physical address of the segment
+        in the input BFD.  */
       m->p_paddr = p->p_paddr;
       m->p_paddr_valid = 1;
 
@@ -3305,9 +3321,19 @@ copy_private_bfd_data (ibfd, obfd)
       isec = 0;
       for (s = ibfd->sections; s != NULL; s = s->next)
        {
-         if (((s->vma >= p->p_vaddr
-               && (s->vma + s->_raw_size <= p->p_vaddr + p->p_memsz
-                   || s->vma + s->_raw_size <= p->p_vaddr + p->p_filesz))
+         boolean matching_lma = false;
+         boolean lma_conflict = false;
+         bfd_vma suggested_lma = 0;
+         asection * os;
+         
+#define is_contained_by(addr, len, bottom, phdr)                       \
+         ((addr) >= (bottom)                                           \
+          && (   ((addr) + (len)) <= ((bottom) + (phdr)->p_memsz)      \
+              || ((addr) + (len)) <= ((bottom) + (phdr)->p_filesz)))
+           
+         os = s->output_section;
+         
+         if ((is_contained_by (s->vma, s->_raw_size, p->p_vaddr, p)
               || (p->p_vaddr == 0
                   && p->p_filesz > 0
                   && (s->flags & SEC_HAS_CONTENTS) != 0
@@ -3315,10 +3341,37 @@ copy_private_bfd_data (ibfd, obfd)
                   && ((bfd_vma) s->filepos + s->_raw_size
                       <= p->p_offset + p->p_filesz)))
              && (s->flags & SEC_ALLOC) != 0
-             && s->output_section != NULL)
+             && os != NULL)
            {
-             m->sections[isec] = s->output_section;
+             m->sections[isec] = os;
              ++isec;
+
+             /* Match up the physical address of the segment with the
+                LMA addresses of its sections.  */
+
+             if (is_contained_by (os->lma, os->_raw_size, m->p_paddr, p))
+               matching_lma = true;
+             else if (suggested_lma == 0)
+               suggested_lma = os->lma;
+             else if
+               (! is_contained_by (os->lma, os->_raw_size, suggested_lma, p))
+               lma_conflict = true;
+           }
+         
+         if (matching_lma)
+           {
+             if (suggested_lma)
+               (*_bfd_error_handler)
+(_("Warning: Some sections' LMAs lie outside their segment's physical address\n"));
+           }
+         else if (lma_conflict)
+           {
+             (*_bfd_error_handler)
+(_("Warning: Cannot change segment's physical address to contain all of its sections' LMAs\n"));
+           }
+         else if (suggested_lma)
+           {
+             m->p_paddr = suggested_lma;
            }
        }
       BFD_ASSERT (isec == csecs);