[gnu.utils.bug] hacking COFF

eirik@labs.labs.tek.com (Eirik Fuller) (11/15/89)

I just finished bootstrapping gcc on a sun386 with the GNU assembler
and the GNU linker.  In order to do this, I had to modify robotussin.
Because I have no idea what effect the changes I made will have on
other COFF systems, I wrapped them in "#ifdef sun386".

I also made some changes to gcc source files in order to use the GNU
toolset; that code should soon appear on bug-gcc (gnu.gcc.bug).

After applying these diffs, compile with -DPORTAR -DCOFF_ENCAPSULATE
Depending on how you configure gcc, you might also want -Dnounderscore,
though I did not wind up using it.

If you run out of stack space while running GNU ar or GNU ld (this
manifests itself as a segment violation), you should link in alloca.c
from the gcc sources, and get rid of the "#define alloca" in ar.c and
ld.c; or you could try to get Sun to fix this annoying "feature".

*** robotussin.c	Sat Apr 22 21:21:03 1989
--- sun386-robotussin.c	Sat Nov 11 21:06:22 1989
***************
*** 71,76 ****
--- 71,84 ----
  #define sizeof_reloc (RELSZ)
  #define sizeof_section (SCNHSZ)
  #define sizeof_coff_header (FILHSZ)
+ /* 
+   Without the following, compiling this is a pain on a BSD4.3 Vax.
+   Though that might not seem useful, the compatibility of byte order
+   between a Vax and a 386 can come in handy for cross-debugging
+ */
+ #ifdef NO_VFPRINTF
+ #define vfprintf(fp, format, ap) _doprnt (format, ap, fp)
+ #endif /* not HAVE_VPRINTF */
  
  extern long lseek ();
  extern void exit ();
***************
*** 161,166 ****
--- 169,185 ----
  	}
      }
  
+ #ifdef sun386
+ /*
+   The purpose of the following kludge is to cope with the discrepancy
+   between coff_data_header.s_vaddr and coff_text_header.s_size; in a BSD
+   object file, they are assumed equal.  It should be ok to use
+   coff_data_header.s_paddr, since it has no other apparent use.
+ */
+   coff_data_header.s_paddr = coff_text_header.s_size;
+   coff_bss_header.s_paddr = coff_data_header.s_size + coff_text_header.s_size;
+ #endif
+ 
    /*
     ** Pass1 thru the symbol table - count usable symbols and map
     ** old symbol #'s into new ones (as used by relocation
***************
*** 194,199 ****
--- 213,226 ----
  	  if (verbose_flag)
  	    printf ("map %d to %d\n", i, symbol_count);
  	  symbol_map[i] = symbol_count++;
+ #ifdef sun386
+ 	  if (coff_sym_listp[i].n_scnum == data_sect_num)
+ 	    coff_sym_listp[i].n_value -=
+ 	      coff_data_header.s_vaddr - coff_data_header.s_paddr;
+ 	  else if (coff_sym_listp[i].n_scnum == bss_sect_num)
+ 	    coff_sym_listp[i].n_value -=
+ 	      coff_bss_header.s_vaddr - coff_bss_header.s_paddr;
+ #endif
  	} 
        else
  	{
***************
*** 404,409 ****
--- 431,440 ----
      {
        if (read (fd_in, &coff_reloc, sizeof_reloc) != sizeof_reloc)
  	error ("can't read relocation entry");
+ #ifdef sun386
+       coff_reloc.r_vaddr -=
+ 	section_headerp->s_vaddr - section_headerp->s_paddr;
+ #endif
        if (verbose_flag)
  	printf ("vaddr = 0x%x, symndx = %d\n", coff_reloc.r_vaddr, coff_reloc.r_symndx);
        /*
***************
*** 454,459 ****
--- 485,520 ----
  	{
  	  if (symbol_map[coff_reloc.r_symndx] == -1)
  	    error ("Oops! possible bug - reloc reference to ignored symbol");
+ #ifdef sun386
+ 	  {
+ 	    int offset=0;
+ 	    switch (-symbol_map[coff_reloc.r_symndx])
+ 	      {
+ 	      case N_DATA:
+ 		offset = coff_data_header.s_vaddr - coff_data_header.s_paddr;
+ 		break;
+ 	      case N_BSS:
+ 		offset = coff_bss_header.s_vaddr - coff_bss_header.s_paddr;
+ 		break;
+ 	      }
+ 	    switch (coff_reloc.r_type)
+ 	      {
+ 	      case R_RELBYTE:
+ 		*((char *) (text_and_data + coff_reloc.r_vaddr)) -= offset;
+ 		break;
+ 	      case R_RELWORD:
+ 		*((short *) (text_and_data + coff_reloc.r_vaddr)) -= offset;
+ 		break;
+ 	      case R_RELLONG:
+ 	      case R_DIR32:
+ 	      case R_PCRLONG:
+ 		*((int *) (text_and_data + coff_reloc.r_vaddr)) -= offset;
+ 		break;
+ 	      default:
+ 		error ("unknown relocation type 0%o", coff_reloc.r_type);
+ 	      }
+ 	  }
+ #endif
  	  reloc_infop->r_symbolnum = -symbol_map[coff_reloc.r_symndx];
  	  reloc_infop->r_extern = 0;
  	}
***************
*** 461,466 ****
--- 522,531 ----
         ** COFF address includes the section address - BSD doesn't, so
         ** subtract it out.
         */
+ #ifdef sun386
+       coff_reloc.r_vaddr +=
+ 	section_headerp->s_vaddr - section_headerp->s_paddr;
+ #endif
        reloc_infop->r_address = coff_reloc.r_vaddr - section_headerp->s_vaddr;
        switch (coff_reloc.r_type)
  	{