[PATCH 0/2] djgpp patches

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/2] djgpp patches

Sourceware - binutils list mailing list
The following two patches implement functionality that has long been
available in the djgpp release of binutils, but not yet upstreamed
here.  These patches are written by Juan Manuel Guerrero, who has given
his permission for me to submit these here:

http://www.delorie.com/djgpp/mail-archives/browse.cgi?p=djgpp/2020/03/11/16:23:08

I have made some modifications so that this applies cleanly to the
current master branch, and to minimize changes to target-independent
code.


Reply | Threaded
Open this post in threaded view
|

[PATCH 1/2] coff-go32: update ldscript

Sourceware - binutils list mailing list
This patch updates the linker scripts for coff-go32.
Most importantly, it defines the _environ symbol.  Without this it is
impossible to link any program with djgpp's libc, since it requires
this symbol to be provided by the linker script.
Also the .ctors and .dtors sections are linked in, and finally the LTO
sections are discarded.

ld/
2020-04-08  Juan Manuel Guerrero  <[hidden email]>
            Jan W. Jagersma  <[hidden email]>

        * scripttempl/i386go32.sc: Provide symbol _environ.  Link in
        .ctors and .dtors.  Discard LTO sections.
---
 ld/scripttempl/i386go32.sc | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/ld/scripttempl/i386go32.sc b/ld/scripttempl/i386go32.sc
index 999aa0527d..feb919b982 100644
--- a/ld/scripttempl/i386go32.sc
+++ b/ld/scripttempl/i386go32.sc
@@ -47,11 +47,16 @@ SECTIONS
     ${RELOCATING+djgpp_first_ctor = . ;
     *(SORT(.ctors.*))
     *(.ctor)
+    *(.ctors)
     djgpp_last_ctor = . ;}
     ${RELOCATING+djgpp_first_dtor = . ;
     *(SORT(.dtors.*))
     *(.dtor)
+    *(.dtors)
     djgpp_last_dtor = . ;}
+    __environ = . ;
+    PROVIDE(_environ = .) ;
+    LONG(0) ;
     *(.data)
     ${RELOCATING+*(.data.*)}
 
@@ -74,6 +79,8 @@ SECTIONS
     ${RELOCATING+ end = . ; PROVIDE(_end = .) ;}
     ${RELOCATING+ . = ALIGN(${SEGMENT_SIZE});}
   }
+  /* Discard LTO sections.  */
+  /DISCARD/ : { *(.gnu.lto_*) }
   /* Stabs debugging sections.  */
   .stab 0 : { *(.stab) }
   .stabstr 0 : { *(.stabstr) }
--
2.26.0

Reply | Threaded
Open this post in threaded view
|

[PATCH 2/2] coff-go32: support extended relocations

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
This patch extends the relocation and line number counters for
coff-go32 and coff-go32-exe to 32 bits.  As I understand it works the
same as for PE-COFF:

If the number of relocations in an object file exceeds 65534, the
NRELOC field is set to 65535 and the actual number of relocations is
stored in the VADDR field of the first relocation entry.

Executable files have no relocations, and thus the NRELOC field is
repurposed to extend NLNNO to 32-bits.

bfd/
2020-04-08  Juan Manuel Guerrero  <[hidden email]>
            Jan W. Jagersma  <[hidden email]>

        * coff-go32.c (COFF_GO32, IMAGE_SCN_LNK_NRELOC_OVFL)
        (coff_swap_scnhdr_in, coff_swap_scnhdr_out): Define.
        (_bfd_go32_swap_scnhdr_in, _bfd_go32_swap_scnhdr_out)
        (_bfd_go32_mkobject): New functions.
        * coff-stgo32.c (IMAGE_SCN_LNK_NRELOC_OVFL)
        (coff_swap_scnhdr_in, coff_swap_scnhdr_out): Define.
        (go32exe_mkobject): Call _bfd_go32_mkobject.
        * coffcode.h (COFF_WITH_EXTENDED_RELOC_COUNTER): Define.
        (coff_set_alignment_hook): Define function for COFF_GO32_EXE
        and COFF_GO32.
        (coff_write_relocs): Enable extended reloc counter code if
        COFF_WITH_EXTENDED_RELOC_COUNTER is defined.  Test for obj_go32.
        (coff_write_object_contents): Likewise.  Pad section headers
        for COFF_GO32 and COFF_GO32EXE.
        cofflink.c (_bfd_coff_final_link): Test for obj_go32.
        coffswap.h: (coff_swap_scnhdr_in, coff_swap_scnhdr_in): Allow
        overriding these functions with macros of the same name.
        libcoff-in.h: (struct coff_tdata): New field go32.
        (obj_go32): Define.
---
 bfd/coff-go32.c   | 134 ++++++++++++++++++++++++++++++++++++++++++++++
 bfd/coff-stgo32.c |  30 +++++------
 bfd/coffcode.h    |  66 ++++++++++++++++++++---
 bfd/cofflink.c    |   4 +-
 bfd/coffswap.h    |   4 ++
 bfd/libcoff-in.h  |   6 ++-
 6 files changed, 219 insertions(+), 25 deletions(-)

diff --git a/bfd/coff-go32.c b/bfd/coff-go32.c
index e43d5cee3d..f5fc71d126 100644
--- a/bfd/coff-go32.c
+++ b/bfd/coff-go32.c
@@ -22,6 +22,7 @@
 #define TARGET_SYM i386_coff_go32_vec
 #define TARGET_NAME "coff-go32"
 #define TARGET_UNDERSCORE '_'
+#define COFF_GO32
 #define COFF_LONG_SECTION_NAMES
 #define COFF_SUPPORT_GNU_LINKONCE
 #define COFF_LONG_FILENAMES
