diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index ff6e0058270..26fe092678f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,20 @@
+1999-05-10  DJ Delorie  <dj@cygnus.com>
+
+	* ecoff.c (_bfd_ecoff_write_armap): give the symtab element a
+	reasonable mode until "ar x" is smart enough to skip it (fixes
+	gcc/libgcc.a builds on mips-ecoff targets
+
+	* coffcode.h (styp_to_sec_flags): Explain how COMDATs are supposed
+	to work.  Hack to support MS import libraries, which use different
+	COMDAT types than GNU.
+	(coff_slurp_symbol_table): C_SECTION symbols are local; they refer
+	to implied zero-length sections (see peicode below)
+	* coffgen.c (coff_get_normalized_symtab): Properly read long MS
+	filename symbols, which use one *or more* auxents.
+	* coffswap.h (coff_swap_aux_in): ditto
+	* peicode.h (coff_swap_sym_in): Build the implied zero-length
+	sections
+	
 Tue May 11 15:51:58 1999  Jeffrey A Law  (law@cygnus.com)
 
 	* elf32-v850.c (v850_elf_howto_table): Make partial_inplace false
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 383719c00c9..bee6b666e47 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -588,6 +588,12 @@ styp_to_sec_flags (abfd, hdr, name)
          can't call slurp_symtab, because the linker doesn't want the
          swapped symbols.  */
 
+      /* COMDAT sections are special.  The first symbol is the section
+	 symbol, which tells what kind of COMDAT section it is.  The
+	 *second* symbol is the "comdat symbol" - the one with the
+	 unique name.  GNU uses the section symbol for the unique
+	 name; MS uses ".text" for every comdat section.  Sigh.  - DJ */
+
       if (_bfd_coff_get_external_symbols (abfd))
 	{
 	  bfd_byte *esym, *esymend;
@@ -629,10 +635,23 @@ styp_to_sec_flags (abfd, hdr, name)
 					    isym.n_type, isym.n_sclass,
 					    0, isym.n_numaux, (PTR) &aux);
 
+		      /* FIXME: Microsoft uses NODUPLICATES and
+			 ASSOCIATIVE, but gnu uses ANY and SAME_SIZE.
+			 Unfortunately, gnu doesn't do the comdat
+			 symbols right.  So, until we can fix it to do
+			 the right thing, we are temporarily disabling
+			 comdats for the MS types (they're used in
+			 DLLs and C++, but we don't support *their*
+			 C++ libraries anyway - DJ */
+
 		      switch (aux.x_scn.x_comdat)
 			{
 			case IMAGE_COMDAT_SELECT_NODUPLICATES:
+#if 0
 			  sec_flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
+#else
+			  sec_flags &= ~SEC_LINK_ONCE;
+#endif
 			  break;
 
 			default:
@@ -649,8 +668,12 @@ styp_to_sec_flags (abfd, hdr, name)
 			  break;
 
 			case IMAGE_COMDAT_SELECT_ASSOCIATIVE:
+#if 0
 			  /* FIXME: This is not currently implemented.  */
 			  sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
+#else
+			  sec_flags &= ~SEC_LINK_ONCE;
+#endif
 			  break;
 			}
 
@@ -3581,6 +3604,11 @@ coff_slurp_symbol_table (abfd)
 #ifdef COFF_WITH_PE
 	      if (src->u.syment.n_sclass == C_NT_WEAK)
 		dst->symbol.flags = BSF_WEAK;
+	      if (src->u.syment.n_sclass == C_SECTION
+		  && src->u.syment.n_scnum > 0)
+		{
+		  dst->symbol.flags = BSF_LOCAL;
+		}
 #endif
 
 	      if (src->u.syment.n_sclass == C_WEAKEXT)
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index df413833bd3..a06ed663b3d 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -1747,9 +1747,19 @@ coff_get_normalized_symtab (abfd)
 	  else
 	    {
 	      /* ordinary short filename, put into memory anyway */
-	      internal_ptr->u.syment._n._n_n._n_offset = (long)
-		copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname,
-			   FILNMLEN);
+	      if (internal_ptr->u.syment.n_numaux > 1
+		  && coff_data (abfd)->pe)
+		{
+		  internal_ptr->u.syment._n._n_n._n_offset = (long)
+		    copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname,
+			       internal_ptr->u.syment.n_numaux * symesz);
+		}
+	      else
+		{
+		  internal_ptr->u.syment._n._n_n._n_offset = (long)
+		    copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname,
+			       FILNMLEN);
+		}
 	    }
 	}
       else
