2004-02-13 Andrew Cagney <cagney@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Fri, 13 Feb 2004 14:58:58 +0000 (14:58 +0000)
committerAndrew Cagney <cagney@redhat.com>
Fri, 13 Feb 2004 14:58:58 +0000 (14:58 +0000)
* elf.c (vma_page_aligned_bias): New function.
(assign_file_positions_except_relocs)
(assign_file_positions_for_segments): Replace broken modulo
arithmetic with call to vma_page_aligned_bias.

bfd/ChangeLog
bfd/elf.c

index 4ab53c52640e894f7094b8c2e2a4623aee5c4bf4..4192e849b7ed692eacbe7bc7f5a02d97095de511 100644 (file)
@@ -1,3 +1,10 @@
+2004-02-13  Andrew Cagney  <cagney@redhat.com>
+
+       * elf.c (vma_page_aligned_bias): New function.
+       (assign_file_positions_except_relocs)
+       (assign_file_positions_for_segments): Replace broken modulo
+       arithmetic with call to vma_page_aligned_bias.
+
 2004-02-11  Andrew Cagney  <cagney@redhat.com>
 
        * bfd-in.h: Update copyright.
index 82f778b308bce81e8a292c16cf62f20ce92ed439..5e31f8935832c05c06453e64e89c0b7ab43014e1 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,6 +1,7 @@
 /* ELF executable support for BFD.
-   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003 Free Software Foundation, Inc.
+
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+   2002, 2003, 2004 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -3571,6 +3572,35 @@ elf_sort_sections (const void *arg1, const void *arg2)
   return sec1->target_index - sec2->target_index;
 }
 
+/* Ian Lance Taylor writes:
+
+   We shouldn't be using % with a negative signed number.  That's just
+   not good.  We have to make sure either that the number is not
+   negative, or that the number has an unsigned type.  When the types
+   are all the same size they wind up as unsigned.  When file_ptr is a
+   larger signed type, the arithmetic winds up as signed long long,
+   which is wrong.
+
+   What we're trying to say here is something like ``increase OFF by
+   the least amount that will cause it to be equal to the VMA modulo
+   the page size.''  */
+/* In other words, something like:
+
+   vma_offset = m->sections[0]->vma % bed->maxpagesize;
+   off_offset = off % bed->maxpagesize;
+   if (vma_offset < off_offset)
+     adjustment = vma_offset + bed->maxpagesize - off_offset;
+   else
+     adjustment = vma_offset - off_offset;
+     
+   which can can be collapsed into the expression below.  */
+
+static file_ptr
+vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize)
+{
+  return ((vma - off) % maxpagesize);
+}
+
 /* Assign file positions to the sections based on the mapping from
    sections to segments.  This function also sets up some fields in
    the file header, and writes out the program headers.  */
@@ -3698,7 +3728,8 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
          && (m->sections[0]->flags & SEC_ALLOC) != 0)
        {
          if ((abfd->flags & D_PAGED) != 0)
-           off += (m->sections[0]->vma - off) % bed->maxpagesize;
+           off += vma_page_aligned_bias (m->sections[0]->vma, off,
+                                         bed->maxpagesize);
          else
            {
              bfd_size_type align;
@@ -3713,7 +3744,8 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
                    align = secalign;
                }
 
-             off += (m->sections[0]->vma - off) % (1 << align);
+             off += vma_page_aligned_bias (m->sections[0]->vma, off,
+                                           1 << align);
            }
        }
 
@@ -3875,9 +3907,11 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
                     not have the SEC_LOAD case just above, and then
                     this was necessary, but now I'm not sure.  */
                  if ((abfd->flags & D_PAGED) != 0)
-                   adjust = (sec->vma - voff) % bed->maxpagesize;
+                   adjust = vma_page_aligned_bias (sec->vma, voff,
+                                                   bed->maxpagesize);
                  else
-                   adjust = (sec->vma - voff) % align;
+                   adjust = vma_page_aligned_bias (sec->vma, voff,
+                                                   align);
                }
              else
                adjust = 0;
@@ -4211,9 +4245,11 @@ assign_file_positions_except_relocs (bfd *abfd,
                 ? "*unknown*"
                 : hdr->bfd_section->name)));
              if ((abfd->flags & D_PAGED) != 0)
-               off += (hdr->sh_addr - off) % bed->maxpagesize;
+               off += vma_page_aligned_bias (hdr->sh_addr, off,
+                                             bed->maxpagesize);
              else
-               off += (hdr->sh_addr - off) % hdr->sh_addralign;
+               off += vma_page_aligned_bias (hdr->sh_addr, off,
+                                             hdr->sh_addralign);
              off = _bfd_elf_assign_file_position_for_section (hdr, off,
                                                               FALSE);
            }