@@ -42,4 +43,137 @@
 { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi"), \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
 
+/* Section contains extended relocations. */
+#define IMAGE_SCN_LNK_NRELOC_OVFL (0x01000000)
+
+#include "sysdep.h"
+#include "bfd.h"
+
+/* The following functions are not static, because they are also
+   used for coff-go32-exe (coff-stgo32.c).  */
+bfd_boolean _bfd_go32_mkobject (bfd *);
+void _bfd_go32_swap_scnhdr_in (bfd *, void *, void *);
+unsigned int _bfd_go32_swap_scnhdr_out (bfd *, void *, void *);
+
+#define coff_mkobject _bfd_go32_mkobject
+#define coff_swap_scnhdr_in _bfd_go32_swap_scnhdr_in
+#define coff_swap_scnhdr_out _bfd_go32_swap_scnhdr_out
+
 #include "coff-i386.c"
+
+bfd_boolean
+_bfd_go32_mkobject (bfd * abfd)
+{
+  const bfd_size_type amt = sizeof (coff_data_type);
+
+  abfd->tdata.coff_obj_data = bfd_zalloc (abfd, amt);
+  if (abfd->tdata.coff_obj_data == NULL)
+    return FALSE;
+
+  coff_data (abfd)->go32 = TRUE;
+
+  return TRUE;
+}
+
+void
+_bfd_go32_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
+{
+  SCNHDR *scnhdr_ext = (SCNHDR *) ext;
+  struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
+
+  memcpy (scnhdr_int->s_name, scnhdr_ext->s_name, sizeof (scnhdr_int->s_name));
+
+  scnhdr_int->s_vaddr = GET_SCNHDR_VADDR (abfd, scnhdr_ext->s_vaddr);
+  scnhdr_int->s_paddr = GET_SCNHDR_PADDR (abfd, scnhdr_ext->s_paddr);
+  scnhdr_int->s_size = GET_SCNHDR_SIZE (abfd, scnhdr_ext->s_size);
+
+  scnhdr_int->s_scnptr = GET_SCNHDR_SCNPTR (abfd, scnhdr_ext->s_scnptr);
+  scnhdr_int->s_relptr = GET_SCNHDR_RELPTR (abfd, scnhdr_ext->s_relptr);
+  scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, scnhdr_ext->s_lnnoptr);
+  scnhdr_int->s_flags = GET_SCNHDR_FLAGS (abfd, scnhdr_ext->s_flags);
+  scnhdr_int->s_nreloc = GET_SCNHDR_NRELOC (abfd, scnhdr_ext->s_nreloc);
+  scnhdr_int->s_nlnno = GET_SCNHDR_NLNNO (abfd, scnhdr_ext->s_nlnno);
+
+  /* DJGPP follows the same strategy as PE COFF.
+     Iff the file is an executable then the higher 16 bits
+     of the line number have been stored in the relocation
+     counter field.  */
+  if (abfd->flags & EXEC_P && (strcmp (scnhdr_ext->s_name, ".text") == 0))
+    {
+      scnhdr_int->s_nlnno
+ = (GET_SCNHDR_NRELOC (abfd, scnhdr_ext->s_nreloc) << 16)
+  + GET_SCNHDR_NLNNO (abfd, scnhdr_ext->s_nlnno);
+      scnhdr_int->s_nreloc = 0;
+    }
+}
+
+unsigned int
+_bfd_go32_swap_scnhdr_out (bfd * abfd, void * in, void * out)
+{
+  struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
+  SCNHDR *scnhdr_ext = (SCNHDR *) out;
+  unsigned int ret = bfd_coff_scnhsz (abfd);
+
+  memcpy (scnhdr_ext->s_name, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
+
+  PUT_SCNHDR_VADDR (abfd, scnhdr_int->s_vaddr, scnhdr_ext->s_vaddr);
+  PUT_SCNHDR_PADDR (abfd, scnhdr_int->s_paddr, scnhdr_ext->s_paddr);
+  PUT_SCNHDR_SIZE (abfd, scnhdr_int->s_size, scnhdr_ext->s_size);
+  PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr, scnhdr_ext->s_scnptr);
+  PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr, scnhdr_ext->s_relptr);
+  PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr, scnhdr_ext->s_lnnoptr);
+  PUT_SCNHDR_FLAGS (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags);
+
+  if (abfd->flags & EXEC_P && (strcmp (scnhdr_int->s_name, ".text") == 0))
+    {
+      /* DJGPP follows the same strategy as PE COFF.
+ By inference from looking at MS output, the 32 bit field
+ which is the combination of the number_of_relocs and
+ number_of_linenos is used for the line number count in
+ executables.  A 16-bit field won't do for cc1.  The MS
+ document says that the number of relocs is zero for
+ executables, but the 17-th bit has been observed to be there.
+ Overflow is not an issue: a 4G-line program will overflow a
+ bunch of other fields long before this!  */
+      PUT_SCNHDR_NLNNO (abfd, (scnhdr_int->s_nlnno & 0xffff),
+ scnhdr_ext->s_nlnno);
+      PUT_SCNHDR_NRELOC (abfd, (scnhdr_int->s_nlnno >> 16),
+ scnhdr_ext->s_nreloc);
+    }
+  else
+    {
+      /* DJGPP follows the same strategy as PE COFF.  */
+      if (scnhdr_int->s_nlnno <= MAX_SCNHDR_NLNNO)
+ PUT_SCNHDR_NLNNO (abfd, scnhdr_int->s_nlnno, scnhdr_ext->s_nlnno);
+      else
+ {
+  char buf[sizeof (scnhdr_int->s_name) + 1];
+
+  memcpy (buf, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
+  buf[sizeof (scnhdr_int->s_name)] = '\0';
+  _bfd_error_handler
+    /* xgettext:c-format */
+    (_("%pB: warning: %s: line number overflow: 0x%lx > 0xffff"),
+     abfd, buf, scnhdr_int->s_nlnno);
+  bfd_set_error (bfd_error_file_truncated);
+  PUT_SCNHDR_NLNNO (abfd, 0xffff, scnhdr_ext->s_nlnno);
+  ret = 0;
+ }
+
+      /* Although we could encode 0xffff relocs here, we do not, to be
+ consistent with other parts of bfd. Also it lets us warn, as
+ we should never see 0xffff here w/o having the overflow flag
+ set.  */
+      if (scnhdr_int->s_nreloc < MAX_SCNHDR_NRELOC)
+ PUT_SCNHDR_NRELOC (abfd, scnhdr_int->s_nreloc, scnhdr_ext->s_nreloc);
+      else
+ {
+  /* DJGPP can deal with large #s of relocs, but not here.  */
+  PUT_SCNHDR_NRELOC (abfd, 0xffff, scnhdr_ext->s_nreloc);
+  scnhdr_int->s_flags |= IMAGE_SCN_LNK_NRELOC_OVFL;
+  PUT_SCNHDR_FLAGS (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags);
+ }
+    }
+
+  return ret;
+}
diff --git a/bfd/coff-stgo32.c b/bfd/coff-stgo32.c
index d1be578c6a..98f601b5da 100644
--- a/bfd/coff-stgo32.c
+++ b/bfd/coff-stgo32.c
@@ -46,6 +46,9 @@
 { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi"), \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
 
+/* Section contains extended relocations. */
+#define IMAGE_SCN_LNK_NRELOC_OVFL (0x01000000)
+
 #include "sysdep.h"
 #include "bfd.h"
 #include "coff/msdos.h"
@@ -55,10 +58,17 @@ static bfd_boolean go32exe_write_object_contents (bfd *);
 static bfd_boolean go32exe_mkobject (bfd *);
 static bfd_boolean go32exe_copy_private_bfd_data (bfd *, bfd *);
 
+/* Defined in coff-go32.c.  */
+bfd_boolean _bfd_go32_mkobject (bfd *);
+void _bfd_go32_swap_scnhdr_in (bfd *, void *, void *);
+unsigned int _bfd_go32_swap_scnhdr_out (bfd *, void *, void *);
+
 #define COFF_CHECK_FORMAT go32exe_check_format
 #define COFF_WRITE_CONTENTS go32exe_write_object_contents
 #define coff_mkobject go32exe_mkobject
 #define coff_bfd_copy_private_bfd_data go32exe_copy_private_bfd_data
+#define coff_swap_scnhdr_in _bfd_go32_swap_scnhdr_in
+#define coff_swap_scnhdr_out _bfd_go32_swap_scnhdr_out
 
 #include "coff-i386.c"
 
@@ -352,32 +362,20 @@ go32exe_write_object_contents (bfd *abfd)
 static bfd_boolean
 go32exe_mkobject (bfd *abfd)
 {
-  coff_data_type *coff = NULL;
-  const bfd_size_type amt = sizeof (coff_data_type);
-
   /* Don't output to an archive.  */
   if (abfd->my_archive != NULL)
     return FALSE;
 
-  abfd->tdata.coff_obj_data = bfd_zalloc (abfd, amt);
-  if (abfd->tdata.coff_obj_data == NULL)
+  if (!_bfd_go32_mkobject (abfd))
     return FALSE;
-  coff = coff_data (abfd);
-  coff->symbols = NULL;
-  coff->conversion_table = NULL;
-  coff->raw_syments = NULL;
-  coff->relocbase = 0;
-  coff->local_toc_sym_map = 0;
 
   go32exe_create_stub (abfd);
-  if (coff->stub == NULL)
+  if (coff_data (abfd)->stub == NULL)
     {
-      bfd_release (abfd, coff);
+      bfd_release (abfd, coff_data (abfd));
       return FALSE;
     }
-  abfd->origin = coff->stub_size;
-
-/*  make_abs_section(abfd);*/ /* ??? */
+  abfd->origin = coff_data (abfd)->stub_size;
 
   return TRUE;
 }
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 3bee5d2f9d..c9c93d492b 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -364,6 +364,10 @@ CODE_FRAGMENT
 #define GNU_LINKONCE_WT ".gnu.linkonce.wt."
 #define DOT_RELOC ".reloc"
 
+#if defined(COFF_WITH_PE) || defined(COFF_GO32_EXE) || defined(COFF_GO32)
+# define COFF_WITH_EXTENDED_RELOC_COUNTER
+#endif
+
 #if defined (COFF_LONG_SECTION_NAMES)
 /* Needed to expand the inputs to BLANKOR1TOODD.  */
 #define COFFLONGSECTIONCATHELPER(x,y)    x ## y
@@ -1964,6 +1968,39 @@ coff_set_alignment_hook (bfd *abfd, asection *section, void * scnhdr)
 }
 
 #else /* ! RS6000COFF_C */
