OSDN Git Service

* peigen.c (_bfd_pei_swap_scnhdr_out): note extended relocs
authordj <dj>
Fri, 6 Oct 2000 19:47:51 +0000 (19:47 +0000)
committerdj <dj>
Fri, 6 Oct 2000 19:47:51 +0000 (19:47 +0000)
* coffcode.h (coff_set_alignment_hook): read extended reloc count
(coff_write_relocs): write extended reloc count
(coff_write_object_contents): account for extended relocs

bfd/ChangeLog
bfd/coffcode.h
bfd/peigen.c

index dc4e67d..7069fb8 100644 (file)
@@ -1,3 +1,10 @@
+2000-10-05  DJ Delorie  <dj@redhat.com>
+
+       * peigen.c (_bfd_pei_swap_scnhdr_out): note extended relocs
+       * coffcode.h (coff_set_alignment_hook): read extended reloc count
+       (coff_write_relocs): write extended reloc count
+       (coff_write_object_contents): account for extended relocs
+
 2000-10-05  Jim Wilson  <wilson@cygnus.com>
 
        * elf-bfd.h (struct elf_backend_data): Add elf_backend_section_flags
index 2750ad7..3bdf307 100644 (file)
@@ -1607,6 +1607,23 @@ coff_set_alignment_hook (abfd, section, scnhdr)
   pei_section_data (abfd, section)->pe_flags = hdr->s_flags;
 
   section->lma = hdr->s_vaddr;
+
+  /* check for extended relocs */
+  if (hdr->s_flags & IMAGE_SCN_LNK_NRELOC_OVFL)
+    {
+      struct external_reloc dst;
+      struct internal_reloc n;
+      int oldpos = bfd_tell (abfd);
+      bfd_seek (abfd, hdr->s_relptr, 0);
+      if (bfd_read ((PTR) & dst, 1, bfd_coff_relsz (abfd), abfd)
+         != bfd_coff_relsz (abfd))
+       return;
+      
+      coff_swap_reloc_in (abfd, &dst, &n);
+      bfd_seek (abfd, oldpos, 0);
+      section->reloc_count =
+       hdr->s_nreloc = n.r_vaddr;
+    }
 }
 #undef ALIGN_SET
 #undef ELIFALIGN_SET
@@ -2336,6 +2353,22 @@ coff_write_relocs (abfd, first_undef)
 
       if (bfd_seek (abfd, s->rel_filepos, SEEK_SET) != 0)
        return false;
+
+#ifdef COFF_WITH_PE
+      if (s->reloc_count > 0xffff)
+       {
+         /* encode real count here as first reloc */
+         struct internal_reloc n;
+         memset ((PTR) & n, 0, sizeof (n));
+         /* add one to count *this* reloc (grr) */
+         n.r_vaddr = s->reloc_count + 1;
+         coff_swap_reloc_out (abfd, &n, &dst);
+         if (bfd_write ((PTR) & dst, 1, bfd_coff_relsz (abfd), abfd)
+             != bfd_coff_relsz (abfd))
+           return false;
+       }
+#endif
+
       for (i = 0; i < s->reloc_count; i++)
        {
          struct internal_reloc n;
@@ -3176,7 +3209,7 @@ coff_write_object_contents (abfd)
   file_ptr reloc_base;
   file_ptr lineno_base;
   file_ptr sym_base;
-  unsigned long reloc_size = 0;
+  unsigned long reloc_size = 0, reloc_count = 0;
   unsigned long lnno_size = 0;
   boolean long_section_names;
   asection *text_sec = NULL;
@@ -3207,7 +3240,16 @@ coff_write_object_contents (abfd)
 
   for (current = abfd->sections; current != NULL; current =
        current->next)
-    reloc_size += current->reloc_count * bfd_coff_relsz (abfd);
+    {
+#ifdef COFF_WITH_PE
+      /* we store the actual reloc count in the first reloc's addr */
+      if (current->reloc_count > 0xffff)
+       reloc_count ++;
+#endif
+      reloc_count += current->reloc_count;
+    }
+
+  reloc_size = reloc_count * bfd_coff_relsz (abfd);
 
   lineno_base = reloc_base + reloc_size;
   sym_base = lineno_base + lnno_size;
@@ -3230,6 +3272,11 @@ coff_write_object_contents (abfd)
        {
          current->rel_filepos = reloc_base;
          reloc_base += current->reloc_count * bfd_coff_relsz (abfd);
+#ifdef COFF_WITH_PE
+         /* extra reloc to hold real count */
+         if (current->reloc_count > 0xffff)
+           reloc_base += bfd_coff_relsz (abfd);
+#endif
        }
       else
        {
index 066a601..a3373fc 100644 (file)
@@ -991,12 +991,19 @@ _bfd_pei_swap_scnhdr_out (abfd, in, out)
                      (bfd_byte *) scnhdr_ext->s_nreloc);
       else
        {
-         (*_bfd_error_handler) (_("%s: reloc overflow: 0x%lx > 0xffff"),
+         /* PE can deal with large #s of relocs, but not here */
+         bfd_h_put_16 (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nreloc);
+         scnhdr_int->s_flags |= IMAGE_SCN_LNK_NRELOC_OVFL;
+         bfd_h_put_32(abfd, scnhdr_int->s_flags,
+                      (bfd_byte *) scnhdr_ext->s_flags);
+#if 0
+         (*_bfd_error_handler) (_("%s: reloc overflow 1: 0x%lx > 0xffff"),
                                 bfd_get_filename (abfd),
                                 scnhdr_int->s_nreloc);
          bfd_set_error (bfd_error_file_truncated);
          bfd_h_put_16 (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nreloc);
          ret = 0;
+#endif
        }
     }
   return ret;