$OpenBSD: patch-bfd_coffgen_c,v 1.2 2009/12/09 16:55:51 ckuethe Exp $
--- bfd/coffgen.c.orig	Wed Aug 13 19:38:22 2008
+++ bfd/coffgen.c	Sun Dec  6 21:48:53 2009
@@ -687,6 +687,20 @@ coff_renumber_symbols (bfd *bfd_ptr, int *first_undef)
 	      if (last_file != NULL)
 		last_file->n_value = native_index;
 	      last_file = &(s->u.syment);
+	      if (bfd_get_arch (bfd_ptr) == bfd_arch_avr
+		  && bfd_coff_long_filenames (bfd_ptr)
+		  && s->u.syment.n_numaux > 0)
+		{
+		  /* AVR COFF records long filenames in successive aux
+		     records.  Adjust the number of aux records
+		     required here, so the renumbering will account
+		     for them. */
+		  unsigned int filnmlen = bfd_coff_filnmlen (bfd_ptr);
+		  unsigned int namelen = strlen (coff_symbol_ptr->symbol.name);
+		  unsigned int n = (namelen + filnmlen - 1) / filnmlen;
+
+		  s->u.syment.n_numaux = n > NAUXENTS? NAUXENTS: n;
+		}
 	    }
 	  else
 	    /* Modify the symbol values according to their section and
@@ -815,6 +829,20 @@ coff_fix_symbol_name (bfd *abfd,
 	{
 	  if (name_length <= filnmlen)
 	    strncpy (auxent->x_file.x_fname, name, filnmlen);
+	  else if (bfd_get_arch (abfd) == bfd_arch_avr)
+	    {
+	      /* AVR COFF records long filenames in successive aux records. */
+	      int i = 1;
+	      while (name_length > filnmlen && i < NAUXENTS)
+		{
+		  strncpy (auxent->x_file.x_fname, name, filnmlen);
+		  name += filnmlen;
+		  name_length -= filnmlen;
+		  i++;
+		  auxent = &(native + i)->u.auxent;
+		}
+	      strncpy (auxent->x_file.x_fname, name, filnmlen);
+	    }
 	  else
 	    {
 	      auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE;
@@ -1218,7 +1246,11 @@ coff_write_symbols (bfd *abfd)
 		  if (bfd_bwrite (".file", (bfd_size_type) 6, abfd) != 6)
 		    return FALSE;
 		}
-	      maxlen = bfd_coff_filnmlen (abfd);
+	      if (bfd_get_arch (abfd) == bfd_arch_avr)
+		/* AVR COFF handles long file names in aux records. */
+		maxlen = name_length;
+	      else
+		maxlen = bfd_coff_filnmlen (abfd);
 	    }
 	  else
 	    maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN;
@@ -1655,14 +1687,27 @@ coff_get_normalized_symtab (bfd *abfd)
 	    {
 	      /* Ordinary short filename, put into memory anyway.  The
                  Microsoft PE tools sometimes store a filename in
-                 multiple AUX entries.  */
+                 multiple AUX entries.
+		 AVR COFF does it that way, too. */
 	      if (internal_ptr->u.syment.n_numaux > 1
-		  && coff_data (abfd)->pe)
-		internal_ptr->u.syment._n._n_n._n_offset =
-		  ((bfd_hostptr_t)
-		   copy_name (abfd,
-			      (internal_ptr + 1)->u.auxent.x_file.x_fname,
-			      internal_ptr->u.syment.n_numaux * symesz));
+		  && (coff_data (abfd)->pe
+		      || (bfd_get_arch (abfd) == bfd_arch_avr)))
+		{
+		  char *b;
+		  unsigned int i;
+
+		  /* We allocate enough storage to fit the contents of
+		     this many aux records, and simply append a \0.
+		     This ensures the string will always be
+		     terminated, even in the case where it just fit
+		     into the aux records. */
+		  b = (char *) bfd_alloc (abfd,
+					  internal_ptr->u.syment.n_numaux * FILNMLEN + 1);
+		  internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) b;
+		  b[internal_ptr->u.syment.n_numaux * FILNMLEN] = '\0';
+		  for (i = 0; i < internal_ptr->u.syment.n_numaux; i++, b += FILNMLEN)
+		    memcpy (b, (internal_ptr + i + 1)->u.auxent.x_file.x_fname, FILNMLEN);
+		}
 	      else
 		internal_ptr->u.syment._n._n_n._n_offset =
 		  ((bfd_hostptr_t)
@@ -1768,9 +1813,9 @@ coff_bfd_make_debug_symbol (bfd *abfd,
 
   if (new == NULL)
     return NULL;
-  /* @@ The 10 is a guess at a plausible maximum number of aux entries
-     (but shouldn't be a constant).  */
-  amt = sizeof (combined_entry_type) * 10;
+  /* @@ The NAUXENTS is a guess at a plausible maximum number of aux
+     entries (but shouldn't be a constant).  */
+  amt = sizeof (combined_entry_type) * (NAUXENTS + 1);
   new->native = bfd_zalloc (abfd, amt);
   if (!new->native)
     return NULL;