+#if defined (COFF_GO32_EXE) || defined (COFF_GO32)
+
+static void
+coff_set_alignment_hook (bfd * abfd, asection * section, void * scnhdr)
+{
+  struct internal_scnhdr *hdr = (struct internal_scnhdr *) scnhdr;
+
+  /* Check for extended relocs.  */
+  if (hdr->s_flags & IMAGE_SCN_LNK_NRELOC_OVFL)
+    {
+      struct external_reloc dst;
+      struct internal_reloc n;
+      const file_ptr oldpos = bfd_tell (abfd);
+      const bfd_size_type relsz = bfd_coff_relsz (abfd);
+
+      if (bfd_seek (abfd, (file_ptr) hdr->s_relptr, 0) != 0)
+ return;
+      if (bfd_bread (& dst, relsz, abfd) != relsz)
+ return;
+
+      coff_swap_reloc_in (abfd, &dst, &n);
+      if (bfd_seek (abfd, oldpos, 0) != 0)
+ return;
+      section->reloc_count = hdr->s_nreloc = n.r_vaddr - 1;
+      section->rel_filepos += relsz;
+    }
+  else if (hdr->s_nreloc == 0xffff)
+    _bfd_error_handler
+      (_("%pB: warning: claims to have 0xffff relocs, without overflow"),
+       abfd);
+}
+
+#else /* ! COFF_GO32_EXE && ! COFF_GO32 */
 
 static void
 coff_set_alignment_hook (bfd *abfd ATTRIBUTE_UNUSED,
@@ -1972,6 +2009,7 @@ coff_set_alignment_hook (bfd *abfd ATTRIBUTE_UNUSED,
 {
 }
 
+#endif /* ! COFF_GO32_EXE && ! COFF_GO32 */
 #endif /* ! RS6000COFF_C */
 #endif /* ! COFF_WITH_PE */
 #endif /* ! COFF_ALIGN_IN_SECTION_HEADER */
@@ -2521,8 +2559,8 @@ coff_write_relocs (bfd * abfd, int first_undef)
       if (bfd_seek (abfd, s->rel_filepos, SEEK_SET) != 0)
  return FALSE;
 
-#ifdef COFF_WITH_PE
-      if (obj_pe (abfd) && s->reloc_count >= 0xffff)
+#ifdef COFF_WITH_EXTENDED_RELOC_COUNTER
+      if ((obj_pe (abfd) || obj_go32 (abfd)) && s->reloc_count >= 0xffff)
  {
   /* Encode real count here as first reloc.  */
   struct internal_reloc n;
@@ -3382,9 +3420,9 @@ coff_write_object_contents (bfd * abfd)
   for (current = abfd->sections; current != NULL; current =
        current->next)
     {
-#ifdef COFF_WITH_PE
+#ifdef COFF_WITH_EXTENDED_RELOC_COUNTER
       /* We store the actual reloc count in the first reloc's addr.  */
-      if (obj_pe (abfd) && current->reloc_count >= 0xffff)
+      if ((obj_pe (abfd) || obj_go32 (abfd)) && current->reloc_count >= 0xffff)
  reloc_count ++;
 #endif
       reloc_count += current->reloc_count;
@@ -3412,9 +3450,9 @@ coff_write_object_contents (bfd * abfd)
  {
   current->rel_filepos = reloc_base;
   reloc_base += current->reloc_count * bfd_coff_relsz (abfd);
-#ifdef COFF_WITH_PE
+#ifdef COFF_WITH_EXTENDED_RELOC_COUNTER
   /* Extra reloc to hold real count.  */
-  if (obj_pe (abfd) && current->reloc_count >= 0xffff)
+  if ((obj_pe (abfd) || obj_go32 (abfd)) && current->reloc_count >= 0xffff)
     reloc_base += bfd_coff_relsz (abfd);
 #endif
  }
@@ -3749,6 +3787,22 @@ coff_write_object_contents (bfd * abfd)
 #endif
 #endif
 
+#if defined (COFF_GO32_EXE) || defined (COFF_GO32)
+  /* Pad section headers.  */
+  if ((abfd->flags & EXEC_P) && abfd->sections != NULL)
+    {
+      file_ptr cur_ptr = scn_base
+ + abfd->section_count * bfd_coff_scnhsz (abfd);
+      long fill_size = (abfd->sections->filepos - cur_ptr);
+      bfd_byte *b = bfd_zmalloc (fill_size);
+      if (b)
+ {
+  bfd_bwrite ((PTR)b, fill_size, abfd);
+  free (b);
+ }
+    }
+#endif
+
   /* OK, now set up the filehdr...  */
 
   /* Don't include the internal abs section in the section count */
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index e52f543ee6..0beff8397f 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -689,7 +689,7 @@ _bfd_coff_final_link (bfd *abfd,
   rel_filepos += o->reloc_count * relsz;
   /* In PE COFF, if there are at least 0xffff relocations an
      extra relocation will be written out to encode the count.  */
-  if (obj_pe (abfd) && o->reloc_count >= 0xffff)
+  if ((obj_pe (abfd) || obj_go32 (abfd)) && o->reloc_count >= 0xffff)
     rel_filepos += relsz;
  }
 
@@ -1108,7 +1108,7 @@ _bfd_coff_final_link (bfd *abfd,
 
   if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0)
     goto error_return;
-  if (obj_pe (abfd) && o->reloc_count >= 0xffff)
+  if ((obj_pe (abfd) || obj_go32 (abfd)) && o->reloc_count >= 0xffff)
     {
       /* In PE COFF, write the count of relocs as the first
  reloc.  The header overflow bit will be set
diff --git a/bfd/coffswap.h b/bfd/coffswap.h
index c4ac067a62..9697d23ced 100644
--- a/bfd/coffswap.h
+++ b/bfd/coffswap.h
@@ -725,6 +725,7 @@ coff_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   return AOUTSZ;
 }
 
+#ifndef coff_swap_scnhdr_in
 static void
 coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
 {
@@ -750,7 +751,9 @@ coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
   COFF_ADJUST_SCNHDR_IN_POST (abfd, ext, in);
 #endif
 }
+#endif
 
+#ifndef coff_swap_scnhdr_out
 static unsigned int
 coff_swap_scnhdr_out (bfd * abfd, void * in, void * out)
 {
@@ -806,3 +809,4 @@ coff_swap_scnhdr_out (bfd * abfd, void * in, void * out)
 #endif
   return ret;
 }
+#endif
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index e4155d286f..3f0227c4ac 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -33,8 +33,9 @@ extern "C" {
 
 #define coff_data(bfd)      ((bfd)->tdata.coff_obj_data)
 #define obj_pe(bfd)      (coff_data (bfd)->pe)
+#define obj_go32(bfd)      (coff_data (bfd)->go32)
 #define obj_symbols(bfd)      (coff_data (bfd)->symbols)
-#define obj_sym_filepos(bfd)      (coff_data (bfd)->sym_filepos)
+#define obj_sym_filepos(bfd)      (coff_data (bfd)->sym_filepos)
 #define obj_relocbase(bfd)      (coff_data (bfd)->relocbase)
 #define obj_raw_syments(bfd)      (coff_data (bfd)->raw_syments)
 #define obj_raw_syment_count(bfd)     (coff_data (bfd)->raw_syment_count)
@@ -114,6 +115,9 @@ typedef struct coff_tdata
      used by ARM code.  */
   flagword flags;
 
+  /* Is this a GO32 coff file?  */
+  bfd_boolean go32;
+
   /* A stub (extra data prepended before the COFF image) and its size.
      Used by coff-go32-exe, it contains executable data that loads the
      COFF object into memory.  */
--
2.26.0

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/2] coff-go32: support extended relocations

Sourceware - binutils list mailing list
On 2020-04-08 17:21, J.W. Jagersma wrote:

> This patch extends the relocation and line number counters for
> coff-go32 and coff-go32-exe to 32 bits.  As I understand it works the
> same as for PE-COFF:
>
> If the number of relocations in an object file exceeds 65534, the
> NRELOC field is set to 65535 and the actual number of relocations is
> stored in the VADDR field of the first relocation entry.
>
> Executable files have no relocations, and thus the NRELOC field is
> repurposed to extend NLNNO to 32-bits.
>
> bfd/
> 2020-04-08  Juan Manuel Guerrero  <[hidden email]>
>             Jan W. Jagersma  <[hidden email]>
>
> * coff-go32.c (COFF_GO32, IMAGE_SCN_LNK_NRELOC_OVFL)
> (coff_swap_scnhdr_in, coff_swap_scnhdr_out): Define.
> (_bfd_go32_swap_scnhdr_in, _bfd_go32_swap_scnhdr_out)
> (_bfd_go32_mkobject): New functions.
> * coff-stgo32.c (IMAGE_SCN_LNK_NRELOC_OVFL)
> (coff_swap_scnhdr_in, coff_swap_scnhdr_out): Define.
> (go32exe_mkobject): Call _bfd_go32_mkobject.
> * coffcode.h (COFF_WITH_EXTENDED_RELOC_COUNTER): Define.
> (coff_set_alignment_hook): Define function for COFF_GO32_EXE
> and COFF_GO32.
> (coff_write_relocs): Enable extended reloc counter code if
> COFF_WITH_EXTENDED_RELOC_COUNTER is defined.  Test for obj_go32.
> (coff_write_object_contents): Likewise.  Pad section headers
> for COFF_GO32 and COFF_GO32EXE.
> cofflink.c (_bfd_coff_final_link): Test for obj_go32.
> coffswap.h: (coff_swap_scnhdr_in, coff_swap_scnhdr_in): Allow
> overriding these functions with macros of the same name.
> libcoff-in.h: (struct coff_tdata): New field go32.
> (obj_go32): Define.
> ---

I'm sorry, I did not thoroughly proofread the changelog before sending.
Please use the following:

        * coff-go32.c (COFF_GO32, IMAGE_SCN_LNK_NRELOC_OVFL)
        (coff_swap_scnhdr_in, coff_swap_scnhdr_out): Define.
        (_bfd_go32_swap_scnhdr_in, _bfd_go32_swap_scnhdr_out)
        (_bfd_go32_mkobject): New functions.
        * coff-stgo32.c (IMAGE_SCN_LNK_NRELOC_OVFL)
        (coff_swap_scnhdr_in, coff_swap_scnhdr_out): Define.
        (go32exe_mkobject): Call _bfd_go32_mkobject.
        * coffcode.h (COFF_WITH_EXTENDED_RELOC_COUNTER): Define.
        (coff_set_alignment_hook): Define function for COFF_GO32_EXE
        and COFF_GO32.
        (coff_write_relocs): Enable extended reloc counter code if
        COFF_WITH_EXTENDED_RELOC_COUNTER is defined.  Test for obj_go32.
        (coff_write_object_contents): Likewise.  Pad section headers
        for COFF_GO32 and COFF_GO32EXE.
        * cofflink.c (_bfd_coff_final_link): Test for obj_go32.
        * coffswap.h: (coff_swap_scnhdr_in, coff_swap_scnhdr_in): Allow
        overriding these functions with macros of the same name.
        * libcoff-in.h: (struct coff_tdata): New field go32.
        (obj_go32): Define.
        * libcoff.h: Regenerate.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/2] coff-go32: support extended relocations

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
Hi Jan,

> coffswap.h: (coff_swap_scnhdr_in, coff_swap_scnhdr_out): Allow
> overriding these functions with macros of the same name.

[...]

> +#ifndef coff_swap_scnhdr_in
>  static void
>  coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)

This breaks build any other COFF based target.  They all define coff_swap_scnhdr_in
and coff_swap_scnhdr_out to be target specific names, but they use the generic code.
Eg bfd/alpha-coff.c (lines 86 and 87):

  #define coff_swap_scnhdr_in alpha_ecoff_swap_scnhdr_in
  #define coff_swap_scnhdr_out alpha_ecoff_swap_scnhdr_out

I believe that this is done so that if the binutils are configured to support multiple
coff targets they will each have their own versions of the coff_swap_scnhdr_[in|out]
functions.  (Which makes sense given that the functions use macros which can be target
specific).

I think that what you need to do is to change these defines (in coff-go32.c and coff-stgo32.c):

 #define coff_swap_scnhdr_in _bfd_go32_swap_scnhdr_in
 #define coff_swap_scnhdr_out _bfd_go32_swap_scnhdr_out

to:

 #define coff_SWAP_scnhdr_in _bfd_go32_swap_scnhdr_in
 #define coff_SWAP_scnhdr_out _bfd_go32_swap_scnhdr_out

which will then ensure that the correct routines are referenced in the bfd_coff_std_swap_table
defined in coffcode.h.

Please could you check this and make sure that it does work ?

Secondly, once that is done, please could you check that a toolchain configured as:

  --enable-targets=all

will build ?  That way you can be sure that the alpha and mips coff targets also work.

Cheers
  Nick

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/2] coff-go32: support extended relocations

Sourceware - binutils list mailing list
On 2020-04-09 11:49, Nick Clifton wrote:

> Hi Jan,
>
>> coffswap.h: (coff_swap_scnhdr_in, coff_swap_scnhdr_out): Allow
>> overriding these functions with macros of the same name.
>
> [...]
>
>> +#ifndef coff_swap_scnhdr_in
>>  static void
>>  coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
>
> This breaks build any other COFF based target.  They all define coff_swap_scnhdr_in
> and coff_swap_scnhdr_out to be target specific names, but they use the generic code.
> Eg bfd/alpha-coff.c (lines 86 and 87):
>
>   #define coff_swap_scnhdr_in alpha_ecoff_swap_scnhdr_in
>   #define coff_swap_scnhdr_out alpha_ecoff_swap_scnhdr_out
>
> I believe that this is done so that if the binutils are configured to support multiple
> coff targets they will each have their own versions of the coff_swap_scnhdr_[in|out]
> functions.  (Which makes sense given that the functions use macros which can be target
> specific).
>
> I think that what you need to do is to change these defines (in coff-go32.c and coff-stgo32.c):
>
>  #define coff_swap_scnhdr_in _bfd_go32_swap_scnhdr_in
>  #define coff_swap_scnhdr_out _bfd_go32_swap_scnhdr_out
>
> to:
>
>  #define coff_SWAP_scnhdr_in _bfd_go32_swap_scnhdr_in
>  #define coff_SWAP_scnhdr_out _bfd_go32_swap_scnhdr_out
>
> which will then ensure that the correct routines are referenced in the bfd_coff_std_swap_table
> defined in coffcode.h.
>
> Please could you check this and make sure that it does work ?
>
> Secondly, once that is done, please could you check that a toolchain configured as:
>
>   --enable-targets=all
>
> will build ?  That way you can be sure that the alpha and mips coff targets also work.
>
> Cheers
>   Nick

Thanks, I see how the swap tables and these macros are used now.

However when I define coff_SWAP_scnhdr_{in,out}, I get an unused
function warning for coff_swap_scnhdr_in:

In file included from ../../binutils-gdb/bfd/coffcode.h:356,
                 from ../../binutils-gdb/bfd/coff-i386.c:618,
                 from ../../binutils-gdb/bfd/coff-stgo32.c:73:
../../binutils-gdb/bfd/coffswap.h:729:1: warning: 'coff_swap_scnhdr_in' defined but not used [-Wunused-function]
  729 | coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
      | ^~~~~~~~~~~~~~~~~~~

This can be suppressed with ATTRIBUTE_UNUSED.  But note that the
warning doesn't appear for _out.  It seems this function is used
directly in coff_write_object_contents (coffcode.h:3618,3744).  I
suppose this should be bfd_coff_swap_scnhdr_out instead?
Reply | Threaded
Open this post in threaded view
|

[PATCH v2 2/2] coff-go32: support extended relocations

Sourceware - binutils list mailing list
In reply to this post by Sourceware - binutils list mailing list
This patch extends the relocation and line number counters for
coff-go32 and coff-go32-exe to 32 bits.  As I understand it works the
same as for PE-COFF:

If the number of relocations in an object file exceeds 65534, the
NRELOC field is set to 65535 and the actual number of relocations is
stored in the VADDR field of the first relocation entry.

Executable files have no relocations, and thus the NRELOC field is
repurposed to extend NLNNO to 32-bits.

bfd/
2020-04-11  Juan Manuel Guerrero  <[hidden email]>
            Jan W. Jagersma  <[hidden email]>

        * coff-go32.c (COFF_GO32, IMAGE_SCN_LNK_NRELOC_OVFL)
        (coff_SWAP_scnhdr_in, coff_SWAP_scnhdr_out): Define.
        (_bfd_go32_swap_scnhdr_in, _bfd_go32_swap_scnhdr_out)
        (_bfd_go32_mkobject): New functions.
        * coff-stgo32.c (IMAGE_SCN_LNK_NRELOC_OVFL)
        (coff_SWAP_scnhdr_in, coff_SWAP_scnhdr_out): Define.
        (go32exe_mkobject): Call _bfd_go32_mkobject.
        * coffcode.h (COFF_WITH_EXTENDED_RELOC_COUNTER): Define.
        (coff_set_alignment_hook): Define function for COFF_GO32_EXE
        and COFF_GO32.
        (coff_write_relocs): Enable extended reloc counter code if
        COFF_WITH_EXTENDED_RELOC_COUNTER is defined.  Test for obj_go32.
        (coff_write_object_contents): Likewise.  Pad section headers
        for COFF_GO32 and COFF_GO32EXE.  Use bfd_coff_swap_scnhdr_out
        instead of coff_swap_scnhdr_out.
        * cofflink.c (_bfd_coff_final_link): Test also for obj_go32 to
        enable extended reloc counter.
        * coffswap.h: (coff_swap_scnhdr_in, coff_swap_scnhdr_out):
        Declare with ATTRIBUTE_UNUSED.
        * libcoff-in.h: (struct coff_tdata): New field go32.
        (obj_go32): Define.
        * libcoff.h: Regenerate.
---
 bfd/coff-go32.c   | 134 ++++++++++++++++++++++++++++++++++++++++++++++
 bfd/coff-stgo32.c |  30 +++++------
 bfd/coffcode.h    |  70 +++++++++++++++++++++---
 bfd/cofflink.c    |   4 +-
 bfd/coffswap.h    |   2 +
 bfd/libcoff-in.h  |   6 ++-
 6 files changed, 219 insertions(+), 27 deletions(-)

diff --git a/bfd/coff-go32.c b/bfd/coff-go32.c
index e43d5cee3d..448769362a 100644
--- a/bfd/coff-go32.c
+++ b/bfd/coff-go32.c
@@ -22,6 +22,7 @@
 #define TARGET_SYM i386_coff_go32_vec
 #define TARGET_NAME "coff-go32"
 #define TARGET_UNDERSCORE '_'
+#define COFF_GO32
 #define COFF_LONG_SECTION_NAMES
 #define COFF_SUPPORT_GNU_LINKONCE
 #define COFF_LONG_FILENAMES
@@ -42,4 +43,137 @@
 { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi"), \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
 
+/* Section contains extended relocations. */
+#define IMAGE_SCN_LNK_NRELOC_OVFL (0x01000000)
+
+#include "sysdep.h"
+#include "bfd.h"
+
+/* The following functions are not static, because they are also
+   used for coff-go32-exe (coff-stgo32.c).  */
+bfd_boolean _bfd_go32_mkobject (bfd *);
+void _bfd_go32_swap_scnhdr_in (bfd *, void *, void *);
+unsigned int _bfd_go32_swap_scnhdr_out (bfd *, void *, void *);
+
+#define coff_mkobject _bfd_go32_mkobject
+#define coff_SWAP_scnhdr_in _bfd_go32_swap_scnhdr_in
+#define coff_SWAP_scnhdr_out _bfd_go32_swap_scnhdr_out
+
 #include "coff-i386.c"
+
+bfd_boolean
+_bfd_go32_mkobject (bfd * abfd)
+{
+  const bfd_size_type amt = sizeof (coff_data_type);
+
+  abfd->tdata.coff_obj_data = bfd_zalloc (abfd, amt);
+  if (abfd->tdata.coff_obj_data == NULL)
+    return FALSE;
+
+  coff_data (abfd)->go32 = TRUE;
+
+  return TRUE;
+}
+
+void
+_bfd_go32_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
+{
+  SCNHDR *scnhdr_ext = (SCNHDR *) ext;
+  struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
+
+  memcpy (scnhdr_int->s_name, scnhdr_ext->s_name, sizeof (scnhdr_int->s_name));
+
+  scnhdr_int->s_vaddr = GET_SCNHDR_VADDR (abfd, scnhdr_ext->s_vaddr);
+  scnhdr_int->s_paddr = GET_SCNHDR_PADDR (abfd, scnhdr_ext->s_paddr);
+  scnhdr_int->s_size = GET_SCNHDR_SIZE (abfd, scnhdr_ext->s_size);
+
+  scnhdr_int->s_scnptr = GET_SCNHDR_SCNPTR (abfd, scnhdr_ext->s_scnptr);
+  scnhdr_int->s_relptr = GET_SCNHDR_RELPTR (abfd, scnhdr_ext->s_relptr);
+  scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, scnhdr_ext->s_lnnoptr);
+  scnhdr_int->s_flags = GET_SCNHDR_FLAGS (abfd, scnhdr_ext->s_flags);
+  scnhdr_int->s_nreloc = GET_SCNHDR_NRELOC (abfd, scnhdr_ext->s_nreloc);
+  scnhdr_int->s_nlnno = GET_SCNHDR_NLNNO (abfd, scnhdr_ext->s_nlnno);
+
+  /* DJGPP follows the same strategy as PE COFF.
+     Iff the file is an executable then the higher 16 bits
+     of the line number have been stored in the relocation
+     counter field.  */
+  if (abfd->flags & EXEC_P && (strcmp (scnhdr_ext->s_name, ".text") == 0))
+    {
+      scnhdr_int->s_nlnno
+ = (GET_SCNHDR_NRELOC (abfd, scnhdr_ext->s_nreloc) << 16)
+  + GET_SCNHDR_NLNNO (abfd, scnhdr_ext->s_nlnno);
+      scnhdr_int->s_nreloc = 0;
+    }
+}
+
+unsigned int
+_bfd_go32_swap_scnhdr_out (bfd * abfd, void * in, void * out)
+{
+  struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
+  SCNHDR *scnhdr_ext = (SCNHDR *) out;
+  unsigned int ret = bfd_coff_scnhsz (abfd);
+
+  memcpy (scnhdr_ext->s_name, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
+
+  PUT_SCNHDR_VADDR (abfd, scnhdr_int->s_vaddr, scnhdr_ext->s_vaddr);
+  PUT_SCNHDR_PADDR (abfd, scnhdr_int->s_paddr, scnhdr_ext->s_paddr);
+  PUT_SCNHDR_SIZE (abfd, scnhdr_int->s_size, scnhdr_ext->s_size);
+  PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr, scnhdr_ext->s_scnptr);
+  PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr, scnhdr_ext->s_relptr);
+  PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr, scnhdr_ext->s_lnnoptr);
+  PUT_SCNHDR_FLAGS (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags);
+
+  if (abfd->flags & EXEC_P && (strcmp (scnhdr_int->s_name, ".text") == 0))
+    {
+      /* DJGPP follows the same strategy as PE COFF.
+ By inference from looking at MS output, the 32 bit field
+ which is the combination of the number_of_relocs and
+ number_of_linenos is used for the line number count in
+ executables.  A 16-bit field won't do for cc1.  The MS
+ document says that the number of relocs is zero for
+ executables, but the 17-th bit has been observed to be there.
+ Overflow is not an issue: a 4G-line program will overflow a
+ bunch of other fields long before this!  */
+      PUT_SCNHDR_NLNNO (abfd, (scnhdr_int->s_nlnno & 0xffff),
+ scnhdr_ext->s_nlnno);
+      PUT_SCNHDR_NRELOC (abfd, (scnhdr_int->s_nlnno >> 16),
+ scnhdr_ext->s_nreloc);
+    }
+  else
+    {
+      /* DJGPP follows the same strategy as PE COFF.  */
+      if (scnhdr_int->s_nlnno <= MAX_SCNHDR_NLNNO)
+ PUT_SCNHDR_NLNNO (abfd, scnhdr_int->s_nlnno, scnhdr_ext->s_nlnno);
+      else
+ {
+  char buf[sizeof (scnhdr_int->s_name) + 1];
+
+  memcpy (buf, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
+  buf[sizeof (scnhdr_int->s_name)] = '\0';
+  _bfd_error_handler
+    /* xgettext:c-format */
+    (_("%pB: warning: %s: line number overflow: 0x%lx > 0xffff"),
+     abfd, buf, scnhdr_int->s_nlnno);
+  bfd_set_error (bfd_error_file_truncated);
+  PUT_SCNHDR_NLNNO (abfd, 0xffff, scnhdr_ext->s_nlnno);
+  ret = 0;
+ }
+
+      /* Although we could encode 0xffff relocs here, we do not, to be
+ consistent with other parts of bfd.  Also it lets us warn, as
+ we should never see 0xffff here w/o having the overflow flag
+ set.  */
+      if (scnhdr_int->s_nreloc < MAX_SCNHDR_NRELOC)
+ PUT_SCNHDR_NRELOC (abfd, scnhdr_int->s_nreloc, scnhdr_ext->s_nreloc);
+      else
+ {
+  /* DJGPP can deal with large #s of relocs, but not here.  */
+  PUT_SCNHDR_NRELOC (abfd, 0xffff, scnhdr_ext->s_nreloc);
+  scnhdr_int->s_flags |= IMAGE_SCN_LNK_NRELOC_OVFL;
+  PUT_SCNHDR_FLAGS (abfd, scnhdr_int->s_flags, scnhdr_ext->s_flags);
+ }
+    }
+
+  return ret;
+}
diff --git a/bfd/coff-stgo32.c b/bfd/coff-stgo32.c
index d1be578c6a..0fea119fc4 100644
--- a/bfd/coff-stgo32.c
+++ b/bfd/coff-stgo32.c
@@ -46,6 +46,9 @@
 { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi"), \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
 
+/* Section contains extended relocations. */
+#define IMAGE_SCN_LNK_NRELOC_OVFL (0x01000000)
+
 #include "sysdep.h"
 #include "bfd.h"
 #include "coff/msdos.h"
@@ -55,10 +58,17 @@ static bfd_boolean go32exe_write_object_contents (bfd *);
 static bfd_boolean go32exe_mkobject (bfd *);
 static bfd_boolean go32exe_copy_private_bfd_data (bfd *, bfd *);
 
+/* Defined in coff-go32.c.  */
+bfd_boolean _bfd_go32_mkobject (bfd *);
+void _bfd_go32_swap_scnhdr_in (bfd *, void *, void *);
+unsigned int _bfd_go32_swap_scnhdr_out (bfd *, void *, void *);
+
 #define COFF_CHECK_FORMAT go32exe_check_format
 #define COFF_WRITE_CONTENTS go32exe_write_object_contents
 #define coff_mkobject go32exe_mkobject
 #define coff_bfd_copy_private_bfd_data go32exe_copy_private_bfd_data
+#define coff_SWAP_scnhdr_in _bfd_go32_swap_scnhdr_in
+#define coff_SWAP_scnhdr_out _bfd_go32_swap_scnhdr_out
 
 #include "coff-i386.c"
 
@@ -352,32 +362,20 @@ go32exe_write_object_contents (bfd *abfd)
 static bfd_boolean
 go32exe_mkobject (bfd *abfd)
 {
-  coff_data_type *coff = NULL;
-  const bfd_size_type amt = sizeof (coff_data_type);
-
   /* Don't output to an archive.  */
   if (abfd->my_archive != NULL)
     return FALSE;
 
-  abfd->tdata.coff_obj_data = bfd_zalloc (abfd, amt);
-  if (abfd->tdata.coff_obj_data == NULL)
+  if (!_bfd_go32_mkobject (abfd))
     return FALSE;
-  coff = coff_data (abfd);
-  coff->symbols = NULL;
-  coff->conversion_table = NULL;
-  coff->raw_syments = NULL;
-  coff->relocbase = 0;
-  coff->local_toc_sym_map = 0;
 
   go32exe_create_stub (abfd);
-  if (coff->stub == NULL)
+  if (coff_data (abfd)->stub == NULL)
     {
-      bfd_release (abfd, coff);
+      bfd_release (abfd, coff_data (abfd));
       return FALSE;
     }
-  abfd->origin = coff->stub_size;
-
-/*  make_abs_section(abfd);*/ /* ??? */
+  abfd->origin = coff_data (abfd)->stub_size;
 
   return TRUE;
 }
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 3bee5d2f9d..c6569ec9cd 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -364,6 +364,10 @@ CODE_FRAGMENT
 #define GNU_LINKONCE_WT ".gnu.linkonce.wt."
 #define DOT_RELOC ".reloc"
 
+#if defined(COFF_WITH_PE) || defined(COFF_GO32_EXE) || defined(COFF_GO32)
+# define COFF_WITH_EXTENDED_RELOC_COUNTER
+#endif
+
 #if defined (COFF_LONG_SECTION_NAMES)
 /* Needed to expand the inputs to BLANKOR1TOODD.  */
 #define COFFLONGSECTIONCATHELPER(x,y)    x ## y
@@ -1964,6 +1968,39 @@ coff_set_alignment_hook (bfd *abfd, asection *section, void * scnhdr)
 }
 
 #else /* ! RS6000COFF_C */