diff --git a/bfd/coffswap.h b/bfd/coffswap.h
index ae30a5d966f..9bc180f4de8 100644
--- a/bfd/coffswap.h
+++ b/bfd/coffswap.h
@@ -422,7 +422,16 @@ coff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
 #if FILNMLEN != E_FILNMLEN
 	    -> Error, we need to cope with truncating or extending FILNMLEN!;
 #else
-	    memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
+	    if (numaux > 1)
+	      {
+		if (indx == 0)
+		  memcpy (in->x_file.x_fname, ext->x_file.x_fname,
+			  numaux * sizeof (AUXENT));
+	      }
+	    else
+	      {
+		memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
+	      }
 #endif
 	  }
       goto end;
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index d5c6f85a717..32a2309e941 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -3181,7 +3181,14 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
      armap.  */
   hdr.ar_uid[0] = '0';
   hdr.ar_gid[0] = '0';
+#if 0
   hdr.ar_mode[0] = '0';
+#else
+  /* Building gcc ends up extracting the armap as a file - twice. */
+  hdr.ar_mode[0] = '6';
+  hdr.ar_mode[1] = '4';
+  hdr.ar_mode[2] = '4';
+#endif
 
   sprintf (hdr.ar_size, "%-10d", (int) mapsize);
 
diff --git a/bfd/peicode.h b/bfd/peicode.h
index 79d16e5abe9..f15e0ec28ba 100644
--- a/bfd/peicode.h
+++ b/bfd/peicode.h
@@ -504,6 +504,7 @@ coff_swap_sym_in (abfd, ext1, in1)
     {
       in->n_value = 0x0;
 
+#if 0
       /* FIXME: This is clearly wrong.  The problem seems to be that
          undefined C_SECTION symbols appear in the first object of a
          MS generated .lib file, and the symbols are not defined
@@ -518,6 +519,55 @@ coff_swap_sym_in (abfd, ext1, in1)
       /*      in->n_scnum = 3; */
       /*    else */
       /*      in->n_scnum = 2; */
+#else
+      /* Create synthetic empty sections as needed.  DJ */
+      if (in->n_scnum == 0)
+	{
+	  asection *sec;
+	  for (sec=abfd->sections; sec; sec=sec->next)
+	    {
+	      if (strcmp (sec->name, in->n_name) == 0)
+		{
+		  in->n_scnum = sec->target_index;
+		  break;
+		}
+	    }
+	}
+      if (in->n_scnum == 0)
+	{
+	  int unused_section_number = 0;
+	  asection *sec;
+	  char *name;
+	  for (sec=abfd->sections; sec; sec=sec->next)
+	    if (unused_section_number <= sec->target_index)
+	      unused_section_number = sec->target_index+1;
+
+	  name = bfd_alloc (abfd, strlen (in->n_name) + 10);
+	  if (name == NULL)
+	    return;
+	  strcpy (name, in->n_name);
+	  sec = bfd_make_section_anyway (abfd, name);
+
+	  sec->vma = 0;
+	  sec->lma = 0;
+	  sec->_cooked_size = 0;
+	  sec->_raw_size = 0;
+	  sec->filepos = 0;
+	  sec->rel_filepos = 0;
+	  sec->reloc_count = 0;
+	  sec->line_filepos = 0;
+	  sec->lineno_count = 0;
+	  sec->userdata = NULL;
+	  sec->next = (asection *) NULL;
+	  sec->flags = 0;
+	  sec->alignment_power = 2;
+	  sec->flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD;
+
+	  sec->target_index = unused_section_number;
+
+	  in->n_scnum = unused_section_number;
+	}
+#endif
     }
 
 #ifdef coff_swap_sym_in_hook