From 3e4554a2064c06f1b49a759095ad5f2d172d45bc Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Fri, 6 Oct 2000 19:47:51 +0000 Subject: * 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 --- bfd/ChangeLog | 7 +++++++ bfd/coffcode.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- bfd/peigen.c | 9 ++++++++- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index dc4e67d..7069fb8 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2000-10-05 DJ Delorie + + * 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 * elf-bfd.h (struct elf_backend_data): Add elf_backend_section_flags diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 2750ad7..3bdf307 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -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 { diff --git a/bfd/peigen.c b/bfd/peigen.c index 066a601..a3373fc 100644 --- a/bfd/peigen.c +++ b/bfd/peigen.c @@ -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; -- cgit v1.1