+#if defined (COFF_GO32_EXE) || defined (COFF_GO32)
+
+static void
+coff_set_alignment_hook (bfd * abfd, asection * section, void * scnhdr)
+{
+  struct internal_scnhdr *hdr = (struct internal_scnhdr *) scnhdr;
+
+  /* Check for extended relocs.  */
+  if (hdr->s_flags & IMAGE_SCN_LNK_NRELOC_OVFL)
+    {
+      struct external_reloc dst;
+      struct internal_reloc n;
+      const file_ptr oldpos = bfd_tell (abfd);
+      const bfd_size_type relsz = bfd_coff_relsz (abfd);
+
+      if (bfd_seek (abfd, (file_ptr) hdr->s_relptr, 0) != 0)
+ return;
+      if (bfd_bread (& dst, relsz, abfd) != relsz)
+ return;
+
+      coff_swap_reloc_in (abfd, &dst, &n);
+      if (bfd_seek (abfd, oldpos, 0) != 0)
+ return;
+      section->reloc_count = hdr->s_nreloc = n.r_vaddr - 1;
+      section->rel_filepos += relsz;
+    }
+  else if (hdr->s_nreloc == 0xffff)
+    _bfd_error_handler
+      (_("%pB: warning: claims to have 0xffff relocs, without overflow"),
+       abfd);
+}
+
+#else /* ! COFF_GO32_EXE && ! COFF_GO32 */
 
 static void
 coff_set_alignment_hook (bfd *abfd ATTRIBUTE_UNUSED,
@@ -1972,6 +2009,7 @@ coff_set_alignment_hook (bfd *abfd ATTRIBUTE_UNUSED,
 {
 }
 
+#endif /* ! COFF_GO32_EXE && ! COFF_GO32 */
 #endif /* ! RS6000COFF_C */
 #endif /* ! COFF_WITH_PE */
 #endif /* ! COFF_ALIGN_IN_SECTION_HEADER */
@@ -2521,8 +2559,8 @@ coff_write_relocs (bfd * abfd, int first_undef)
       if (bfd_seek (abfd, s->rel_filepos, SEEK_SET) != 0)
  return FALSE;
 
-#ifdef COFF_WITH_PE
-      if (obj_pe (abfd) && s->reloc_count >= 0xffff)
+#ifdef COFF_WITH_EXTENDED_RELOC_COUNTER
+      if ((obj_pe (abfd) || obj_go32 (abfd)) && s->reloc_count >= 0xffff)
  {
   /* Encode real count here as first reloc.  */
   struct internal_reloc n;
@@ -3382,9 +3420,9 @@ coff_write_object_contents (bfd * abfd)
   for (current = abfd->sections; current != NULL; current =
        current->next)
     {
-#ifdef COFF_WITH_PE
+#ifdef COFF_WITH_EXTENDED_RELOC_COUNTER
       /* We store the actual reloc count in the first reloc's addr.  */
-      if (obj_pe (abfd) && current->reloc_count >= 0xffff)
+      if ((obj_pe (abfd) || obj_go32 (abfd)) && current->reloc_count >= 0xffff)
  reloc_count ++;
 #endif
       reloc_count += current->reloc_count;
@@ -3412,9 +3450,9 @@ coff_write_object_contents (bfd * abfd)
  {
   current->rel_filepos = reloc_base;
   reloc_base += current->reloc_count * bfd_coff_relsz (abfd);
-#ifdef COFF_WITH_PE
+#ifdef COFF_WITH_EXTENDED_RELOC_COUNTER
   /* Extra reloc to hold real count.  */
-  if (obj_pe (abfd) && current->reloc_count >= 0xffff)
+  if ((obj_pe (abfd) || obj_go32 (abfd)) && current->reloc_count >= 0xffff)
     reloc_base += bfd_coff_relsz (abfd);
 #endif
  }
@@ -3615,7 +3653,7 @@ coff_write_object_contents (bfd * abfd)
   SCNHDR buff;
   bfd_size_type amt = bfd_coff_scnhsz (abfd);
 
-  if (coff_swap_scnhdr_out (abfd, &section, &buff) == 0
+  if (bfd_coff_swap_scnhdr_out (abfd, &section, &buff) == 0
       || bfd_bwrite (& buff, amt, abfd) != amt)
     return FALSE;
  }
@@ -3741,7 +3779,7 @@ coff_write_object_contents (bfd * abfd)
   scnhdr.s_nlnno = current->target_index;
   scnhdr.s_flags = STYP_OVRFLO;
   amt = bfd_coff_scnhsz (abfd);
-  if (coff_swap_scnhdr_out (abfd, &scnhdr, &buff) == 0
+  if (bfd_coff_swap_scnhdr_out (abfd, &scnhdr, &buff) == 0
       || bfd_bwrite (& buff, amt, abfd) != amt)
     return FALSE;
  }
@@ -3749,6 +3787,22 @@ coff_write_object_contents (bfd * abfd)
 #endif
 #endif
 
+#if defined (COFF_GO32_EXE) || defined (COFF_GO32)
+  /* Pad section headers.  */
+  if ((abfd->flags & EXEC_P) && abfd->sections != NULL)
+    {
+      file_ptr cur_ptr = scn_base
+ + abfd->section_count * bfd_coff_scnhsz (abfd);
+      long fill_size = (abfd->sections->filepos - cur_ptr);
+      bfd_byte *b = bfd_zmalloc (fill_size);
+      if (b)
+ {
+  bfd_bwrite ((PTR)b, fill_size, abfd);
+  free (b);
+ }
+    }
+#endif
+
   /* OK, now set up the filehdr...  */
 
   /* Don't include the internal abs section in the section count */
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index e52f543ee6..0beff8397f 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -689,7 +689,7 @@ _bfd_coff_final_link (bfd *abfd,
   rel_filepos += o->reloc_count * relsz;
   /* In PE COFF, if there are at least 0xffff relocations an
      extra relocation will be written out to encode the count.  */
-  if (obj_pe (abfd) && o->reloc_count >= 0xffff)
+  if ((obj_pe (abfd) || obj_go32 (abfd)) && o->reloc_count >= 0xffff)
     rel_filepos += relsz;
  }
 
@@ -1108,7 +1108,7 @@ _bfd_coff_final_link (bfd *abfd,
 
   if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0)
     goto error_return;
-  if (obj_pe (abfd) && o->reloc_count >= 0xffff)
+  if ((obj_pe (abfd) || obj_go32 (abfd)) && o->reloc_count >= 0xffff)
     {
       /* In PE COFF, write the count of relocs as the first
  reloc.  The header overflow bit will be set
diff --git a/bfd/coffswap.h b/bfd/coffswap.h
index c4ac067a62..7c0be22107 100644
--- a/bfd/coffswap.h
+++ b/bfd/coffswap.h
@@ -725,6 +725,7 @@ coff_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   return AOUTSZ;
 }
 
+ATTRIBUTE_UNUSED
 static void
 coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
 {
@@ -751,6 +752,7 @@ coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
 #endif
 }
 
+ATTRIBUTE_UNUSED
 static unsigned int
 coff_swap_scnhdr_out (bfd * abfd, void * in, void * out)
 {
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index e4155d286f..3f0227c4ac 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -33,8 +33,9 @@ extern "C" {
 
 #define coff_data(bfd)      ((bfd)->tdata.coff_obj_data)
 #define obj_pe(bfd)      (coff_data (bfd)->pe)
+#define obj_go32(bfd)      (coff_data (bfd)->go32)
 #define obj_symbols(bfd)      (coff_data (bfd)->symbols)
-#define obj_sym_filepos(bfd)      (coff_data (bfd)->sym_filepos)
+#define obj_sym_filepos(bfd)      (coff_data (bfd)->sym_filepos)
 #define obj_relocbase(bfd)      (coff_data (bfd)->relocbase)
 #define obj_raw_syments(bfd)      (coff_data (bfd)->raw_syments)
 #define obj_raw_syment_count(bfd)     (coff_data (bfd)->raw_syment_count)
@@ -114,6 +115,9 @@ typedef struct coff_tdata
      used by ARM code.  */
   flagword flags;
 
+  /* Is this a GO32 coff file?  */
+  bfd_boolean go32;
+
   /* A stub (extra data prepended before the COFF image) and its size.
      Used by coff-go32-exe, it contains executable data that loads the
      COFF object into memory.  */
--
2.26.0

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v2 2/2] coff-go32: support extended relocations

Sourceware - binutils list mailing list
Hi Jan,

> bfd/
> 2020-04-11  Juan Manuel Guerrero  <[hidden email]>
>             Jan W. Jagersma  <[hidden email]>
>
> * coff-go32.c (COFF_GO32, IMAGE_SCN_LNK_NRELOC_OVFL)
> (coff_SWAP_scnhdr_in, coff_SWAP_scnhdr_out): Define.
> (_bfd_go32_swap_scnhdr_in, _bfd_go32_swap_scnhdr_out)
> (_bfd_go32_mkobject): New functions.
> * coff-stgo32.c (IMAGE_SCN_LNK_NRELOC_OVFL)
> (coff_SWAP_scnhdr_in, coff_SWAP_scnhdr_out): Define.
> (go32exe_mkobject): Call _bfd_go32_mkobject.
> * coffcode.h (COFF_WITH_EXTENDED_RELOC_COUNTER): Define.
> (coff_set_alignment_hook): Define function for COFF_GO32_EXE
> and COFF_GO32.
> (coff_write_relocs): Enable extended reloc counter code if
> COFF_WITH_EXTENDED_RELOC_COUNTER is defined.  Test for obj_go32.
> (coff_write_object_contents): Likewise.  Pad section headers
> for COFF_GO32 and COFF_GO32EXE.  Use bfd_coff_swap_scnhdr_out
> instead of coff_swap_scnhdr_out.
> * cofflink.c (_bfd_coff_final_link): Test also for obj_go32 to
> enable extended reloc counter.
> * coffswap.h: (coff_swap_scnhdr_in, coff_swap_scnhdr_out):
> Declare with ATTRIBUTE_UNUSED.
> * libcoff-in.h: (struct coff_tdata): New field go32.
> (obj_go32): Define.
> * libcoff.h: Regenerate.

Approved and applied.  Thanks very much for persisting with this patch.

Cheers
  Nick

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v2 2/2] coff-go32: support extended relocations

Sourceware - binutils list mailing list
On 2020-04-14 18:31, Nick Clifton wrote:

> Hi Jan,
>
>> bfd/
>> 2020-04-11  Juan Manuel Guerrero  <[hidden email]>
>>             Jan W. Jagersma  <[hidden email]>
>>
>> * coff-go32.c (COFF_GO32, IMAGE_SCN_LNK_NRELOC_OVFL)
>> (coff_SWAP_scnhdr_in, coff_SWAP_scnhdr_out): Define.
>> (_bfd_go32_swap_scnhdr_in, _bfd_go32_swap_scnhdr_out)
>> (_bfd_go32_mkobject): New functions.
>> * coff-stgo32.c (IMAGE_SCN_LNK_NRELOC_OVFL)
>> (coff_SWAP_scnhdr_in, coff_SWAP_scnhdr_out): Define.
>> (go32exe_mkobject): Call _bfd_go32_mkobject.
>> * coffcode.h (COFF_WITH_EXTENDED_RELOC_COUNTER): Define.
>> (coff_set_alignment_hook): Define function for COFF_GO32_EXE
>> and COFF_GO32.
>> (coff_write_relocs): Enable extended reloc counter code if
>> COFF_WITH_EXTENDED_RELOC_COUNTER is defined.  Test for obj_go32.
>> (coff_write_object_contents): Likewise.  Pad section headers
>> for COFF_GO32 and COFF_GO32EXE.  Use bfd_coff_swap_scnhdr_out
>> instead of coff_swap_scnhdr_out.
>> * cofflink.c (_bfd_coff_final_link): Test also for obj_go32 to
>> enable extended reloc counter.
>> * coffswap.h: (coff_swap_scnhdr_in, coff_swap_scnhdr_out):
>> Declare with ATTRIBUTE_UNUSED.
>> * libcoff-in.h: (struct coff_tdata): New field go32.
>> (obj_go32): Define.
>> * libcoff.h: Regenerate.
>
> Approved and applied.  Thanks very much for persisting with this patch.
>
> Cheers
>   Nick

Hi Nick, thanks for committing this patch.  I hope it will help to
keep the djgpp target alive :)

However don't see the changes to the ldscript template (patch 1/2).
Maybe you forgot to include it?  I didn't submit a v2 of this part
since there were no changes.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v2 2/2] coff-go32: support extended relocations

Sourceware - binutils list mailing list
Hi Jan,

> However don't see the changes to the ldscript template (patch 1/2).
> Maybe you forgot to include it?  I didn't submit a v2 of this part
> since there were no changes.

Oops!  Sorry about that.  Now applied...

Cheers
  Nick