]> git.pld-linux.org Git - packages/crossavr-binutils.git/commitdiff
- updated for 2.18.50.0.9
authorkosmo <kosmo@pld-linux.org>
Thu, 16 Oct 2008 10:01:08 +0000 (10:01 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    crossavr-binutils-coff-avr.patch -> 1.4

crossavr-binutils-coff-avr.patch

index fa93be4f260e772f5b87cc454b2e7745951276ea..cd054bd89cc4e5eb10c119176a0a1030f47b71d2 100644 (file)
-diff -uNdr binutils-2.17.50.0.18-old/bfd/Makefile.am binutils-2.17.50.0.18/bfd/Makefile.am
---- binutils-2.17.50.0.18-old/bfd/Makefile.am  2007-08-01 15:11:47.000000000 +0200
-+++ binutils-2.17.50.0.18/bfd/Makefile.am      2007-10-20 16:45:33.000000000 +0200
-@@ -208,6 +208,8 @@
-       coff-apollo.lo \
-       coff-arm.lo \
-       coff-aux.lo \
-+      coff-avr.lo \
-+      coff-ext-avr.lo \
-       coff-h8300.lo \
-       coff-h8500.lo \
-       coff-i386.lo \
-@@ -387,6 +389,8 @@
-       coff-apollo.c \
-       coff-arm.c \
-       coff-aux.c \
-+      coff-avr.c \
-+      coff-ext-avr.c \
-       coff-h8300.c \
-       coff-h8500.c \
-       coff-i386.c \
-@@ -1186,6 +1190,12 @@
-   coff-m68k.c $(INCDIR)/hashtab.h $(INCDIR)/coff/m68k.h \
-   $(INCDIR)/coff/internal.h libcoff.h $(INCDIR)/bfdlink.h \
-   coffcode.h coffswap.h
-+coff-avr.lo: coff-avr.c $(INCDIR)/filenames.h $(INCDIR)/coff/avr.h \
-+  $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
-+  libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
-+coff-ext-avr.lo: coff-ext-avr.c $(INCDIR)/filenames.h $(INCDIR)/coff/avr.h \
-+  $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
-+  libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
- coff-h8300.lo: coff-h8300.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
-   $(INCDIR)/bfdlink.h genlink.h $(INCDIR)/coff/h8300.h \
-   $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
-diff -uNdr binutils-2.17.50.0.18-old/bfd/Makefile.in binutils-2.17.50.0.18/bfd/Makefile.in
---- binutils-2.17.50.0.18-old/bfd/Makefile.in  2007-10-20 15:38:12.000000000 +0200
-+++ binutils-2.17.50.0.18/bfd/Makefile.in      2007-10-20 16:45:33.000000000 +0200
-@@ -458,6 +458,8 @@
-       coff-apollo.lo \
-       coff-arm.lo \
-       coff-aux.lo \
-+      coff-avr.lo \
-+      coff-ext-avr.lo \
-       coff-h8300.lo \
-       coff-h8500.lo \
-       coff-i386.lo \
-@@ -637,6 +639,8 @@
-       coff-apollo.c \
-       coff-arm.c \
-       coff-aux.c \
-+      coff-avr.c \
-+      coff-ext-avr.c \
-       coff-h8300.c \
-       coff-h8500.c \
-       coff-i386.c \
-@@ -1767,6 +1771,12 @@
-   coff-m68k.c $(INCDIR)/hashtab.h $(INCDIR)/coff/m68k.h \
-   $(INCDIR)/coff/internal.h libcoff.h $(INCDIR)/bfdlink.h \
-   coffcode.h coffswap.h
-+coff-avr.lo: coff-avr.c $(INCDIR)/filenames.h $(INCDIR)/coff/avr.h \
-+  $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
-+  libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
-+coff-ext-avr.lo: coff-ext-avr.c $(INCDIR)/filenames.h $(INCDIR)/coff/avr.h \
-+  $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
-+  libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
- coff-h8300.lo: coff-h8300.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
-   $(INCDIR)/bfdlink.h genlink.h $(INCDIR)/coff/h8300.h \
-   $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
-diff -uNdr binutils-2.17.50.0.18-old/bfd/coff-avr.c binutils-2.17.50.0.18/bfd/coff-avr.c
---- binutils-2.17.50.0.18-old/bfd/coff-avr.c   1970-01-01 01:00:00.000000000 +0100
-+++ binutils-2.17.50.0.18/bfd/coff-avr.c       2007-10-20 16:45:33.000000000 +0200
-@@ -0,0 +1,609 @@
-+/* BFD back-end for Atmel AVR COFF files.
-+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2003
-+   Free Software Foundation, Inc.
-+   Created mostly by substituting "avr" for "i860" in coff-i860.c
+--- binutils-2.18.orig/binutils/Makefile.am    Tue Oct 23 21:44:42 2007
++++ binutils-2.18/binutils/Makefile.am Tue Oct 23 22:22:40 2007
+@@ -98,7 +98,7 @@
+       resbin.c rescoff.c resrc.c resres.c \
+       size.c srconv.c stabs.c strings.c sysdump.c \
+       unwind-ia64.c version.c \
+-      windres.c winduni.c wrstabs.c \
++      windres.c winduni.c wrcoff.c wrstabs.c \
+       windmc.c mclex.c
+ GENERATED_CFILES = \
+@@ -106,7 +106,7 @@
+       defparse.c deflex.c nlmheader.c rcparse.c mcparse.c
+ DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c
+-WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c
++WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c wrcoff.c
+ # Code shared by all the binutils.
+ BULIBS = bucomm.c version.c filemode.c
+--- binutils-2.18.orig/binutils/Makefile.in    Tue Oct 23 21:44:42 2007
++++ binutils-2.18/binutils/Makefile.in Tue Oct 23 22:26:52 2007
+@@ -129,7 +129,7 @@
+ nm_new_OBJECTS = $(am_nm_new_OBJECTS)
+ nm_new_LDADD = $(LDADD)
+ am__objects_2 = rddbg.$(OBJEXT) debug.$(OBJEXT) stabs.$(OBJEXT) \
+-      ieee.$(OBJEXT) rdcoff.$(OBJEXT)
++      ieee.$(OBJEXT) rdcoff.$(OBJEXT) wrcoff.$(OBJEXT)
+ am__objects_3 = $(am__objects_2) wrstabs.$(OBJEXT)
+ am_objcopy_OBJECTS = objcopy.$(OBJEXT) not-strip.$(OBJEXT) \
+       rename.$(OBJEXT) $(am__objects_3) $(am__objects_1)
+@@ -418,7 +418,7 @@
+       resbin.c rescoff.c resrc.c resres.c \
+       size.c srconv.c stabs.c strings.c sysdump.c \
+       unwind-ia64.c version.c \
+-      windres.c winduni.c wrstabs.c \
++      windres.c winduni.c wrcoff.c wrstabs.c \
+       windmc.c mclex.c
+ GENERATED_CFILES = \
+@@ -426,7 +426,7 @@
+       defparse.c deflex.c nlmheader.c rcparse.c mcparse.c
+ DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c
+-WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c
++WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c wrcoff.c
+ # Code shared by all the binutils.
+ BULIBS = bucomm.c version.c filemode.c
+--- binutils-2.18.orig/binutils/bucomm.c       Tue Oct 23 21:44:42 2007
++++ binutils-2.18/binutils/bucomm.c    Tue Oct 23 22:18:44 2007
+@@ -501,6 +501,32 @@
+   return ret;
+ }
++/* Return the basename of "file", i. e. everything minus whatever
++   directory part has been provided.  Stolen from bfd/archive.c.
++   Should we also handle the VMS case (as in bfd/archive.c)?  */
++const char *
++bu_basename (file)
++     const char *file;
++{
++  const char *filename = strrchr (file, '/');
 +
-+This file is part of BFD, the Binary File Descriptor library.
++#ifdef HAVE_DOS_BASED_FILE_SYSTEM
++  {
++    /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
++    char *bslash = strrchr (file, '\\');
++    if (filename == NULL || (bslash != NULL && bslash > filename))
++      filename = bslash;
++    if (filename == NULL && file[0] != '\0' && file[1] == ':')
++      filename = file + 1;
++  }
++#endif
++  if (filename != (char *) NULL)
++    filename++;
++  else
++    filename = file;
++  return filename;
++}
 +
-+This program is free software; you can redistribute it and/or modify
-+it under the terms of the GNU General Public License as published by
-+the Free Software Foundation; either version 2 of the License, or
-+(at your option) any later version.
+ /* Returns the size of the named file.  If the file does not
+    exist, or if it is not a real file, then a suitable non-fatal
+    error message is printed and zero is returned.  */
+--- binutils-2.18.orig/binutils/bucomm.h       Tue Oct 23 21:44:42 2007
++++ binutils-2.18/binutils/bucomm.h    Tue Oct 23 22:18:44 2007
+@@ -54,6 +54,8 @@
+ off_t get_file_size (const char *);
++const char *bu_basename PARAMS ((const char *));
 +
-+This program is distributed in the hope that it will be useful,
-+but WITHOUT ANY WARRANTY; without even the implied warranty of
-+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+GNU General Public License for more details.
+ extern char *program_name;
+ /* filemode.c */
+--- binutils-2.18.orig/binutils/budbg.h        Tue Oct 23 21:44:42 2007
++++ binutils-2.18/binutils/budbg.h     Tue Oct 23 22:18:44 2007
+@@ -51,8 +51,11 @@
+ extern bfd_boolean write_ieee_debugging_info (bfd *, void *);
+-/* Routine used to read COFF debugging information.  */
++/* Routine used to read and write COFF debugging information.  */
+ extern bfd_boolean parse_coff (bfd *, asymbol **, long, void *);
 +
-+You should have received a copy of the GNU General Public License
-+along with this program; if not, write to the Free Software
-+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
++extern bfd_boolean write_coff_debugging_info
++  (bfd *abfd, void *, long *symcountp, asymbol ***);
+ #endif
+--- binutils-2.18.orig/binutils/debug.c.orig   Mon Aug  6 21:55:10 2007
++++ binutils-2.18/binutils/debug.c     Tue Oct 23 23:43:19 2007
+@@ -31,6 +31,7 @@
+ #include <assert.h>
+ #include "bfd.h"
+ #include "libiberty.h"
++#include "bucomm.h"
+ #include "debug.h"
+ /* Global information we keep for debugging.  A pointer to this
+@@ -552,6 +553,19 @@
+   struct debug_type *t;
+ };
++/* Simple list, used for pathname translations. */
++struct xlat_list
++{
++  /* Next string on list. */
++  struct xlat_list *next;
++  /* Old part to match against. */
++  const char *old;
++  size_t olen;
++  /* New part to replace. */
++  const char *newstr;
++  size_t nlen;
++};
 +
-+#include "bfd.h"
-+#include "sysdep.h"
-+#include "libbfd.h"
+ /* Local functions.  */
+ static void debug_error (const char *);
+@@ -588,6 +602,11 @@
+   (struct debug_handle *, struct debug_type *, struct debug_type *);
+ static bfd_boolean debug_class_type_samep
+   (struct debug_handle *, struct debug_type *, struct debug_type *);
++static const char *debug_xlat_pathname (const char *);
 +
-+#include "coff/avr.h"
++/* List of pathname translations. */
++static struct xlat_list *xlat, *xltail;
++static bfd_boolean xlat_basename;
\f
+ /* Issue an error message.  */
+@@ -680,6 +699,8 @@
+   if (name == NULL)
+     name = "";
++  else
++    name = debug_xlat_pathname (name);
+   nfile = (struct debug_file *) xmalloc (sizeof *nfile);
+   memset (nfile, 0, sizeof *nfile);
+@@ -720,6 +741,8 @@
+   if (name == NULL)
+     name = "";
++  else
++    name = debug_xlat_pathname (name);
+   if (info->current_unit == NULL)
+     {
+@@ -3369,4 +3392,70 @@
+     }
+   return TRUE;
++}
 +
-+#include "coff/internal.h"
++/* Register a pathname translation. */
++void
++debug_register_pathname_xlat (oname, nname)
++     const char *oname;
++     const char *nname;
++{
++  struct xlat_list *xlp;
 +
-+#include "libcoff.h"
++  /* Special case: if oname is given as NULL, this means the
++     --basename option has been given to objcopy. */
++  if (oname == NULL)
++    {
++      xlat_basename = TRUE;
++      return;
++    }
 +
-+static bfd_reloc_status_type coff_avr_reloc
-+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-+static reloc_howto_type *coff_avr_rtype_to_howto
-+  PARAMS ((bfd *, asection *, struct internal_reloc *,
-+         struct coff_link_hash_entry *, struct internal_syment *,
-+         bfd_vma *));
-+static const bfd_target * coff_avr_object_p PARAMS ((bfd *));
-+
-+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
-+/* The page size is a guess based on ELF.  */
-+
-+#define COFF_PAGE_SIZE 0x1000
-+
-+/* For some reason when using avr COFF the value stored in the .text
-+   section for a reference to a common symbol is the value itself plus
-+   any desired offset.  Ian Taylor, Cygnus Support.  */
-+
-+/* If we are producing relocateable output, we need to do some
-+   adjustments to the object file that are not done by the
-+   bfd_perform_relocation function.  This function is called by every
-+   reloc type to make any required adjustments.  */
++  xlp = (struct xlat_list *) xmalloc (sizeof (struct xlat_list));
++  xlp->next = NULL;
++  if (xlat == NULL)
++    xlat = xltail = xlp;
++  else
++    {
++      xltail->next = xlp;
++      xltail = xlp;
++    }
++  xlp->old = oname;
++  xlp->newstr = nname;
++  xlp->olen = strlen (oname);
++  xlp->nlen = strlen (nname);
++}
 +
-+static bfd_reloc_status_type
-+coff_avr_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
-+               error_message)
-+     bfd *abfd;
-+     arelent *reloc_entry;
-+     asymbol *symbol;
-+     PTR data;
-+     asection *input_section ATTRIBUTE_UNUSED;
-+     bfd *output_bfd;
-+     char **error_message ATTRIBUTE_UNUSED;
++/* Try to translate a pathname. */
++static const char *
++debug_xlat_pathname (oname)
++     const char *oname;
 +{
-+  symvalue diff;
++  struct xlat_list *xlp;
++  char *cp;
++  size_t olen;
 +
-+  if (output_bfd == (bfd *) NULL)
-+    return bfd_reloc_continue;
++  if (xlat_basename)
++    return bu_basename (oname);  
 +
-+  if (bfd_is_com_section (symbol->section))
-+    {
-+      /* We are relocating a common symbol.  The current value in the
-+       object file is ORIG + OFFSET, where ORIG is the value of the
-+       common symbol as seen by the object file when it was compiled
-+       (this may be zero if the symbol was undefined) and OFFSET is
-+       the offset into the common symbol (normally zero, but may be
-+       non-zero when referring to a field in a common structure).
-+       ORIG is the negative of reloc_entry->addend, which is set by
-+       the CALC_ADDEND macro below.  We want to replace the value in
-+       the object file with NEW + OFFSET, where NEW is the value of
-+       the common symbol which we are going to put in the final
-+       object file.  NEW is symbol->value.  */
-+      diff = symbol->value + reloc_entry->addend;
-+    }
-+  else
++  olen = strlen (oname);
++  for (xlp = xlat; xlp; xlp = xlp->next)
 +    {
-+      /* For some reason bfd_perform_relocation always effectively
-+       ignores the addend for a COFF target when producing
-+       relocateable output.  This seems to be always wrong for 860
-+       COFF, so we handle the addend here instead.  */
-+      diff = reloc_entry->addend;
++      if (xlp->olen > olen)
++      /* This cannot be our turn. */
++      continue;
++      /* Since we have pre-computed all our length values to avoid
++       repetitively computing them, just use memcmp() since it's
++       faster than strcmp(). */
++      if (memcmp (xlp->old, oname, xlp->olen) == 0)
++      {
++        cp = (char *) xmalloc (olen + xlp->nlen - xlp->olen + 1);
++        memcpy (cp, xlp->newstr, xlp->nlen);
++        memcpy (cp + xlp->nlen, oname + xlp->olen,
++                olen - xlp->olen + 1);
++        return cp;
++      }
 +    }
 +
-+#define DOIT(x) \
-+  x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
++  /* Not found, pass the original name on. */
++  return oname;
+ }
+--- binutils-2.18.orig/binutils/debug.h        Tue Oct 23 21:44:43 2007
++++ binutils-2.18/binutils/debug.h     Tue Oct 23 22:18:44 2007
+@@ -440,6 +440,12 @@
+ extern bfd_boolean debug_start_source (void *, const char *);
++/* Register a pathname translation for source (and include) filenames.
++   This is used by the --change-pathname option of objcopy. */
 +
-+    if (diff != 0)
-+      {
-+      reloc_howto_type *howto = reloc_entry->howto;
-+      unsigned char *addr = (unsigned char *) data + reloc_entry->address;
++extern void debug_register_pathname_xlat
++  PARAMS ((const char *, const char *));
 +
-+      switch (howto->size)
-+        {
-+        case 0:
-+          {
-+            char x = bfd_get_8 (abfd, addr);
-+            DOIT (x);
-+            bfd_put_8 (abfd, x, addr);
-+          }
-+          break;
+ /* Record a function definition.  This implicitly starts a function
+    block.  The debug_type argument is the type of the return value.
+    The bfd_boolean indicates whether the function is globally visible.
+--- binutils-2.18.orig/binutils/objcopy.c      Tue Oct 23 21:44:43 2007
++++ binutils-2.18/binutils/objcopy.c   Tue Oct 23 22:38:29 2007
+@@ -32,6 +32,7 @@
+ #include "elf-bfd.h"
+ #include <sys/stat.h>
+ #include "libbfd.h"
++#include "debug.h"
+ /* A list of symbols to explicitly strip out, or to keep.  A linked
+    list is good enough for a small number from the command line, but
+@@ -272,7 +273,9 @@
+     OPTION_PURE,
+     OPTION_IMPURE,
+     OPTION_EXTRACT_SYMBOL,
+-    OPTION_REVERSE_BYTES
++    OPTION_REVERSE_BYTES,
++    OPTION_CHANGE_PATHNAME,
++    OPTION_BASENAME
+   };
+ /* Options to handle if running as "strip".  */
+@@ -316,10 +319,12 @@
+   {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
+   {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
+   {"alt-machine-code", required_argument, 0, OPTION_ALT_MACH_CODE},
++  {"basename", no_argument, 0, OPTION_BASENAME},
+   {"binary-architecture", required_argument, 0, 'B'},
+   {"byte", required_argument, 0, 'b'},
+   {"change-addresses", required_argument, 0, OPTION_CHANGE_ADDRESSES},
+   {"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR},
++  {"change-pathname", required_argument, 0, OPTION_CHANGE_PATHNAME},
+   {"change-section-address", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
+   {"change-section-lma", required_argument, 0, OPTION_CHANGE_SECTION_LMA},
+   {"change-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_VMA},
+@@ -504,6 +509,8 @@
+      --prefix-alloc-sections <prefix>\n\
+                                    Add <prefix> to start of every allocatable\n\
+                                      section name\n\
++     --change-pathname <old>=<new> Change debug pathnames from <old> to <new>\n\
++     --basename                    Strip directory part from debug pathnames\n\
+   -v --verbose                     List all object files modified\n\
+   @<file>                          Read options from <file>\n\
+   -V --version                     Display this program's version number\n\
+@@ -911,6 +918,8 @@
+   asymbol **from = isyms, **to = osyms;
+   long src_count = 0, dst_count = 0;
+   int relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
++  bfd_boolean need_for_debugging = convert_debugging
++    && bfd_get_arch (abfd) == bfd_arch_avr;
+   for (; src_count < symcount; src_count++)
+     {
+@@ -1010,9 +1019,10 @@
+              || bfd_is_com_section (bfd_get_section (sym)))
+       keep = strip_symbols != STRIP_UNNEEDED;
+       else if ((flags & BSF_DEBUGGING) != 0)  /* Debugging symbol.  */
+-      keep = (strip_symbols != STRIP_DEBUG
+-              && strip_symbols != STRIP_UNNEEDED
+-              && ! convert_debugging);
++      keep = need_for_debugging
++              || (strip_symbols != STRIP_DEBUG
++                  && strip_symbols != STRIP_UNNEEDED
++                  && ! convert_debugging);
+       else if (bfd_coff_get_comdat_section (abfd, bfd_get_section (sym)))
+       /* COMDAT sections store special information in local
+          symbols, so we cannot risk stripping any of them.  */
+@@ -2588,6 +2598,10 @@
+     return write_ieee_debugging_info (obfd, dhandle);
+   if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
++      && bfd_get_arch (obfd) == bfd_arch_avr)
++    return write_coff_debugging_info (obfd, dhandle, symcountp, symppp);
 +
-+        case 1:
-+          {
-+            short x = bfd_get_16 (abfd, addr);
-+            DOIT (x);
-+            bfd_put_16 (abfd, (bfd_vma) x, addr);
-+          }
-+          break;
++  if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
+       || bfd_get_flavour (obfd) == bfd_target_elf_flavour)
+     {
+       bfd_byte *syms, *strings;
+@@ -3287,6 +3301,30 @@
+       case OPTION_PREFIX_ALLOC_SECTIONS:
+         prefix_alloc_sections_string = optarg;
++        break;
 +
-+        case 2:
-+          {
-+            long x = bfd_get_32 (abfd, addr);
-+            DOIT (x);
-+            bfd_put_32 (abfd, (bfd_vma) x, addr);
-+          }
-+          break;
++      case OPTION_CHANGE_PATHNAME:
++        {
++          const char *s;
++          int len;
++          char *name;
 +
-+        default:
-+          abort ();
-+        }
-+      }
++          s = strchr (optarg, '=');
++          if (s == NULL)
++            fatal (_("bad format for %s"), "--change-pathname");
 +
-+  /* Now let bfd_perform_relocation finish everything up.  */
-+  return bfd_reloc_continue;
-+}
++          len = s - optarg;
++          name = (char *) xmalloc (len + 1);
++          strncpy (name, optarg, len);
++          name[len] = '\0';
 +
-+#ifndef PCRELOFFSET
-+#define PCRELOFFSET FALSE
-+#endif
++          debug_register_pathname_xlat (name, s + 1);
++        }
++        break;
 +
-+static reloc_howto_type howto_table[] =
-+{
-+  EMPTY_HOWTO (0),
-+  EMPTY_HOWTO (1),
-+  EMPTY_HOWTO (2),
-+  EMPTY_HOWTO (3),
-+  EMPTY_HOWTO (4),
-+  EMPTY_HOWTO (5),
-+  HOWTO (R_DIR32,               /* type */
-+       0,                     /* rightshift */
-+       2,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       32,                    /* bitsize */
-+       FALSE,                 /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_bitfield, /* complain_on_overflow */
-+       coff_avr_reloc,       /* special_function */
-+       "dir32",               /* name */
-+       TRUE,                  /* partial_inplace */
-+       0xffffffff,            /* src_mask */
-+       0xffffffff,            /* dst_mask */
-+       TRUE),                /* pcrel_offset */
-+  /* {7}, */
-+  HOWTO (R_IMAGEBASE,            /* type */
-+       0,                     /* rightshift */
-+       2,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       32,                    /* bitsize */
-+       FALSE,                 /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_bitfield, /* complain_on_overflow */
-+       coff_avr_reloc,       /* special_function */
-+       "rva32",                  /* name */
-+       TRUE,                  /* partial_inplace */
-+       0xffffffff,            /* src_mask */
-+       0xffffffff,            /* dst_mask */
-+       FALSE),                /* pcrel_offset */
-+  EMPTY_HOWTO (010),
-+  EMPTY_HOWTO (011),
-+  EMPTY_HOWTO (012),
-+  EMPTY_HOWTO (013),
-+  EMPTY_HOWTO (014),
-+  EMPTY_HOWTO (015),
-+  EMPTY_HOWTO (016),
-+  HOWTO (R_RELBYTE,           /* type */
-+       0,                     /* rightshift */
-+       0,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       8,                     /* bitsize */
-+       FALSE,                 /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_bitfield, /* complain_on_overflow */
-+       coff_avr_reloc,        /* special_function */
-+       "8",                   /* name */
-+       TRUE,                  /* partial_inplace */
-+       0x000000ff,            /* src_mask */
-+       0x000000ff,            /* dst_mask */
-+       PCRELOFFSET),          /* pcrel_offset */
-+  HOWTO (R_RELWORD,           /* type */
-+       0,                     /* rightshift */
-+       1,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       16,                    /* bitsize */
-+       FALSE,                 /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_bitfield, /* complain_on_overflow */
-+       coff_avr_reloc,        /* special_function */
-+       "16",                  /* name */
-+       TRUE,                  /* partial_inplace */
-+       0x0000ffff,            /* src_mask */
-+       0x0000ffff,            /* dst_mask */
-+       PCRELOFFSET),          /* pcrel_offset */
-+  HOWTO (R_RELLONG,           /* type */
-+       0,                     /* rightshift */
-+       2,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       32,                    /* bitsize */
-+       FALSE,                 /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_bitfield, /* complain_on_overflow */
-+       coff_avr_reloc,        /* special_function */
-+       "32",                  /* name */
-+       TRUE,                  /* partial_inplace */
-+       0xffffffff,            /* src_mask */
-+       0xffffffff,            /* dst_mask */
-+       PCRELOFFSET),          /* pcrel_offset */
-+  HOWTO (R_PCRBYTE,           /* type */
-+       0,                     /* rightshift */
-+       0,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       8,                     /* bitsize */
-+       TRUE,                  /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_signed, /* complain_on_overflow */
-+       coff_avr_reloc,        /* special_function */
-+       "DISP8",               /* name */
-+       TRUE,                  /* partial_inplace */
-+       0x000000ff,            /* src_mask */
-+       0x000000ff,            /* dst_mask */
-+       PCRELOFFSET),          /* pcrel_offset */
-+  HOWTO (R_PCRWORD,           /* type */
-+       0,                     /* rightshift */
-+       1,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       16,                    /* bitsize */
-+       TRUE,                  /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_signed, /* complain_on_overflow */
-+       coff_avr_reloc,        /* special_function */
-+       "DISP16",              /* name */
-+       TRUE,                  /* partial_inplace */
-+       0x0000ffff,            /* src_mask */
-+       0x0000ffff,            /* dst_mask */
-+       PCRELOFFSET),          /* pcrel_offset */
-+  HOWTO (R_PCRLONG,           /* type */
-+       0,                     /* rightshift */
-+       2,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       32,                    /* bitsize */
-+       TRUE,                  /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_signed, /* complain_on_overflow */
-+       coff_avr_reloc,        /* special_function */
-+       "DISP32",              /* name */
-+       TRUE,                  /* partial_inplace */
-+       0xffffffff,            /* src_mask */
-+       0xffffffff,            /* dst_mask */
-+       PCRELOFFSET)           /* pcrel_offset */
-+};
-+
-+/* Turn a howto into a reloc  nunmber */
-+
-+#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
-+#define BADMAG(x) AVRBADMAG(x)
-+#define AVR 1                 /* Customize coffcode.h */
-+
-+#define RTYPE2HOWTO(cache_ptr, dst) \
-+          (cache_ptr)->howto = howto_table + (dst)->r_type;
-+
-+/* For AVR COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
-+   library.  On some other COFF targets STYP_BSS is normally
-+   STYP_NOLOAD.  */
-+#define BSS_NOLOAD_IS_SHARED_LIBRARY
-+
-+/* Compute the addend of a reloc.  If the reloc is to a common symbol,
-+   the object file contains the value of the common symbol.  By the
-+   time this is called, the linker may be using a different symbol
-+   from a different object file with a different value.  Therefore, we
-+   hack wildly to locate the original symbol from this file so that we
-+   can make the correct adjustment.  This macro sets coffsym to the
-+   symbol from the original file, and uses it to set the addend value
-+   correctly.  If this is not a common symbol, the usual addend
-+   calculation is done, except that an additional tweak is needed for
-+   PC relative relocs.
-+   FIXME: This macro refers to symbols and asect; these are from the
-+   calling function, not the macro arguments.  */
-+
-+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)              \
-+  {                                                           \
-+    coff_symbol_type *coffsym = (coff_symbol_type *) NULL;    \
-+    if (ptr && bfd_asymbol_bfd (ptr) != abfd)                 \
-+      coffsym = (obj_symbols (abfd)                           \
-+               + (cache_ptr->sym_ptr_ptr - symbols));         \
-+    else if (ptr)                                             \
-+      coffsym = coff_symbol_from (abfd, ptr);                 \
-+    if (coffsym != (coff_symbol_type *) NULL                  \
-+      && coffsym->native->u.syment.n_scnum == 0)              \
-+      cache_ptr->addend = - coffsym->native->u.syment.n_value;        \
-+    else if (ptr && bfd_asymbol_bfd (ptr) == abfd             \
-+           && ptr->section != (asection *) NULL)              \
-+      cache_ptr->addend = - (ptr->section->vma + ptr->value); \
-+    else                                                      \
-+      cache_ptr->addend = 0;                                  \
-+    if (ptr && howto_table[reloc.r_type].pc_relative)         \
-+      cache_ptr->addend += asect->vma;                                \
-+  }
-+
-+/* We use the special COFF backend linker.  */
-+#define coff_relocate_section _bfd_coff_generic_relocate_section
-+
-+static reloc_howto_type *
-+coff_avr_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
-+     bfd *abfd ATTRIBUTE_UNUSED;
-+     asection *sec;
-+     struct internal_reloc *rel;
-+     struct coff_link_hash_entry *h;
-+     struct internal_syment *sym;
-+     bfd_vma *addendp;
-+{
-+
-+  reloc_howto_type *howto;
-+
-+  howto = howto_table + rel->r_type;
-+
-+  if (howto->pc_relative)
-+    *addendp += sec->vma;
-+
-+  if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
-+    {
-+      /* This is a common symbol.  The section contents include the
-+       size (sym->n_value) as an addend.  The relocate_section
-+       function will be adding in the final value of the symbol.  We
-+       need to subtract out the current size in order to get the
-+       correct result.  */
-+
-+      BFD_ASSERT (h != NULL);
-+
-+      /* I think we *do* want to bypass this.  If we don't, I have seen some data
-+       parameters get the wrong relcation address.  If I link two versions
-+       with and without this section bypassed and then do a binary comparison,
-+       the addresses which are different can be looked up in the map.  The
-+       case in which this section has been bypassed has addresses which correspond
-+       to values I can find in the map.  */
-+      *addendp -= sym->n_value;
-+    }
-+
-+  /* If the output symbol is common (in which case this must be a
-+     relocateable link), we need to add in the final size of the
-+     common symbol.  */
-+  if (h != NULL && h->root.type == bfd_link_hash_common)
-+    *addendp += h->root.u.c.size;
-+
-+  return howto;
-+}
-+
-+#define coff_rtype_to_howto coff_avr_rtype_to_howto
-+
-+#include "coffcode.h"
-+
-+static const bfd_target *
-+coff_avr_object_p(a)
-+     bfd *a;
-+{
-+  return coff_object_p (a);
-+}
-+
-+/* Handle all the abominations of AVR COFF:
-+
-+   Generic COFF always uses the D1 slot to indicate the "most
-+   important" derived type, and the D2...Dn slots for decreasing
-+   importance.  E. g., a function symbol will always have its DT_FCN
-+   element in D1, an array its DT_ARY (its first DT_ARY in a
-+   multi-dimensional array).  In contrast, AVR COFF expects this most
-+   important derived type specifier in the upmost Dn slot that is
-+   allocated at all (i. e. that is != 0).
-+
-+   Generic COFF says that "Any symbol that satisfies more than one
-+   condition [... for AUX entries] should have a union format in its
-+   auxiliary entry."  AVR COFF uses sepearate AUX entries for multiple
-+   derived types, and in some cases (like the ISFCN one), even puts
-+   the most important one into the last allocated AUX entry.  We
-+   join/split them here at the border as well.  Note that when
-+   generating AUX entries (where we need to split them), the n_numaux
-+   field must already have been set up properly (e. g. in
-+   binutils/wrcoff.c) since the entry renumbering and pointerization
-+   would not work otherwise.  Thus, we only split the information into
-+   multiple records if n_numaux > 1.  For similar reasons, we keep
-+   n_numaux > 1 on input to keep the appropriate AUX entries
-+   allocated, so a symbol can be reconstructed if it is being passed
-+   through one of the GNU tools.
-+
-+   Note that this adjustment is called after the symbol itself has
-+   been swapped in, but before the AUX entries are swapped in.  This
-+   is the only hook available that could swap (or merge) AUX entries
-+   at all, so we have to operate on the external AUX entries still. */
-+
-+void
-+avr_coff_adjust_sym_in_post (abfd, ext, in)
-+     bfd *abfd;
-+     PTR ext;
-+     PTR in;
-+{
-+  struct internal_syment *dst = (struct internal_syment *)in;
-+  unsigned short dt, bt, ndt;
-+  dt = dst->n_type & ~N_BTMASK;
-+  bt = BTYPE (dst->n_type);
-+
-+  /* Some AVR COFF producers seem to violate the COFF specs, and
-+     produce symbols for tag names that have the C_FOO filled in
-+     properly, but T_NULL as the base type value.  Patch up here,
-+     since some of our generic COFF tools (in particular
-+     binutils/rdcoff.c) rely on the correct data. */
-+  if (bt == T_NULL)
-+    switch (dst->n_sclass)
-+      {
-+      case C_STRTAG:
-+      bt = T_STRUCT;
-+      break;
-+
-+      case C_UNTAG:
-+      bt = T_UNION;
-+      break;
-+
-+      case C_ENTAG:
-+      bt = T_ENUM;
-+      break;
-+      }
-+
-+  /* Swap the derived type slots. */
-+  if (dt != 0)
-+    {
-+      ndt = 0;
-+      while (dt != 0)
-+      {
-+        ndt = (ndt << N_TSHIFT) | (dt & (N_TMASK >> N_BTSHFT));
-+        dt >>= N_TSHIFT;
-+      }
-+      dst->n_type = (ndt << N_BTSHFT) | bt;
-+    }
-+  else
-+    dst->n_type = bt;
-+
-+  /* If the derived type is function, and there is more than one AUX
-+     entry, swap the first and the last AUX entry, so the most
-+     interesting one will become the first.
-+
-+     If the fundamental type is a tagged type (struct/union/enum), try
-+     to find the AUX entry describing the tagged type (the one that
-+     has x_sym.x_tagndx filled in), and merge the tag index into the
-+     first AUX entry.  Depending on the actual input file, there might
-+     be further DT_PTR entries which we just ignore, since we could
-+     not handle that information anyway. */
-+  if (dst->n_numaux > 1 && dst->n_sclass != C_FILE)
-+    {
-+      AUXENT caux, *auxp1, *auxp2;
-+      size_t symesz;
-+      unsigned int i;
-+
-+      symesz = bfd_coff_symesz (abfd);
-+      i = dst->n_numaux;
-+
-+      auxp1 = (AUXENT *)((char *)ext + symesz);
-+      auxp2 = (AUXENT *)((char *)ext + i * symesz);
-+
-+      if (ISFCN (dst->n_type)
-+        || (ISPTR(dst->n_type)
-+            && (bt == T_STRUCT || bt == T_UNION || bt == T_ENUM)))
-+      {
-+        caux = *auxp2;
-+        *auxp2 = *auxp1;
-+        *auxp1 = caux;
-+      }
-+      else
-+      caux = *auxp1;
-+
-+      if ((ISFCN (dst->n_type) || ISARY (dst->n_type))
-+        && (bt == T_STRUCT || bt == T_UNION || bt == T_ENUM))
-+      {
-+        while (i > 1)
-+          {
-+            auxp2 = (AUXENT *)((char *)ext + i * symesz);
-+
-+            if (auxp2->x_sym.x_tagndx[0] != 0 || auxp2->x_sym.x_tagndx[1] != 0
-+                || auxp2->x_sym.x_tagndx[2] != 0 || auxp2->x_sym.x_tagndx[3] != 0)
-+              {
-+                memcpy (caux.x_sym.x_tagndx, auxp2->x_sym.x_tagndx,
-+                        4 * sizeof (char));
-+                break;
-+              }
-+            i--;
-+          }
-+        if (i > 1)
-+          *auxp1 = caux;
-+      }
-+    }
-+}
-+
-+/* When exporting an AVR COFF file, just undo all that has been done
-+   above.  Again, we are called after the symbol itself has been
-+   swapped out, but before the AUX entries are being written.
-+   Unfortunately, we are only given a pointer to the symbol itself, so
-+   we have to derive the pointer to the respective aux entries from
-+   that address, which is a bit clumsy. */
-+void
-+avr_coff_adjust_sym_out_post (abfd, in, ext)
-+     bfd *abfd;
-+     PTR in;
-+     PTR ext;
-+{
-+  struct internal_syment *src = (struct internal_syment *)(in);
-+  struct external_syment *dst = (struct external_syment *)(ext);
-+  unsigned short dt, bt, ndt;
-+
-+  dt = src->n_type & ~N_BTMASK;
-+  bt = BTYPE (src->n_type);
-+
-+  if (dt != 0)
-+    {
-+      ndt = 0;
-+      while (dt != 0)
-+      {
-+        ndt = (ndt << N_TSHIFT) | (dt & (N_TMASK >> N_BTSHFT));
-+        dt >>= N_TSHIFT;
-+      }
-+      H_PUT_16 (abfd, (ndt << N_BTSHFT) | bt, dst->e_type);
-+    }
-+
-+  if (src->n_numaux > 1 && src->n_sclass != C_FILE)
-+    {
-+      combined_entry_type *srce, *dste;
-+      char *hackp;
-+      unsigned int i;
-+
-+      /* Recover the original combinend_entry_type *. */
-+      hackp = (char *)in;
-+      hackp -= offsetof(combined_entry_type, u.syment);
-+      srce = (combined_entry_type *)hackp;
-+      srce++;
-+
-+      /* We simply duplicate the first AUX entry as many times as
-+       needed.  Since COFF itself normally uses just a single AUX
-+       entry for all the information, this will work -- each COFF
-+       consumer will then just pick the fields it is particularly
-+       interested in.  This would not work for the AVR COFF specific
-+       DT_PTR AUX entries, but we don't support them anyway. */
-+      for (i = 1; i < src->n_numaux; i++)
-+      {
-+        dste = srce + i;
-+        *dste = *srce;
-+      }
-+    }
-+}
-+
-+const bfd_target
-+#ifdef TARGET_SYM
-+  TARGET_SYM =
-+#else
-+  avrcoff_vec =
-+#endif
-+{
-+#ifdef TARGET_NAME
-+  TARGET_NAME,
-+#else
-+  "coff-avr",                 /* name */
-+#endif
-+  bfd_target_coff_flavour,
-+  BFD_ENDIAN_LITTLE,          /* data byte order is little */
-+  BFD_ENDIAN_LITTLE,          /* header byte order is little */
-+
-+  (HAS_RELOC | EXEC_P |               /* object flags */
-+   HAS_LINENO | HAS_DEBUG |
-+   HAS_SYMS | HAS_LOCALS | WP_TEXT),
-+
-+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
-+  0,                          /* leading char */
-+  '/',                                /* ar_pad_char */
-+  15,                         /* ar_max_namelen */
-+
-+  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
-+     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
-+     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
-+  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
-+     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
-+     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
-+
-+/* Note that we allow an object file to be treated as a core file as well.  */
-+    {_bfd_dummy_target, coff_avr_object_p, /* bfd_check_format */
-+       bfd_generic_archive_p, coff_avr_object_p},
-+    {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
-+       bfd_false},
-+    {bfd_false, coff_write_object_contents, /* bfd_write_contents */
-+       _bfd_write_archive_contents, bfd_false},
-+
-+     BFD_JUMP_TABLE_GENERIC (coff),
-+     BFD_JUMP_TABLE_COPY (coff),
-+     BFD_JUMP_TABLE_CORE (_bfd_nocore),
-+     BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
-+     BFD_JUMP_TABLE_SYMBOLS (coff),
-+     BFD_JUMP_TABLE_RELOCS (coff),
-+     BFD_JUMP_TABLE_WRITE (coff),
-+     BFD_JUMP_TABLE_LINK (coff),
-+     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
-+
-+  NULL,
-+
-+  COFF_SWAP_TABLE
-+};
-diff -uNdr binutils-2.17.50.0.18-old/bfd/coff-ext-avr.c binutils-2.17.50.0.18/bfd/coff-ext-avr.c
---- binutils-2.17.50.0.18-old/bfd/coff-ext-avr.c       1970-01-01 01:00:00.000000000 +0100
-+++ binutils-2.17.50.0.18/bfd/coff-ext-avr.c   2007-10-20 16:45:33.000000000 +0200
-@@ -0,0 +1,424 @@
-+/* BFD back-end for Atmel AVR "extended" COFF files.
-+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2003
-+   Free Software Foundation, Inc.
-+   This is mostly the same as avr-coff, except of the presence of the
-+   COFF optional header.
-+
-+This file is part of BFD, the Binary File Descriptor library.
-+
-+This program is free software; you can redistribute it and/or modify
-+it under the terms of the GNU General Public License as published by
-+the Free Software Foundation; either version 2 of the License, or
-+(at your option) any later version.
-+
-+This program is distributed in the hope that it will be useful,
-+but WITHOUT ANY WARRANTY; without even the implied warranty of
-+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+GNU General Public License for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with this program; if not, write to the Free Software
-+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-+
-+#include "bfd.h"
-+#include "sysdep.h"
-+#include "libbfd.h"
-+
-+#define AVR_EXT_COFF 1
-+#include "coff/avr.h"
-+
-+#include "coff/internal.h"
-+
-+#include "libcoff.h"
-+
-+static bfd_reloc_status_type coff_ext_avr_reloc
-+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-+static reloc_howto_type *coff_ext_avr_rtype_to_howto
-+  PARAMS ((bfd *, asection *, struct internal_reloc *,
-+         struct coff_link_hash_entry *, struct internal_syment *,
-+         bfd_vma *));
-+static const bfd_target * coff_ext_avr_object_p PARAMS ((bfd *));
-+
-+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
-+/* The page size is a guess based on ELF.  */
-+
-+#define COFF_PAGE_SIZE 0x1000
-+
-+/* For some reason when using avr COFF the value stored in the .text
-+   section for a reference to a common symbol is the value itself plus
-+   any desired offset.  Ian Taylor, Cygnus Support.  */
-+
-+/* If we are producing relocateable output, we need to do some
-+   adjustments to the object file that are not done by the
-+   bfd_perform_relocation function.  This function is called by every
-+   reloc type to make any required adjustments.  */
-+
-+static bfd_reloc_status_type
-+coff_ext_avr_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
-+               error_message)
++      case OPTION_BASENAME:
++        /* very special case of pathname translation */
++        debug_register_pathname_xlat (NULL, NULL);
+         break;
+       case OPTION_READONLY_TEXT:
+--- binutils-2.18.orig/binutils/rdcoff.c       Tue Oct 23 21:44:43 2007
++++ binutils-2.18/binutils/rdcoff.c    Tue Oct 23 22:18:44 2007
+@@ -82,6 +82,9 @@
+   struct coff_slots *slots;
+   /* Basic types.  */
+   debug_type basic[T_MAX + 1];
++  /* Some general information, kept here for convenience. */
++  size_t intsize;             /* sizeof (int) */
++  size_t doublesize;          /* sizeof (double) */
+ };
+ static debug_type *coff_get_slot (struct coff_types *, int);
+@@ -101,6 +104,7 @@
+   (bfd *, struct coff_types *, asymbol *, long, struct internal_syment *,
+    void *, debug_type, bfd_boolean);
+ static bfd_boolean external_coff_symbol_p (int sym_class);
++static bfd_vma coff_convert_register (bfd *, bfd_vma);
\f
+ /* Return the slot for a type.  */
+@@ -271,8 +275,7 @@
+       break;
+     case T_INT:
+-      /* FIXME: Perhaps the size should depend upon the architecture.  */
+-      ret = debug_make_int_type (dhandle, 4, FALSE);
++      ret = debug_make_int_type (dhandle, types->intsize, FALSE);
+       name = "int";
+       break;
+@@ -287,7 +290,7 @@
+       break;
+     case T_DOUBLE:
+-      ret = debug_make_float_type (dhandle, 8);
++      ret = debug_make_float_type (dhandle, types->doublesize);
+       name = "double";
+       break;
+@@ -307,7 +310,7 @@
+       break;
+     case T_UINT:
+-      ret = debug_make_int_type (dhandle, 4, TRUE);
++      ret = debug_make_int_type (dhandle, types->intsize, TRUE);
+       name = "unsigned int";
+       break;
+@@ -565,6 +568,8 @@
+     case C_WEAKEXT:
+     case C_EXT:
++      /* AVR COFF abuses C_EXTDEF */
++    case C_EXTDEF:
+       if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
+                                  DEBUG_GLOBAL, bfd_asymbol_value (sym)))
+       return FALSE;
+@@ -580,9 +585,9 @@
+       break;
+     case C_REG:
+-      /* FIXME: We may need to convert the register number.  */
+       if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
+-                                 DEBUG_REGISTER, bfd_asymbol_value (sym)))
++                                 DEBUG_REGISTER,
++                                 coff_convert_register (abfd, bfd_asymbol_value (sym))))
+       return FALSE;
+       break;
+@@ -596,9 +601,9 @@
+       break;
+     case C_REGPARM:
+-      /* FIXME: We may need to convert the register number.  */
+       if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
+-                                  DEBUG_PARM_REG, bfd_asymbol_value (sym)))
++                                  DEBUG_PARM_REG,
++                                  coff_convert_register (abfd, bfd_asymbol_value (sym))))
+       return FALSE;
+       break;
+@@ -648,6 +653,28 @@
+   return FALSE;
+ }
++static bfd_vma
++coff_convert_register (abfd, val)
 +     bfd *abfd;
-+     arelent *reloc_entry;
-+     asymbol *symbol;
-+     PTR data;
-+     asection *input_section ATTRIBUTE_UNUSED;
-+     bfd *output_bfd;
-+     char **error_message ATTRIBUTE_UNUSED;
++     bfd_vma val;
 +{
-+  symvalue diff;
-+
-+  if (output_bfd == (bfd *) NULL)
-+    return bfd_reloc_continue;
 +
-+  if (bfd_is_com_section (symbol->section))
-+    {
-+      /* We are relocating a common symbol.  The current value in the
-+       object file is ORIG + OFFSET, where ORIG is the value of the
-+       common symbol as seen by the object file when it was compiled
-+       (this may be zero if the symbol was undefined) and OFFSET is
-+       the offset into the common symbol (normally zero, but may be
-+       non-zero when referring to a field in a common structure).
-+       ORIG is the negative of reloc_entry->addend, which is set by
-+       the CALC_ADDEND macro below.  We want to replace the value in
-+       the object file with NEW + OFFSET, where NEW is the value of
-+       the common symbol which we are going to put in the final
-+       object file.  NEW is symbol->value.  */
-+      diff = symbol->value + reloc_entry->addend;
-+    }
-+  else
++  switch (bfd_get_arch (abfd))
 +    {
-+      /* For some reason bfd_perform_relocation always effectively
-+       ignores the addend for a COFF target when producing
-+       relocateable output.  This seems to be always wrong for 860
-+       COFF, so we handle the addend here instead.  */
-+      diff = reloc_entry->addend;
-+    }
-+
-+#define DOIT(x) \
-+  x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
-+
-+    if (diff != 0)
-+      {
-+      reloc_howto_type *howto = reloc_entry->howto;
-+      unsigned char *addr = (unsigned char *) data + reloc_entry->address;
-+
-+      switch (howto->size)
-+        {
-+        case 0:
-+          {
-+            char x = bfd_get_8 (abfd, addr);
-+            DOIT (x);
-+            bfd_put_8 (abfd, x, addr);
-+          }
-+          break;
++    case bfd_arch_avr:
++      /* AVR COFF wants to describe up to four registers by the four
++       bytes of the 32-bit value.  Unused bytes are filled with
++       0xff.  In theory, this would allow for non-contiguous
++       register usage to hold a single value, but hopefully, no
++       compiler is going to use that feature.  We could not handle
++       it anyway. */
++      return val & 0xff;
 +
-+        case 1:
-+          {
-+            short x = bfd_get_16 (abfd, addr);
-+            DOIT (x);
-+            bfd_put_16 (abfd, (bfd_vma) x, addr);
-+          }
-+          break;
++    default:
++      return val;
++    }
++}
 +
-+        case 2:
-+          {
-+            long x = bfd_get_32 (abfd, addr);
-+            DOIT (x);
-+            bfd_put_32 (abfd, (bfd_vma) x, addr);
-+          }
-+          break;
+ /* This is the main routine.  It looks through all the symbols and
+    handles them.  */
+@@ -674,6 +701,17 @@
+   types.slots = NULL;
+   for (i = 0; i <= T_MAX; i++)
+     types.basic[i] = DEBUG_TYPE_NULL;
++  switch (bfd_get_arch (abfd))
++    {
++    case bfd_arch_avr:
++      types.intsize = 2;
++      types.doublesize = 4;
++      break;
 +
-+        default:
-+          abort ();
-+        }
-+      }
++    default:
++      types.intsize = 4;
++      types.doublesize = 8;
++    }
+   next_c_file = -1;
+   fnname = NULL;
+@@ -734,7 +772,6 @@
+       switch (syment.n_sclass)
+       {
+       case C_EFCN:
+-      case C_EXTDEF:
+       case C_ULABEL:
+       case C_USTATIC:
+       case C_LINE:
+@@ -757,6 +794,8 @@
+         /* Fall through.  */
+       case C_WEAKEXT:
+       case C_EXT:
++        /* AVR COFF abuses C_EXTDEF for C_EXT */
++      case C_EXTDEF:
+         if (ISFCN (syment.n_type))
+           {
+             fnname = name;
+--- binutils-2.18.orig/binutils/wrcoff.c       Thu Jan  1 01:00:00 1970
++++ binutils-2.18/binutils/wrcoff.c    Tue Oct 23 22:18:44 2007
+@@ -0,0 +1,3410 @@
++/* wrcoff.c -- Generate (AVR) COFF debugging information
++   Copyright 2003 Free Software Foundation, Inc.
 +
-+  /* Now let bfd_perform_relocation finish everything up.  */
-+  return bfd_reloc_continue;
-+}
++   Written by Joerg Wunsch.
 +
-+#ifndef PCRELOFFSET
-+#define PCRELOFFSET FALSE
-+#endif
++   This file is part of GNU Binutils.
 +
-+static reloc_howto_type howto_table[] =
-+{
-+  EMPTY_HOWTO (0),
-+  EMPTY_HOWTO (1),
-+  EMPTY_HOWTO (2),
-+  EMPTY_HOWTO (3),
-+  EMPTY_HOWTO (4),
-+  EMPTY_HOWTO (5),
-+  HOWTO (R_DIR32,               /* type */
-+       0,                     /* rightshift */
-+       2,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       32,                    /* bitsize */
-+       FALSE,                 /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_bitfield, /* complain_on_overflow */
-+       coff_ext_avr_reloc,       /* special_function */
-+       "dir32",               /* name */
-+       TRUE,                  /* partial_inplace */
-+       0xffffffff,            /* src_mask */
-+       0xffffffff,            /* dst_mask */
-+       TRUE),                /* pcrel_offset */
-+  /* {7}, */
-+  HOWTO (R_IMAGEBASE,            /* type */
-+       0,                     /* rightshift */
-+       2,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       32,                    /* bitsize */
-+       FALSE,                 /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_bitfield, /* complain_on_overflow */
-+       coff_ext_avr_reloc,       /* special_function */
-+       "rva32",                  /* name */
-+       TRUE,                  /* partial_inplace */
-+       0xffffffff,            /* src_mask */
-+       0xffffffff,            /* dst_mask */
-+       FALSE),                /* pcrel_offset */
-+  EMPTY_HOWTO (010),
-+  EMPTY_HOWTO (011),
-+  EMPTY_HOWTO (012),
-+  EMPTY_HOWTO (013),
-+  EMPTY_HOWTO (014),
-+  EMPTY_HOWTO (015),
-+  EMPTY_HOWTO (016),
-+  HOWTO (R_RELBYTE,           /* type */
-+       0,                     /* rightshift */
-+       0,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       8,                     /* bitsize */
-+       FALSE,                 /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_bitfield, /* complain_on_overflow */
-+       coff_ext_avr_reloc,    /* special_function */
-+       "8",                   /* name */
-+       TRUE,                  /* partial_inplace */
-+       0x000000ff,            /* src_mask */
-+       0x000000ff,            /* dst_mask */
-+       PCRELOFFSET),          /* pcrel_offset */
-+  HOWTO (R_RELWORD,           /* type */
-+       0,                     /* rightshift */
-+       1,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       16,                    /* bitsize */
-+       FALSE,                 /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_bitfield, /* complain_on_overflow */
-+       coff_ext_avr_reloc,    /* special_function */
-+       "16",                  /* name */
-+       TRUE,                  /* partial_inplace */
-+       0x0000ffff,            /* src_mask */
-+       0x0000ffff,            /* dst_mask */
-+       PCRELOFFSET),          /* pcrel_offset */
-+  HOWTO (R_RELLONG,           /* type */
-+       0,                     /* rightshift */
-+       2,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       32,                    /* bitsize */
-+       FALSE,                 /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_bitfield, /* complain_on_overflow */
-+       coff_ext_avr_reloc,    /* special_function */
-+       "32",                  /* name */
-+       TRUE,                  /* partial_inplace */
-+       0xffffffff,            /* src_mask */
-+       0xffffffff,            /* dst_mask */
-+       PCRELOFFSET),          /* pcrel_offset */
-+  HOWTO (R_PCRBYTE,           /* type */
-+       0,                     /* rightshift */
-+       0,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       8,                     /* bitsize */
-+       TRUE,                  /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_signed, /* complain_on_overflow */
-+       coff_ext_avr_reloc,    /* special_function */
-+       "DISP8",               /* name */
-+       TRUE,                  /* partial_inplace */
-+       0x000000ff,            /* src_mask */
-+       0x000000ff,            /* dst_mask */
-+       PCRELOFFSET),          /* pcrel_offset */
-+  HOWTO (R_PCRWORD,           /* type */
-+       0,                     /* rightshift */
-+       1,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       16,                    /* bitsize */
-+       TRUE,                  /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_signed, /* complain_on_overflow */
-+       coff_ext_avr_reloc,    /* special_function */
-+       "DISP16",              /* name */
-+       TRUE,                  /* partial_inplace */
-+       0x0000ffff,            /* src_mask */
-+       0x0000ffff,            /* dst_mask */
-+       PCRELOFFSET),          /* pcrel_offset */
-+  HOWTO (R_PCRLONG,           /* type */
-+       0,                     /* rightshift */
-+       2,                     /* size (0 = byte, 1 = short, 2 = long) */
-+       32,                    /* bitsize */
-+       TRUE,                  /* pc_relative */
-+       0,                     /* bitpos */
-+       complain_overflow_signed, /* complain_on_overflow */
-+       coff_ext_avr_reloc,    /* special_function */
-+       "DISP32",              /* name */
-+       TRUE,                  /* partial_inplace */
-+       0xffffffff,            /* src_mask */
-+       0xffffffff,            /* dst_mask */
-+       PCRELOFFSET)           /* pcrel_offset */
-+};
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2 of the License, or
++   (at your option) any later version.
 +
-+/* Turn a howto into a reloc  nunmber */
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
 +
-+#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
-+#define BADMAG(x) AVRBADMAG(x)
-+#define AVR 1                 /* Customize coffcode.h */
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++   02111-1307, USA.  */
 +
-+#define RTYPE2HOWTO(cache_ptr, dst) \
-+          (cache_ptr)->howto = howto_table + (dst)->r_type;
++/* This file contains code which writes out COFF debugging
++   information.  By now, this has only been tested on the AVR
++   platform, though any attempt has been made to keep the conversion
++   applicable to possible other COFF debugging consumers as well. */
 +
-+/* For AVR COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
-+   library.  On some other COFF targets STYP_BSS is normally
-+   STYP_NOLOAD.  */
-+#define BSS_NOLOAD_IS_SHARED_LIBRARY
++#include <stdio.h>
++#include <assert.h>
 +
-+/* Compute the addend of a reloc.  If the reloc is to a common symbol,
-+   the object file contains the value of the common symbol.  By the
-+   time this is called, the linker may be using a different symbol
-+   from a different object file with a different value.  Therefore, we
-+   hack wildly to locate the original symbol from this file so that we
-+   can make the correct adjustment.  This macro sets coffsym to the
-+   symbol from the original file, and uses it to set the addend value
-+   correctly.  If this is not a common symbol, the usual addend
-+   calculation is done, except that an additional tweak is needed for
-+   PC relative relocs.
-+   FIXME: This macro refers to symbols and asect; these are from the
-+   calling function, not the macro arguments.  */
++#include "sysdep.h"
++#include "bfd.h"
++#include "coff/internal.h"
++#include "bucomm.h"
++#include "libiberty.h"
++#include "safe-ctype.h"
++#include "debug.h"
++#include "budbg.h"
 +
-+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)              \
-+  {                                                           \
-+    coff_symbol_type *coffsym = (coff_symbol_type *) NULL;    \
-+    if (ptr && bfd_asymbol_bfd (ptr) != abfd)                 \
-+      coffsym = (obj_symbols (abfd)                           \
-+               + (cache_ptr->sym_ptr_ptr - symbols));         \
-+    else if (ptr)                                             \
-+      coffsym = coff_symbol_from (abfd, ptr);                 \
-+    if (coffsym != (coff_symbol_type *) NULL                  \
-+      && coffsym->native->u.syment.n_scnum == 0)              \
-+      cache_ptr->addend = - coffsym->native->u.syment.n_value;        \
-+    else if (ptr && bfd_asymbol_bfd (ptr) == abfd             \
-+           && ptr->section != (asection *) NULL)              \
-+      cache_ptr->addend = - (ptr->section->vma + ptr->value); \
-+    else                                                      \
-+      cache_ptr->addend = 0;                                  \
-+    if (ptr && howto_table[reloc.r_type].pc_relative)         \
-+      cache_ptr->addend += asect->vma;                                \
-+  }
++/* Enabling COFF_DEBUG will trace the internal callback functions and
++   their parameters as debug_write() calls them. */
++//#define COFF_DEBUG 1
 +
-+/* We use the special COFF backend linker.  */
-+#define coff_relocate_section _bfd_coff_generic_relocate_section
++#include "libcoff.h"
 +
-+static reloc_howto_type *
-+coff_ext_avr_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
-+     bfd *abfd ATTRIBUTE_UNUSED;
-+     asection *sec;
-+     struct internal_reloc *rel;
-+     struct coff_link_hash_entry *h;
-+     struct internal_syment *sym;
-+     bfd_vma *addendp;
++#define N_TMASK (coff_data (info->abfd)->local_n_tmask)
++#define N_BTSHFT (coff_data (info->abfd)->local_n_btshft)
++#define N_BTMASK (coff_data (info->abfd)->local_n_btmask)
++#define N_TSHIFT (coff_data (info->abfd)->local_n_tshift)
++
++/* Structure of local symbols per compilation unit. */
++struct coff_compilation_unit
 +{
++  const char *fname;
++  asymbol **syms;
++  long nsyms, totsyms;
++};
 +
-+  reloc_howto_type *howto;
++enum ts_kind
++{
++  TS_EMPTY,
++  TS_VOID,
++  TS_INT,
++  TS_FLOAT,
++  TS_COMPLEX,
++  TS_ENUM,
++  TS_POINTER,
++  TS_FUNC,
++  TS_ARRAY,
++  TS_STRUCT,
++  TS_NONE = -1
++};
 +
-+  howto = howto_table + rel->r_type;
++/* Structure defining the pre-defined types. */
++struct coff_predef_type
++{
++  enum ts_kind kind;
++  unsigned int size;          /* in bytes */
++  bfd_boolean isunsigned;
++  int slot;
++};
 +
-+  if (howto->pc_relative)
-+    *addendp += sec->vma;
++struct coff_type_stack;
++struct coff_hash_entry;
 +
-+  if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
++struct coff_struct_fields
++{
++  const char *name;
++  bfd_vma bitpos;
++  bfd_vma bitsize;
++  enum debug_visibility visibility;
++  struct coff_type_stack *types;
++};
++
++/* Our type stack. */
++struct coff_type_stack
++{
++  struct coff_type_stack *next;
++  enum ts_kind tsk;
++  union
++  {
++    /* TS_INT */
++    struct
 +    {
-+      /* This is a common symbol.  The section contents include the
-+       size (sym->n_value) as an addend.  The relocate_section
-+       function will be adding in the final value of the symbol.  We
-+       need to subtract out the current size in order to get the
-+       correct result.  */
++      unsigned int size;
++      bfd_boolean isunsigned;
++    }
++    ts_int;
 +
-+      BFD_ASSERT (h != NULL);
++    /* TS_FLOAT */
++    struct
++    {
++      unsigned int size;
++    }
++    ts_float;
 +
-+      /* I think we *do* want to bypass this.  If we don't, I have seen some data
-+       parameters get the wrong relcation address.  If I link two versions
-+       with and without this section bypassed and then do a binary comparison,
-+       the addresses which are different can be looked up in the map.  The
-+       case in which this section has been bypassed has addresses which correspond
-+       to values I can find in the map.  */
-+      *addendp -= sym->n_value;
++    /* TS_ENUM */
++    struct
++    {
++      union
++      {
++      const char *fixtag;
++      char *malloctag;
++      }
++      tag;
++      bfd_boolean tagismalloced;
++      const char **names;
++      bfd_signed_vma *vals;
++      struct coff_enum_hash_entry *ehash;
 +    }
++    ts_enum;
 +
-+  /* If the output symbol is common (in which case this must be a
-+     relocateable link), we need to add in the final size of the
-+     common symbol.  */
-+  if (h != NULL && h->root.type == bfd_link_hash_common)
-+    *addendp += h->root.u.c.size;
++    /* TS_FUNC */
++    struct
++    {
++      struct coff_type_stack *savedts;
++    }
++    ts_func;
 +
-+  return howto;
-+}
++    /* TS_ARRAY */
++    struct
++    {
++      bfd_signed_vma low;
++      bfd_signed_vma high;
++    }
++    ts_array;
 +
-+#define coff_rtype_to_howto coff_ext_avr_rtype_to_howto
++    /* TS_STRUCT */
++    struct
++    {
++      union
++      {
++      const char *fixtag;
++      char *malloctag;
++      }
++      tag;
++      bfd_boolean tagismalloced;
++      unsigned int id;
++      bfd_boolean isstruct;
++      unsigned int size;
++      long nfields;
++      struct coff_struct_fields *fields;
++      struct coff_type_stack *savedts;
++      struct coff_struct_hash_entry *shash;
++    }
++    ts_struct;
++  }
++  u;
++};
 +
-+#include "coffcode.h"
++struct coff_name_type_hash_table
++{
++  struct bfd_hash_table root;
++};
 +
-+static const bfd_target *
-+coff_ext_avr_object_p(a)
-+     bfd *a;
++struct coff_name_type_hash_entry
++{
++  struct bfd_hash_entry root;
++  /* Information for this name.  */
++  struct coff_type_stack *types;
++  bfd_boolean emitted;
++};
++
++struct coff_struct_hash_table
++{
++  struct bfd_hash_table root;
++};
++
++struct coff_struct_hash_entry
++{
++  struct bfd_hash_entry root;
++  /* Information for this name.  */
++  struct coff_type_stack *types;
++  bfd_boolean emitted;
++  combined_entry_type *native;
++  /* list of symbol indices that need fixing */
++  long *fixidxs;
++  unsigned nfixidxs;
++};
++
++struct coff_enum_hash_table
++{
++  struct bfd_hash_table root;
++};
++
++struct coff_enum_hash_entry
 +{
-+  return coff_object_p (a);
-+}
++  struct bfd_hash_entry root;
++  /* Information for this name.  */
++  struct coff_type_stack *types;
++  bfd_boolean emitted;
++  combined_entry_type *native;
++  /* list of symbol indices that need fixing */
++  long *fixidxs;
++  unsigned nfixidxs;
++};
 +
-+const bfd_target
-+#ifdef TARGET_SYM
-+  TARGET_SYM =
-+#else
-+  avrextcoff_vec =
-+#endif
++/* COFF private symbol data.  Used as a cookie to pass data around
++   between various processing stages.  The generic COFF handling code
++   doesn't use any private data. */
++struct coff_private_symdata
 +{
-+#ifdef TARGET_NAME
-+  TARGET_NAME,
-+#else
-+  "coff-ext-avr",                     /* name */
-+#endif
-+  bfd_target_coff_flavour,
-+  BFD_ENDIAN_LITTLE,          /* data byte order is little */
-+  BFD_ENDIAN_LITTLE,          /* header byte order is little */
++  unsigned int size;          /* size of symbol, used in AVR register
++                                 translation */
++  struct coff_struct_hash_entry *shash; /* TS_STRUCT hash for fixups */
++  struct coff_enum_hash_entry *ehash; /* TS_ENUM hash for fixups */
++};
 +
-+  (HAS_RELOC | EXEC_P |               /* object flags */
-+   HAS_LINENO | HAS_DEBUG |
-+   HAS_SYMS | HAS_LOCALS | WP_TEXT),
++/* Stack of tags that need endndx fixing. */
++struct coff_fix_stack
++{
++  struct coff_fix_stack *next;
++  combined_entry_type *native;
++};
 +
-+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
-+  0,                          /* leading char */
-+  '/',                                /* ar_pad_char */
-+  15,                         /* ar_max_namelen */
++/* This is the handle passed through debug_write.  */
 +
-+  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
-+     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
-+     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
-+  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
-+     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
-+     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
++struct coff_write_handle
++{
++  /* The BFD.  */
++  bfd *abfd;
++  /* Pointers to .text and .data sections, can be used as defaults if
++     no other information is available. */
++  asection *textsect;
++  asection *datasect;
++  /* Some special flags. */
++  unsigned long flags;
++  /* Flags describing architecture options. */
++#define COFF_FL_AVR   0x0001  /* COFF is for AVR platform. */
++#define COFF_FL_EXT_AVR       0x0002  /* AVR "extended" COFF */
++  /* Flags describing internal status information. */
++#define COFF_FL_FIX_ENDNDX    0x10000 /* apply endndx fix at next symbol */
++#define COFF_FL_START_FCN     0x20000 /* begin of function pending */
++#define COFF_FL_FIX_BB                0x40000 /* fix last ".bb" symbol */
++  /* List of our compilation units, from input symbol table. */
++  struct coff_compilation_unit *units;
++  long nunits;
++  struct coff_compilation_unit *currentfile;
++  /* Global symbols from input symbol table. */
++  asymbol **globals;
++  long nglobals;
++  /* Section syms for named sections. */
++  coff_symbol_type **secsyms;
++  long nsecsyms;
++  /* Our COFF symbols. */
++  asymbol **syms;
++  long nsyms;
++  /* Total line number count. */
++  unsigned long totlnos;
++  /* Size of standard objects on this arch. */
++  unsigned int pointersize;
++  unsigned int enumsize;
++  /* Pending information when starting a function.  We have to defer
++     almost everything, some actions can be taken when seeing the
++     starting block of that function, some will even have to wait
++     until we see the end of the function. */
++  const char *funname;                /* name of function */
++  bfd_boolean funglobal;              /* global/local function? */
++  unsigned int lastlno;               /* last line number seen so far */
++  long funcindex;             /* index of ".func" symbol in syms */
++  unsigned int nlnos;         /* line numbers recorded for this function*/
++  bfd_vma endaddr;            /* last .eb address we have seen so far */
++  unsigned int funlno;                /* first line number in function */
++  coff_symbol_type **fargs;   /* function arguments */
++  unsigned int nfargs;
++  asection *funcsection;      /* section the current function is using */
++  /* Type information */
++  struct coff_type_stack *tstack;
++  struct coff_name_type_hash_table types;
++  struct coff_struct_hash_table structs;
++  struct coff_enum_hash_table enums;
++  unsigned nenums;            /* counter for anonymous enum tags */
++  /* Stack of pending endndx fixes, see coff_record_symbol(). */
++  struct coff_fix_stack *fixes;
++};
 +
-+/* Note that we allow an object file to be treated as a core file as well.  */
-+    {_bfd_dummy_target, coff_ext_avr_object_p, /* bfd_check_format */
-+       bfd_generic_archive_p, coff_ext_avr_object_p},
-+    {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
-+       bfd_false},
-+    {bfd_false, coff_write_object_contents, /* bfd_write_contents */
-+       _bfd_write_archive_contents, bfd_false},
++/* Predefined types, default to usual 32-bit architectures.
++   Arch-dependant different byte sizes will be tuned upon entering
++   write_coff_debugging_info().  The table is looked up from front to
++   end, so we put `more popular' types that might have the same size
++   as other types first (e. g. "int" precedes "long" and "short"). */
++static struct coff_predef_type coff_predef_types[] =
++{
++  { TS_INT, 4, FALSE, 4 },    /* signed int */
++  { TS_INT, 1, FALSE, 2 },    /* signed char */
++  { TS_INT, 2, FALSE, 3 },    /* signed short */
++  { TS_INT, 4, FALSE, 5 },    /* long int */
++  { TS_FLOAT, 8, FALSE, 7 },  /* double */
++  { TS_FLOAT, 4, FALSE, 6 },  /* float */
++  { TS_INT, 4, TRUE, 14 },    /* unsigned int */
++  { TS_INT, 1, TRUE, 12 },    /* unsigned char */
++  { TS_INT, 2, TRUE, 13 },    /* unsigned short */
++  { TS_INT, 4, TRUE, 15 },    /* unsigned long */
++};
 +
-+     BFD_JUMP_TABLE_GENERIC (coff),
-+     BFD_JUMP_TABLE_COPY (coff),
-+     BFD_JUMP_TABLE_CORE (_bfd_nocore),
-+     BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
-+     BFD_JUMP_TABLE_SYMBOLS (coff),
-+     BFD_JUMP_TABLE_RELOCS (coff),
-+     BFD_JUMP_TABLE_WRITE (coff),
-+     BFD_JUMP_TABLE_LINK (coff),
-+     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
++static bfd_boolean coff_copy_symbols
++  PARAMS ((struct coff_write_handle *, long, asymbol **));
++static asymbol *coff_find_symbol
++  PARAMS ((struct coff_write_handle *, const char *, bfd_boolean, bfd_boolean));
++static void coff_record_symbol
++  PARAMS ((struct coff_write_handle *, coff_symbol_type *));
++static symvalue coff_fixup_avr_register PARAMS ((symvalue, int));
++static struct bfd_hash_entry *coff_name_type_newfunc
++  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
++static bfd_boolean coff_free_type_info
++  PARAMS ((struct coff_name_type_hash_entry *, PTR));
++static struct bfd_hash_entry *coff_struct_newfunc
++  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
++static bfd_boolean coff_free_struct_info
++  PARAMS ((struct coff_struct_hash_entry *, PTR));
++static struct bfd_hash_entry *coff_enum_newfunc
++  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
++static bfd_boolean coff_free_enum_info
++  PARAMS ((struct coff_enum_hash_entry *, PTR));
++static unsigned int coff_get_fundamental_type
++  PARAMS ((struct coff_write_handle *, struct coff_type_stack *));
++static bfd_boolean coff_make_typed_symbol
++  PARAMS ((struct coff_write_handle *, coff_symbol_type **, enum ts_kind));
++static bfd_boolean coff_emit_struct
++  PARAMS ((struct coff_write_handle *, struct coff_type_stack *,
++         struct coff_struct_hash_entry *));
++static bfd_boolean coff_emit_enum
++  PARAMS ((struct coff_write_handle *, struct coff_type_stack *,
++         struct coff_enum_hash_entry *));
++static bfd_boolean coff_emit_ndebug_sym
++  PARAMS ((struct coff_write_handle *, asymbol *, bfd_boolean));
 +
-+  NULL,
++static bfd_boolean coff_start_compilation_unit PARAMS ((PTR, const char *));
++static bfd_boolean coff_start_source PARAMS ((PTR, const char *));
++static bfd_boolean coff_empty_type PARAMS ((PTR));
++static bfd_boolean coff_void_type PARAMS ((PTR));
++static bfd_boolean coff_int_type PARAMS ((PTR, unsigned int, bfd_boolean));
++static bfd_boolean coff_float_type PARAMS ((PTR, unsigned int));
++static bfd_boolean coff_complex_type PARAMS ((PTR, unsigned int));
++static bfd_boolean coff_bool_type PARAMS ((PTR, unsigned int));
++static bfd_boolean coff_enum_type
++  PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
++static bfd_boolean coff_pointer_type PARAMS ((PTR));
++static bfd_boolean coff_function_type PARAMS ((PTR, int, bfd_boolean));
++static bfd_boolean coff_reference_type PARAMS ((PTR));
++static bfd_boolean coff_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
++static bfd_boolean coff_array_type
++  PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, bfd_boolean));
++static bfd_boolean coff_set_type PARAMS ((PTR, bfd_boolean));
++static bfd_boolean coff_offset_type PARAMS ((PTR));
++static bfd_boolean coff_method_type PARAMS ((PTR, bfd_boolean, int, bfd_boolean));
++static bfd_boolean coff_const_type PARAMS ((PTR));
++static bfd_boolean coff_volatile_type PARAMS ((PTR));
++static bfd_boolean coff_start_struct_type
++  PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int));
++static bfd_boolean coff_struct_field
++  PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
++static bfd_boolean coff_end_struct_type PARAMS ((PTR));
++static bfd_boolean coff_start_class_type
++  PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean,
++         bfd_boolean));
++static bfd_boolean coff_class_static_member
++  PARAMS ((PTR, const char *, const char *, enum debug_visibility));
++static bfd_boolean coff_class_baseclass
++  PARAMS ((PTR, bfd_vma, bfd_boolean, enum debug_visibility));
++static bfd_boolean coff_class_start_method PARAMS ((PTR, const char *));
++static bfd_boolean coff_class_method_variant
++  PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean, bfd_boolean,
++         bfd_vma, bfd_boolean));
++static bfd_boolean coff_class_static_method_variant
++  PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean, bfd_boolean));
++static bfd_boolean coff_class_end_method PARAMS ((PTR));
++static bfd_boolean coff_end_class_type PARAMS ((PTR));
++static bfd_boolean coff_typedef_type PARAMS ((PTR, const char *));
++static bfd_boolean coff_tag_type
++  PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
++static bfd_boolean coff_typdef PARAMS ((PTR, const char *));
++static bfd_boolean coff_tag PARAMS ((PTR, const char *));
++static bfd_boolean coff_int_constant PARAMS ((PTR, const char *, bfd_vma));
++static bfd_boolean coff_float_constant PARAMS ((PTR, const char *, double));
++static bfd_boolean coff_typed_constant PARAMS ((PTR, const char *, bfd_vma));
++static bfd_boolean coff_variable
++  PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
++static bfd_boolean coff_start_function PARAMS ((PTR, const char *, bfd_boolean));
++static bfd_boolean coff_function_parameter
++  PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
++static bfd_boolean coff_start_block PARAMS ((PTR, bfd_vma));
++static bfd_boolean coff_end_block PARAMS ((PTR, bfd_vma));
++static bfd_boolean coff_end_function PARAMS ((PTR));
++static bfd_boolean coff_lineno
++  PARAMS ((PTR, const char *, unsigned long, bfd_vma));
 +
-+  COFF_SWAP_TABLE
++static const struct debug_write_fns coff_fns =
++{
++  coff_start_compilation_unit,
++  coff_start_source,
++  coff_empty_type,
++  coff_void_type,
++  coff_int_type,
++  coff_float_type,
++  coff_complex_type,
++  coff_bool_type,
++  coff_enum_type,
++  coff_pointer_type,
++  coff_function_type,
++  coff_reference_type,
++  coff_range_type,
++  coff_array_type,
++  coff_set_type,
++  coff_offset_type,
++  coff_method_type,
++  coff_const_type,
++  coff_volatile_type,
++  coff_start_struct_type,
++  coff_struct_field,
++  coff_end_struct_type,
++  coff_start_class_type,
++  coff_class_static_member,
++  coff_class_baseclass,
++  coff_class_start_method,
++  coff_class_method_variant,
++  coff_class_static_method_variant,
++  coff_class_end_method,
++  coff_end_class_type,
++  coff_typedef_type,
++  coff_tag_type,
++  coff_typdef,
++  coff_tag,
++  coff_int_constant,
++  coff_float_constant,
++  coff_typed_constant,
++  coff_variable,
++  coff_start_function,
++  coff_function_parameter,
++  coff_start_block,
++  coff_end_block,
++  coff_end_function,
++  coff_lineno
 +};
-diff -uNdr binutils-2.17.50.0.18-old/bfd/coffcode.h binutils-2.17.50.0.18/bfd/coffcode.h
---- binutils-2.17.50.0.18-old/bfd/coffcode.h   2007-08-01 17:12:02.000000000 +0200
-+++ binutils-2.17.50.0.18/bfd/coffcode.h       2007-10-20 16:45:33.000000000 +0200
-@@ -1,3 +1,4 @@
++\f
++/*
++ * Copy our input (non-debugging) symbols.  Local symbols will be
++ * maintained in one bucket per each compilation unit, global (and
++ * weak) symbols will be kept in a simple array.
++ */
++static bfd_boolean
++coff_copy_symbols (info, count, sympp)
++     struct coff_write_handle *info;
++     long count;
++     asymbol **sympp;
++{
++  asymbol *osym;
++  long i;
++  struct coff_compilation_unit *up;
 +
- /* Support for the generic parts of most COFF variants, for BFD.
-    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-@@ -1767,6 +1768,17 @@
-   coff->relocbase = 0;
-   coff->local_toc_sym_map = 0;
-+  /* These members communicate important constants about the symbol
-+     table to GDB's symbol-reading code.  These `constants'
-+     unfortunately vary among coff implementations...  */
-+  coff->local_n_btmask = N_BTMASK;
-+  coff->local_n_btshft = N_BTSHFT;
-+  coff->local_n_tmask = N_TMASK;
-+  coff->local_n_tshift = N_TSHIFT;
-+  coff->local_symesz = bfd_coff_symesz (abfd);
-+  coff->local_auxesz = bfd_coff_auxesz (abfd);
-+  coff->local_linesz = bfd_coff_linesz (abfd);
++  up = NULL;
 +
- /*  make_abs_section(abfd);*/
-   return TRUE;
-@@ -1791,17 +1803,6 @@
-   coff->sym_filepos = internal_f->f_symptr;
--  /* These members communicate important constants about the symbol
--     table to GDB's symbol-reading code.  These `constants'
--     unfortunately vary among coff implementations...  */
--  coff->local_n_btmask = N_BTMASK;
--  coff->local_n_btshft = N_BTSHFT;
--  coff->local_n_tmask = N_TMASK;
--  coff->local_n_tshift = N_TSHIFT;
--  coff->local_symesz = bfd_coff_symesz (abfd);
--  coff->local_auxesz = bfd_coff_auxesz (abfd);
--  coff->local_linesz = bfd_coff_linesz (abfd);
--
-   coff->timestamp = internal_f->f_timdat;
-   obj_raw_syment_count (abfd) =
-@@ -1928,6 +1929,11 @@
-       }
-       break;
- #endif
-+#ifdef AVRMAGIC
-+    case AVRMAGIC:
-+      arch = bfd_arch_avr;
-+      break;
-+#endif
- #ifdef MC68MAGIC
-     case MC68MAGIC:
-     case M68MAGIC:
-@@ -2724,6 +2730,13 @@
-       return TRUE;
- #endif
-+#ifdef AVRMAGIC
-+    case bfd_arch_avr:
-+      *magicp = AVRMAGIC;
-+      return TRUE;
-+      break;
-+#endif
++  for (i = 0; i < count; i++)
++    {
++      osym = sympp[i];
 +
- #ifdef PPCMAGIC
-     case bfd_arch_powerpc:
-       *magicp = PPCMAGIC;
-@@ -3520,6 +3533,11 @@
-       section.s_page = coff_get_section_load_page (current);
- #endif
-+#ifdef AVR
-+      /* AVR uses s_paddr the way GNU uses s_vaddr, and effectively
-+       ignores s_vaddr. */
-+      section.s_paddr = current->vma;
-+#endif
- #ifdef COFF_WITH_PE
-       section.s_paddr = 0;
- #endif
-@@ -3864,6 +3882,17 @@
-     internal_a.magic = ZMAGIC;
- #endif
-+#ifdef AVR
-+    /* a.out is a dummy for non-extended COFF */
-+    internal_a.magic = AVRAOUTMAGIC;
-+    /* Upper nibble of f_flags must be set for historical reasons.
-+       The upper byte remains blank on coff-avr, so undo the F_AR32WR
-+       setting performed above. */
-+    internal_f.f_flags |= F_JUNK;
-+    internal_f.f_flags &= ~F_UNUSED;
-+#define __A_MAGIC_SET__
-+#endif /* AVR */
++      /* Try to figure out the .text and .data sections from our input
++       symbols as we walk them.  Unfortunately, this ought to be the
++       /input/ section pointers, so their ->output_section is
++       non-NULL.  That's why we can't simply walk through all the
++       sections of our abfd since this is describing the output
++       only. */
++      if (info->textsect == NULL && osym->section->flags & SEC_CODE)
++      /* Assume this to be our .text section. */
++      info->textsect = osym->section;
++      else if (info->datasect == NULL && osym->section->flags & SEC_DATA)
++      /* Assume this to be our .data section. */
++      info->datasect = osym->section;
 +
- #if defined(PPC_PE)
- #define __A_MAGIC_SET__
-     internal_a.magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
-@@ -3931,8 +3960,16 @@
- #endif
-   }
-+#ifdef AVR_EXT_COFF
-+    /* Note that we do not set F_PTRINFO because the GNU toolchain
-+       doesn't provide any information about the target of a pointer,
-+       so we cannot derive which section our pointer target would be
-+       in. */
-+  internal_a.vstamp = F_FULLPATHS | F_STRUCTINFO;
-+#else
-   /* FIXME: Does anybody ever set this to another value?  */
-   internal_a.vstamp = 0;
-+#endif
-   /* Now should write relocs, strings, syms.  */
-   obj_sym_filepos (abfd) = sym_base;
-@@ -4118,22 +4155,29 @@
-       char * buff;
-       bfd_size_type amount = bfd_coff_aoutsz (abfd);
--      buff = bfd_malloc (amount);
--      if (buff == NULL)
--      return FALSE;
-+      /* Do not attempt to malloc() zero bytes.  According to the
-+         C standard, the behaviour is implementation-defined, and
-+       malloc() might return NULL in that case, which would confuse
-+       us to assume an error where it actually isn't. */
-+      if (amount != 0)
++      if (osym->flags & BSF_FILE)
 +      {
-+        buff = bfd_malloc (amount);
-+        if (buff == NULL)
-+          return FALSE;
--      coff_swap_aouthdr_out (abfd, & internal_a, buff);
--      amount = bfd_bwrite (buff, amount, abfd);
-+        coff_swap_aouthdr_out (abfd, & internal_a, buff);
-+        amount = bfd_bwrite (buff, amount, abfd);
--      free (buff);
-+        free (buff);
--      if (amount != bfd_coff_aoutsz (abfd))
--      return FALSE;
-+        if (amount != bfd_coff_aoutsz (abfd))
-+          return FALSE;
- #ifdef COFF_IMAGE_WITH_PE
--      if (! coff_apply_checksum (abfd))
--      return FALSE;
-+        if (! coff_apply_checksum (abfd))
-+          return FALSE;
- #endif
-+      }
-     }
- #ifdef RS6000COFF_C
-   else
-@@ -4414,6 +4458,10 @@
-           /* In PE, 0x69 (105) denotes a weak external symbol.  */
-           case C_NT_WEAK:
- #endif
-+#ifdef AVR
-+          /* Some AVR COFF compilers handle EXTDEF like EXT. */
-+          case C_EXTDEF:      /* external definition           */
-+#endif
-             switch (coff_classify_symbol (abfd, &src->u.syment))
-               {
-               case COFF_SYMBOL_GLOBAL:
-@@ -4637,7 +4685,9 @@
-                 && src->u.syment.n_scnum == 0)
-               break;
-             /* Fall through.  */
-+#if !defined(AVR)
-           case C_EXTDEF:      /* External definition.  */
-+#endif
-           case C_ULABEL:      /* Undefined label.  */
-           case C_USTATIC:     /* Undefined static.  */
- #ifndef COFF_WITH_PE
-diff -uNdr binutils-2.17.50.0.18-old/bfd/coffgen.c binutils-2.17.50.0.18/bfd/coffgen.c
---- binutils-2.17.50.0.18-old/bfd/coffgen.c    2007-08-01 15:11:47.000000000 +0200
-+++ binutils-2.17.50.0.18/bfd/coffgen.c        2007-10-20 16:45:33.000000000 +0200
-@@ -687,6 +687,20 @@
-             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;
++        /* New file name. */
++        long l;
 +
-+                s->u.syment.n_numaux = n > NAUXENTS? NAUXENTS: n;
-+              }
-           }
-         else
-           /* Modify the symbol values according to their section and
-@@ -815,6 +829,20 @@
-       {
-         if (name_length <= filnmlen)
-           strncpy (auxent->x_file.x_fname, name, filnmlen);
-+        else if (bfd_get_arch (abfd) == bfd_arch_avr)
++        up = NULL;
++
++        /* Well, maybe an old one actually?  If so, append it there.
++           This can happen for files that contribute to multiple
++           (input) sections that were concatenated by the linker
++           (like crt1.S). */
++        for (l = 0; l < info->nunits; l++)
++          {
++            if (strcmp (info->units[l].fname, osym->name) == 0)
++              {
++                up = info->units + l;
++                break;
++              }
++          }
++
++        if (up == NULL)
 +          {
-+            /* AVR COFF records long filenames in successive aux records. */
-+            int i = 1;
-+            while (name_length > filnmlen && i < NAUXENTS)
++            info->units = (struct coff_compilation_unit *)
++              xrealloc (info->units,
++                        ++info->nunits * sizeof(struct coff_compilation_unit));
++            up = info->units + (info->nunits - 1);
++            up->fname = osym->name;
++            up->syms = NULL;
++            up->nsyms = up->totsyms = 0;
++          }
++      }
++      else if (osym->flags & (BSF_GLOBAL | BSF_WEAK))
++      {
++        /* Global (or weak) symbols are recorded outside compilation
++           units. */
++        info->globals = (asymbol **)
++          xrealloc (info->globals, ++info->nglobals * sizeof(asymbol *));
++        info->globals[info->nglobals - 1] = osym;
++        continue;
++      }
++      else if (!bfd_is_const_section(osym->section))
++      {
++        if (osym->flags & BSF_SECTION_SYM)
++          {
++            coff_symbol_type *csymp;
++            /* Just record them by now, they'll be fixed up later. */
++
++            if (info->nsyms == 0 && (info->flags & COFF_FL_AVR) == 0)
 +              {
-+                strncpy (auxent->x_file.x_fname, name, filnmlen);
-+                name += filnmlen;
-+                name_length -= filnmlen;
-+                i++;
-+                auxent = &(native + i)->u.auxent;
++                /* Very first symbol, fake a compilation unit name
++                   for it.  Historical precedence seems to dictate
++                   this, but AVR COFF does not use that. */
++                csymp = (coff_symbol_type *)
++                  coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++                if (csymp == NULL)
++                  return FALSE;
++
++                csymp->symbol.name = xstrdup ("<fake>");
++                csymp->symbol.value = 0;
++                csymp->symbol.udata.p = NULL;
++                csymp->native->u.syment.n_sclass = C_FILE;
++                /* force filename into aux entry */
++                csymp->native->u.syment.n_numaux = 1;
++                coff_record_symbol (info, csymp);
 +              }
-+            strncpy (auxent->x_file.x_fname, name, filnmlen);
++
++            /* convert to COFF native section symbol */
++            csymp = (coff_symbol_type *)
++              coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++            if (csymp == NULL)
++              return FALSE;
++
++            csymp->symbol.name = xstrdup (osym->section->name);
++            csymp->symbol.value = osym->section->output_section->vma;
++            csymp->symbol.flags = BSF_DEBUGGING | BSF_SECTION_SYM;
++            csymp->symbol.section = osym->section;
++            csymp->symbol.udata.p = NULL;
++            csymp->native->fix_scnlen = 1;
++            csymp->native->u.syment.n_sclass = C_STAT;
++            csymp->native->u.syment.n_type = T_NULL;
++            csymp->native->u.syment.n_numaux = 1;
++
++            coff_record_symbol (info, csymp);
++
++            info->secsyms = (coff_symbol_type **)
++              xrealloc (info->secsyms,
++                        ++info->nsecsyms * sizeof(coff_symbol_type *));
++            info->secsyms[info->nsecsyms - 1] = csymp;
 +          }
-         else
-           {
-             auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE;
-@@ -1218,7 +1246,11 @@
-                 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 @@
-           {
-             /* Ordinary short filename, put into memory anyway.  The
-                  Microsoft PE tools sometimes store a filename in
--                 multiple AUX entries.  */
--            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));
-+                 multiple AUX entries.
-+                 AVR COFF does it that way, too. */
-+              if (internal_ptr->u.syment.n_numaux > 1
-+                  && (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 = (long) 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 @@
-   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;
-diff -uNdr binutils-2.17.50.0.18-old/bfd/coffswap.h binutils-2.17.50.0.18/bfd/coffswap.h
---- binutils-2.17.50.0.18-old/bfd/coffswap.h   2007-08-01 15:11:47.000000000 +0200
-+++ binutils-2.17.50.0.18/bfd/coffswap.h       2007-10-20 16:45:33.000000000 +0200
-@@ -383,7 +383,11 @@
-                 void * ext1,
-                 int type,
-                 int class,
--                int indx,
-+                int indx
-+#if defined(AVR) && __GNUC__
-+                __attribute__((unused))
-+#endif
-+                ,
-                 int numaux,
-                 void * in1)
- {
-@@ -409,9 +413,13 @@
- #else
-         if (numaux > 1)
-           {
-+#if defined(AVR)
-+            memcpy (in->x_file.x_fname, ext->x_file.x_fname, sizeof (AUXENT));
-+#else
-             if (indx == 0)
-               memcpy (in->x_file.x_fname, ext->x_file.x_fname,
-                       numaux * sizeof (AUXENT));
-+#endif
-           }
-         else
-           memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
-diff -uNdr binutils-2.17.50.0.18-old/bfd/config.bfd binutils-2.17.50.0.18/bfd/config.bfd
---- binutils-2.17.50.0.18-old/bfd/config.bfd   2007-08-01 15:11:47.000000000 +0200
-+++ binutils-2.17.50.0.18/bfd/config.bfd       2007-10-20 16:45:33.000000000 +0200
-@@ -327,6 +327,7 @@
-   avr-*-*)
-     targ_defvec=bfd_elf32_avr_vec
-+    targ_selvecs="bfd_elf32_avr_vec avrcoff_vec avrextcoff_vec"
-     ;;
-   bfin-*-*)
-diff -uNdr binutils-2.17.50.0.18-old/bfd/configure binutils-2.17.50.0.18/bfd/configure
---- binutils-2.17.50.0.18-old/bfd/configure    2007-08-01 15:11:47.000000000 +0200
-+++ binutils-2.17.50.0.18/bfd/configure        2007-10-20 16:45:33.000000000 +0200
-@@ -19034,6 +19034,8 @@
-     armpe_little_vec)         tb="$tb pe-arm.lo peigen.lo cofflink.lo " ;;
-     armpei_big_vec)           tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;;
-     armpei_little_vec)                tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;;
-+    avrcoff_vec)              tb="$tb coff-avr.lo cofflink.lo " ;;
-+    avrextcoff_vec)           tb="$tb coff-ext-avr.lo cofflink.lo " ;;
-     b_out_vec_big_host)               tb="$tb bout.lo aout32.lo" ;;
-     b_out_vec_little_host)    tb="$tb bout.lo aout32.lo" ;;
-     bfd_efi_app_ia32_vec)     tb="$tb efi-app-ia32.lo peigen.lo cofflink.lo" ;;
-diff -uNdr binutils-2.17.50.0.18-old/bfd/configure.in binutils-2.17.50.0.18/bfd/configure.in
---- binutils-2.17.50.0.18-old/bfd/configure.in 2007-08-01 15:11:47.000000000 +0200
-+++ binutils-2.17.50.0.18/bfd/configure.in     2007-10-20 16:45:33.000000000 +0200
-@@ -612,6 +612,8 @@
-     armpe_little_vec)         tb="$tb pe-arm.lo peigen.lo cofflink.lo " ;;
-     armpei_big_vec)           tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;;
-     armpei_little_vec)                tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;;
-+    avrcoff_vec)              tb="$tb coff-avr.lo cofflink.lo " ;;
-+    avrextcoff_vec)           tb="$tb coff-ext-avr.lo cofflink.lo " ;;
-     b_out_vec_big_host)               tb="$tb bout.lo aout32.lo" ;;
-     b_out_vec_little_host)    tb="$tb bout.lo aout32.lo" ;;
-     bfd_efi_app_ia32_vec)     tb="$tb efi-app-ia32.lo peigen.lo cofflink.lo" ;;
-diff -uNdr binutils-2.17.50.0.18-old/bfd/targets.c binutils-2.17.50.0.18/bfd/targets.c
---- binutils-2.17.50.0.18-old/bfd/targets.c    2007-08-01 15:11:48.000000000 +0200
-+++ binutils-2.17.50.0.18/bfd/targets.c        2007-10-20 16:45:33.000000000 +0200
-@@ -558,6 +558,8 @@
- extern const bfd_target armpe_little_vec;
- extern const bfd_target armpei_big_vec;
- extern const bfd_target armpei_little_vec;
-+extern const bfd_target avrcoff_vec;
-+extern const bfd_target avrextcoff_vec;
- extern const bfd_target b_out_vec_big_host;
- extern const bfd_target b_out_vec_little_host;
- extern const bfd_target bfd_efi_app_ia32_vec;
-@@ -876,6 +878,8 @@
-       &armpe_little_vec,
-       &armpei_big_vec,
-       &armpei_little_vec,
-+      &avrcoff_vec,
-+      &avrextcoff_vec,
-       &b_out_vec_big_host,
-       &b_out_vec_little_host,
-       &bfd_efi_app_ia32_vec,
-diff -uNdr binutils-2.17.50.0.18-old/binutils/Makefile.am binutils-2.17.50.0.18/binutils/Makefile.am
---- binutils-2.17.50.0.18-old/binutils/Makefile.am     2007-08-01 15:11:48.000000000 +0200
-+++ binutils-2.17.50.0.18/binutils/Makefile.am 2007-10-20 16:45:33.000000000 +0200
-@@ -98,7 +98,7 @@
-       resbin.c rescoff.c resrc.c resres.c \
-       size.c srconv.c stabs.c strings.c sysdump.c \
-       unwind-ia64.c version.c \
--      windres.c winduni.c wrstabs.c \
-+      windres.c winduni.c wrcoff.c wrstabs.c \
-       windmc.c mclex.c
- GENERATED_CFILES = \
-@@ -106,7 +106,7 @@
-       defparse.c deflex.c nlmheader.c rcparse.c mcparse.c
- DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c
--WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c
-+WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c wrcoff.c
- # Code shared by all the binutils.
- BULIBS = bucomm.c version.c filemode.c
-diff -uNdr binutils-2.17.50.0.18-old/binutils/Makefile.in binutils-2.17.50.0.18/binutils/Makefile.in
---- binutils-2.17.50.0.18-old/binutils/Makefile.in     2007-08-01 15:11:48.000000000 +0200
-+++ binutils-2.17.50.0.18/binutils/Makefile.in 2007-10-20 16:45:33.000000000 +0200
-@@ -129,7 +129,7 @@
- nm_new_OBJECTS = $(am_nm_new_OBJECTS)
- nm_new_LDADD = $(LDADD)
- am__objects_2 = rddbg.$(OBJEXT) debug.$(OBJEXT) stabs.$(OBJEXT) \
--      ieee.$(OBJEXT) rdcoff.$(OBJEXT)
-+      ieee.$(OBJEXT) rdcoff.$(OBJEXT) wrcoff.$(OBJEXT)
- am__objects_3 = $(am__objects_2) wrstabs.$(OBJEXT)
- am_objcopy_OBJECTS = objcopy.$(OBJEXT) not-strip.$(OBJEXT) \
-       rename.$(OBJEXT) $(am__objects_3) $(am__objects_1)
-@@ -418,7 +418,7 @@
-       resbin.c rescoff.c resrc.c resres.c \
-       size.c srconv.c stabs.c strings.c sysdump.c \
-       unwind-ia64.c version.c \
--      windres.c winduni.c wrstabs.c \
-+      windres.c winduni.c wrcoff.c wrstabs.c \
-       windmc.c mclex.c
- GENERATED_CFILES = \
-@@ -426,7 +426,7 @@
-       defparse.c deflex.c nlmheader.c rcparse.c mcparse.c
- DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c
--WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c
-+WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c wrcoff.c
- # Code shared by all the binutils.
- BULIBS = bucomm.c version.c filemode.c
-diff -uNdr binutils-2.17.50.0.18-old/binutils/bucomm.c binutils-2.17.50.0.18/binutils/bucomm.c
---- binutils-2.17.50.0.18-old/binutils/bucomm.c        2007-08-01 15:11:49.000000000 +0200
-+++ binutils-2.17.50.0.18/binutils/bucomm.c    2007-10-20 16:45:33.000000000 +0200
-@@ -501,6 +501,32 @@
-   return ret;
- }
-+/* Return the basename of "file", i. e. everything minus whatever
-+   directory part has been provided.  Stolen from bfd/archive.c.
-+   Should we also handle the VMS case (as in bfd/archive.c)?  */
-+const char *
-+bu_basename (file)
-+     const char *file;
-+{
-+  const char *filename = strrchr (file, '/');
++        else
++          {
++            /* Local symbol in a named section, will be recorded
++               within the respective compilation unit. */
++            if (up == NULL)
++              {
++                fprintf (stderr,
++                         _("Discarding local symbol outside any compilation unit"));
++                if (osym->name)
++                  fprintf (stderr, ": %s", osym->name);
++                putc ('\n', stderr);
++              }
++            else
++              {
++                up->syms = (asymbol **)
++                  xrealloc (up->syms, ++up->nsyms * sizeof(asymbol *));
++                up->syms[up->nsyms - 1] = osym;
++                up->totsyms = up->nsyms;
++                continue;
++              }
++          }
++      }
++    }
 +
-+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
-+  {
-+    /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
-+    char *bslash = strrchr (file, '\\');
-+    if (filename == NULL || (bslash != NULL && bslash > filename))
-+      filename = bslash;
-+    if (filename == NULL && file[0] != '\0' && file[1] == ':')
-+      filename = file + 1;
-+  }
-+#endif
-+  if (filename != (char *) NULL)
-+    filename++;
-+  else
-+    filename = file;
-+  return filename;
++  return TRUE;
 +}
 +
- /* Returns the size of the named file.  If the file does not
-    exist, or if it is not a real file, then a suitable non-fatal
-    error message is printed and zero is returned.  */
-diff -uNdr binutils-2.17.50.0.18-old/binutils/bucomm.h binutils-2.17.50.0.18/binutils/bucomm.h
---- binutils-2.17.50.0.18-old/binutils/bucomm.h        2007-08-01 15:11:49.000000000 +0200
-+++ binutils-2.17.50.0.18/binutils/bucomm.h    2007-10-20 16:45:33.000000000 +0200
-@@ -54,6 +54,8 @@
- off_t get_file_size (const char *);
-+const char *bu_basename PARAMS ((const char *));
++/* Find a name in the symbol table.  If found, the respective entry in
++   the symbol vector is zeroed, so after processing all debugging
++   symbols, only non-debugging symbols will remain. */
++static asymbol *
++coff_find_symbol (info, name, isfunction, global)
++     struct coff_write_handle *info;
++     const char *name;
++     bfd_boolean isfunction;
++     bfd_boolean global;
++{
++  asymbol *symp;
++  long i;
++  size_t namelen;
 +
- extern char *program_name;
- /* filemode.c */
-diff -uNdr binutils-2.17.50.0.18-old/binutils/budbg.h binutils-2.17.50.0.18/binutils/budbg.h
---- binutils-2.17.50.0.18-old/binutils/budbg.h 2007-08-01 15:11:49.000000000 +0200
-+++ binutils-2.17.50.0.18/binutils/budbg.h     2007-10-20 16:45:33.000000000 +0200
-@@ -51,8 +51,11 @@
- extern bfd_boolean write_ieee_debugging_info (bfd *, void *);
--/* Routine used to read COFF debugging information.  */
-+/* Routine used to read and write COFF debugging information.  */
- extern bfd_boolean parse_coff (bfd *, asymbol **, long, void *);
-+extern bfd_boolean write_coff_debugging_info
-+  (bfd *abfd, void *, long *symcountp, asymbol ***);
++  if (global)
++    {
++      for (i = 0; i < info->nglobals; i++)
++      {
++        symp = info->globals[i];
++        if (symp == NULL)
++          continue;
++        if (strcmp (name, symp->name) == 0
++            && ((symp->flags & BSF_FUNCTION) != 0) == (isfunction == TRUE))
++          {
++            info->globals[i] = NULL;
++            return symp;
++          }
++      }
++      return NULL;
++    }
 +
- #endif
-diff -uNdr binutils-2.17.50.0.18-old/binutils/debug.c binutils-2.17.50.0.18/binutils/debug.c
---- binutils-2.17.50.0.18-old/binutils/debug.c 2007-08-01 15:11:49.000000000 +0200
-+++ binutils-2.17.50.0.18/binutils/debug.c     2007-10-20 16:45:33.000000000 +0200
-@@ -31,6 +31,7 @@
- #include <assert.h>
- #include "bfd.h"
- #include "libiberty.h"
-+#include "bucomm.h"
- #include "debug.h"
- /* Global information we keep for debugging.  A pointer to this
-@@ -552,6 +553,19 @@
-   struct debug_type *t;
- };
-+/* Simple list, used for pathname translations. */
-+struct xlat_list
++  if (info->currentfile == NULL)
++    return NULL;
++
++  /* For local symbols, the match optionally stops at a dot in the
++     symtab symbol's name; this is used by gcc to indicate
++     function-scope static symbols (e. g. symbol "foo" will become
++     "foo.1" in function scope). */
++  namelen = strlen (name);
++  for (i = 0; i < info->currentfile->nsyms; i++)
++    {
++      symp = info->currentfile->syms[i];
++      if (symp == NULL)
++      continue;
++      if (strncmp (name, symp->name, namelen) == 0
++        && (symp->name[namelen] == '\0' || symp->name[namelen] == '.')
++        && ((symp->flags & BSF_FUNCTION) != 0) == (isfunction == TRUE))
++      {
++        info->currentfile->syms[i] = NULL;
++        info->currentfile->totsyms--;
++        return symp;
++      }
++    }
++  return NULL;
++}
++
++static void
++coff_record_symbol (info, csymp)
++     struct coff_write_handle *info;
++     coff_symbol_type *csymp;
 +{
-+  /* Next string on list. */
-+  struct xlat_list *next;
-+  /* Old part to match against. */
-+  const char *old;
-+  size_t olen;
-+  /* New part to replace. */
-+  const char *newstr;
-+  size_t nlen;
-+};
++  struct coff_private_symdata *priv;
 +
- /* Local functions.  */
- static void debug_error (const char *);
-@@ -588,6 +602,11 @@
-   (struct debug_handle *, struct debug_type *, struct debug_type *);
- static bfd_boolean debug_class_type_samep
-   (struct debug_handle *, struct debug_type *, struct debug_type *);
-+static const char *debug_xlat_pathname (const char *);
++  info->syms = (asymbol **) xrealloc (info->syms,
++                                    ++info->nsyms * sizeof (asymbol *));
++  info->syms[info->nsyms - 1] = (asymbol *)csymp;
 +
-+/* List of pathname translations. */
-+static struct xlat_list *xlat, *xltail;
-+static bfd_boolean xlat_basename;
\f
- /* Issue an error message.  */
-@@ -680,6 +699,8 @@
-   if (name == NULL)
-     name = "";
-+  else
-+    name = debug_xlat_pathname (name);
-   nfile = (struct debug_file *) xmalloc (sizeof *nfile);
-   memset (nfile, 0, sizeof *nfile);
-@@ -720,6 +741,8 @@
-   if (name == NULL)
-     name = "";
-+  else
-+    name = debug_xlat_pathname (name);
-   if (info->current_unit == NULL)
-     {
-@@ -3370,3 +3393,69 @@
-   return TRUE;
- }
++  if ((priv = csymp->symbol.udata.p) != NULL)
++    {
++      if (priv->shash != NULL)
++      {
++        struct coff_struct_hash_entry *shash = priv->shash;
++        shash->fixidxs = (long *)
++          xrealloc (shash->fixidxs, ++shash->nfixidxs * sizeof (long));
++        shash->fixidxs[shash->nfixidxs - 1] = info->nsyms - 1;
++      }
++      if (priv->ehash != NULL)
++      {
++        struct coff_enum_hash_entry *ehash = priv->ehash;
++        ehash->fixidxs = (long *)
++          xrealloc (ehash->fixidxs, ++ehash->nfixidxs * sizeof (long));
++        ehash->fixidxs[ehash->nfixidxs - 1] = info->nsyms - 1;
++      }
++      free (priv);
++      csymp->symbol.udata.p = NULL;
++    }
++
++  /* If there are any pending endndx fixes, pop the last element from
++     that stack, and record the current symbol for fixing.  We need to
++     do this here since we need to record our current csymp->native
++     (where that csymp is completely unrelated to whatever symbol was
++     previously generated that requested the fixup).  The stack of
++     pending fixes is required since several endndx fixes could be
++     nested, e. g. the start of a function has a pending fix that
++     needs to point to the first symbol after the function, but there
++     could be an anonymous struct definition inside that function's
++     local variables where the endndx needs to point after the last
++     symbol of this struct.  Also, structs and unions could be nested.
++
++     Each call to coff_record_symbol() can fix at most one endndx
++     (even if more are pending in the stack), but that's OK.
++
++     Note that bfd/coffgen.c converts that csymp->native into a
++     symtable slot number after coff_renumber_symbols() has been
++     run. */
++  if (info->flags & COFF_FL_FIX_ENDNDX)
++    {
++      struct coff_fix_stack *fsp, *ofsp;
++      union internal_auxent *aux;
++
++      assert (info->fixes != NULL);
++
++      fsp = info->fixes;
++      ofsp = NULL;
++      while (fsp->next != NULL)
++      {
++        ofsp = fsp;
++        fsp = fsp->next;
++      }
++      if (ofsp == NULL)
++      info->fixes = NULL;
++      else
++      ofsp->next = NULL;
++
++      aux = &(fsp->native->u.auxent);
++      fsp->native->fix_end = 1;
++      aux->x_sym.x_fcnary.x_fcn.x_endndx.p = csymp->native;
++      free (fsp);
++
++      info->flags &= ~COFF_FL_FIX_ENDNDX;
++    }
++}
++
++/* Fixup AVR COFF register handling: they don't only mention the
++   starting register number, but all registers, each within one byte
++   of the value.  Unused register positions are filled up with
++   0xff. */
++static symvalue
++coff_fixup_avr_register (val, size)
++     symvalue val;
++     int size;
++{
++  union
++  {
++    unsigned char c[4];
++    symvalue v;
++  } u;
 +
-+/* Register a pathname translation. */
-+void
-+debug_register_pathname_xlat (oname, nname)
-+     const char *oname;
-+     const char *nname;
++  u.c[1] = u.c[2] = u.c[3] = 0xff;
++  u.c[0] = val;
++  if (size > 8)
++    u.c[1] = val + 1;
++  if (size > 16)
++    {
++      u.c[2] = val + 2;
++      u.c[3] = val + 3;
++    }
++
++  return u.v;
++}
++
++/* Initialize an entry in the hash tables.  */
++
++static struct bfd_hash_entry *
++coff_name_type_newfunc (entry, table, string)
++     struct bfd_hash_entry *entry;
++     struct bfd_hash_table *table;
++     const char *string;
 +{
-+  struct xlat_list *xlp;
++  struct coff_name_type_hash_entry *ret =
++    (struct coff_name_type_hash_entry *) entry;
 +
-+  /* Special case: if oname is given as NULL, this means the
-+     --basename option has been given to objcopy. */
-+  if (oname == NULL)
++  /* Allocate the structure if it has not already been allocated by a
++     subclass.  */
++  if (ret == NULL)
++    ret = ((struct coff_name_type_hash_entry *)
++         bfd_hash_allocate (table, sizeof *ret));
++  if (ret == NULL)
++    return NULL;
++
++  /* Call the allocation method of the superclass.  */
++  ret = ((struct coff_name_type_hash_entry *)
++       bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
++  if (ret)
 +    {
-+      xlat_basename = TRUE;
-+      return;
++      /* Set local fields.  */
++      ret->types = NULL;
++      ret->emitted = FALSE;
 +    }
 +
-+  xlp = (struct xlat_list *) xmalloc (sizeof (struct xlat_list));
-+  xlp->next = NULL;
-+  if (xlat == NULL)
-+    xlat = xltail = xlp;
-+  else
++  return (struct bfd_hash_entry *) ret;
++}
++
++static struct bfd_hash_entry *
++coff_struct_newfunc (entry, table, string)
++     struct bfd_hash_entry *entry;
++     struct bfd_hash_table *table;
++     const char *string;
++{
++  struct coff_struct_hash_entry *ret =
++    (struct coff_struct_hash_entry *) entry;
++
++  /* Allocate the structure if it has not already been allocated by a
++     subclass.  */
++  if (ret == NULL)
++    ret = ((struct coff_struct_hash_entry *)
++         bfd_hash_allocate (table, sizeof *ret));
++  if (ret == NULL)
++    return NULL;
++
++  /* Call the allocation method of the superclass.  */
++  ret = ((struct coff_struct_hash_entry *)
++       bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
++  if (ret)
 +    {
-+      xltail->next = xlp;
-+      xltail = xlp;
++      /* Set local fields.  */
++      ret->types = NULL;
++      ret->emitted = FALSE;
++      ret->fixidxs = NULL;
++      ret->nfixidxs = 0;
++      ret->native = NULL;
 +    }
-+  xlp->old = oname;
-+  xlp->newstr = nname;
-+  xlp->olen = strlen (oname);
-+  xlp->nlen = strlen (nname);
++
++  return (struct bfd_hash_entry *) ret;
 +}
 +
-+/* Try to translate a pathname. */
-+static const char *
-+debug_xlat_pathname (oname)
-+     const char *oname;
++static struct bfd_hash_entry *
++coff_enum_newfunc (entry, table, string)
++     struct bfd_hash_entry *entry;
++     struct bfd_hash_table *table;
++     const char *string;
 +{
-+  struct xlat_list *xlp;
-+  char *cp;
-+  size_t olen;
++  struct coff_enum_hash_entry *ret =
++    (struct coff_enum_hash_entry *) entry;
 +
-+  if (xlat_basename)
-+    return bu_basename (oname);  
++  /* Allocate the structure if it has not already been allocated by a
++     subclass.  */
++  if (ret == NULL)
++    ret = ((struct coff_enum_hash_entry *)
++         bfd_hash_allocate (table, sizeof *ret));
++  if (ret == NULL)
++    return NULL;
 +
-+  olen = strlen (oname);
-+  for (xlp = xlat; xlp; xlp = xlp->next)
++  /* Call the allocation method of the superclass.  */
++  ret = ((struct coff_enum_hash_entry *)
++       bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
++  if (ret)
 +    {
-+      if (xlp->olen > olen)
-+      /* This cannot be our turn. */
-+      continue;
-+      /* Since we have pre-computed all our length values to avoid
-+       repetitively computing them, just use memcmp() since it's
-+       faster than strcmp(). */
-+      if (memcmp (xlp->old, oname, xlp->olen) == 0)
-+      {
-+        cp = (char *) xmalloc (olen + xlp->nlen - xlp->olen + 1);
-+        memcpy (cp, xlp->newstr, xlp->nlen);
-+        memcpy (cp + xlp->nlen, oname + xlp->olen,
-+                olen - xlp->olen + 1);
-+        return cp;
-+      }
++      /* Set local fields.  */
++      ret->types = NULL;
++      ret->emitted = FALSE;
++      ret->fixidxs = NULL;
++      ret->nfixidxs = 0;
++      ret->native = NULL;
 +    }
 +
-+  /* Not found, pass the original name on. */
-+  return oname;
++  return (struct bfd_hash_entry *) ret;
 +}
-diff -uNdr binutils-2.17.50.0.18-old/binutils/debug.h binutils-2.17.50.0.18/binutils/debug.h
---- binutils-2.17.50.0.18-old/binutils/debug.h 2007-08-01 15:11:49.000000000 +0200
-+++ binutils-2.17.50.0.18/binutils/debug.h     2007-10-20 16:45:33.000000000 +0200
-@@ -440,6 +440,12 @@
- extern bfd_boolean debug_start_source (void *, const char *);
-+/* Register a pathname translation for source (and include) filenames.
-+   This is used by the --change-pathname option of objcopy. */
 +
-+extern void debug_register_pathname_xlat
-+  PARAMS ((const char *, const char *));
++/* Look up an entry in the hash tables.  */
 +
- /* Record a function definition.  This implicitly starts a function
-    block.  The debug_type argument is the type of the return value.
-    The bfd_boolean indicates whether the function is globally visible.
-diff -uNdr binutils-2.17.50.0.18-old/binutils/objcopy.c binutils-2.17.50.0.18/binutils/objcopy.c
---- binutils-2.17.50.0.18-old/binutils/objcopy.c       2007-08-01 15:11:49.000000000 +0200
-+++ binutils-2.17.50.0.18/binutils/objcopy.c   2007-10-20 16:45:33.000000000 +0200
-@@ -32,6 +32,7 @@
- #include "elf-bfd.h"
- #include <sys/stat.h>
- #include "libbfd.h"
-+#include "debug.h"
- /* A list of symbols to explicitly strip out, or to keep.  A linked
-    list is good enough for a small number from the command line, but
-@@ -272,7 +273,9 @@
-     OPTION_PURE,
-     OPTION_IMPURE,
-     OPTION_EXTRACT_SYMBOL,
--    OPTION_REVERSE_BYTES
-+    OPTION_REVERSE_BYTES,
-+    OPTION_CHANGE_PATHNAME,
-+    OPTION_BASENAME
-   };
- /* Options to handle if running as "strip".  */
-@@ -316,10 +319,12 @@
-   {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
-   {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
-   {"alt-machine-code", required_argument, 0, OPTION_ALT_MACH_CODE},
-+  {"basename", no_argument, 0, OPTION_BASENAME},
-   {"binary-architecture", required_argument, 0, 'B'},
-   {"byte", required_argument, 0, 'b'},
-   {"change-addresses", required_argument, 0, OPTION_CHANGE_ADDRESSES},
-   {"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR},
-+  {"change-pathname", required_argument, 0, OPTION_CHANGE_PATHNAME},
-   {"change-section-address", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
-   {"change-section-lma", required_argument, 0, OPTION_CHANGE_SECTION_LMA},
-   {"change-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_VMA},
-@@ -504,6 +509,8 @@
-      --prefix-alloc-sections <prefix>\n\
-                                    Add <prefix> to start of every allocatable\n\
-                                      section name\n\
-+     --change-pathname <old>=<new> Change debug pathnames from <old> to <new>\n\
-+     --basename                    Strip directory part from debug pathnames\n\
-   -v --verbose                     List all object files modified\n\
-   @<file>                          Read options from <file>\n\
-   -V --version                     Display this program's version number\n\
-@@ -911,6 +918,8 @@
-   asymbol **from = isyms, **to = osyms;
-   long src_count = 0, dst_count = 0;
-   int relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
-+  bfd_boolean need_for_debugging = convert_debugging
-+    && bfd_get_arch (abfd) == bfd_arch_avr;
-   for (; src_count < symcount; src_count++)
-     {
-@@ -1010,9 +1019,10 @@
-              || bfd_is_com_section (bfd_get_section (sym)))
-       keep = strip_symbols != STRIP_UNNEEDED;
-       else if ((flags & BSF_DEBUGGING) != 0)  /* Debugging symbol.  */
--      keep = (strip_symbols != STRIP_DEBUG
--              && strip_symbols != STRIP_UNNEEDED
--              && ! convert_debugging);
-+      keep = need_for_debugging
-+              || (strip_symbols != STRIP_DEBUG
-+                  && strip_symbols != STRIP_UNNEEDED
-+                  && ! convert_debugging);
-       else if (bfd_coff_get_comdat_section (abfd, bfd_get_section (sym)))
-       /* COMDAT sections store special information in local
-          symbols, so we cannot risk stripping any of them.  */
-@@ -2579,6 +2589,10 @@
-     return write_ieee_debugging_info (obfd, dhandle);
-   if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
-+      && bfd_get_arch (obfd) == bfd_arch_avr)
-+    return write_coff_debugging_info (obfd, dhandle, symcountp, symppp);
++#define coff_name_type_hash_lookup(table, string, create, copy) \
++  ((struct coff_name_type_hash_entry *) \
++   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
 +
-+  if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
-       || bfd_get_flavour (obfd) == bfd_target_elf_flavour)
-     {
-       bfd_byte *syms, *strings;
-@@ -3280,6 +3294,30 @@
-         prefix_alloc_sections_string = optarg;
-         break;
-+      case OPTION_CHANGE_PATHNAME:
-+        {
-+          const char *s;
-+          int len;
-+          char *name;
++/* Traverse the hash table.  */
++
++#define coff_name_type_hash_traverse(table, func, info)                       \
++  (bfd_hash_traverse                                                  \
++   (&(table)->root,                                                   \
++    (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
++    (info)))
++
++#define coff_struct_hash_lookup(table, string, create, copy) \
++  ((struct coff_struct_hash_entry *) \
++   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
++
++/* Traverse the hash table.  */
++
++#define coff_struct_hash_traverse(table, func, info)                  \
++  (bfd_hash_traverse                                                  \
++   (&(table)->root,                                                   \
++    (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
++    (info)))
 +
-+          s = strchr (optarg, '=');
-+          if (s == NULL)
-+            fatal (_("bad format for %s"), "--change-pathname");
++#define coff_enum_hash_lookup(table, string, create, copy) \
++  ((struct coff_enum_hash_entry *) \
++   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
 +
-+          len = s - optarg;
-+          name = (char *) xmalloc (len + 1);
-+          strncpy (name, optarg, len);
-+          name[len] = '\0';
++/* Traverse the hash table.  */
 +
-+          debug_register_pathname_xlat (name, s + 1);
-+        }
-+        break;
++#define coff_enum_hash_traverse(table, func, info)                    \
++  (bfd_hash_traverse                                                  \
++   (&(table)->root,                                                   \
++    (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
++    (info)))
 +
-+      case OPTION_BASENAME:
-+        /* very special case of pathname translation */
-+        debug_register_pathname_xlat (NULL, NULL);
-+        break;
++#define coff_push_type(kind) \
++  tst = (struct coff_type_stack *) xmalloc (sizeof (struct coff_type_stack)); \
++  memset (tst, 0, sizeof (*tst)); \
++  tst->next = info->tstack; \
++  tst->tsk = kind; \
++  info->tstack = tst
 +
-       case OPTION_READONLY_TEXT:
-         bfd_flags_to_set |= WP_TEXT;
-         bfd_flags_to_clear &= ~WP_TEXT;
-diff -uNdr binutils-2.17.50.0.18-old/binutils/rdcoff.c binutils-2.17.50.0.18/binutils/rdcoff.c
---- binutils-2.17.50.0.18-old/binutils/rdcoff.c        2007-08-01 15:11:49.000000000 +0200
-+++ binutils-2.17.50.0.18/binutils/rdcoff.c    2007-10-20 16:45:33.000000000 +0200
-@@ -82,6 +82,9 @@
-   struct coff_slots *slots;
-   /* Basic types.  */
-   debug_type basic[T_MAX + 1];
-+  /* Some general information, kept here for convenience. */
-+  size_t intsize;             /* sizeof (int) */
-+  size_t doublesize;          /* sizeof (double) */
- };
- static debug_type *coff_get_slot (struct coff_types *, int);
-@@ -101,6 +104,7 @@
-   (bfd *, struct coff_types *, asymbol *, long, struct internal_syment *,
-    void *, debug_type, bfd_boolean);
- static bfd_boolean external_coff_symbol_p (int sym_class);
-+static bfd_vma coff_convert_register (bfd *, bfd_vma);
\f
- /* Return the slot for a type.  */
-@@ -271,8 +275,7 @@
-       break;
-     case T_INT:
--      /* FIXME: Perhaps the size should depend upon the architecture.  */
--      ret = debug_make_int_type (dhandle, 4, FALSE);
-+      ret = debug_make_int_type (dhandle, types->intsize, FALSE);
-       name = "int";
-       break;
-@@ -287,7 +290,7 @@
-       break;
-     case T_DOUBLE:
--      ret = debug_make_float_type (dhandle, 8);
-+      ret = debug_make_float_type (dhandle, types->doublesize);
-       name = "double";
-       break;
-@@ -307,7 +310,7 @@
-       break;
-     case T_UINT:
--      ret = debug_make_int_type (dhandle, 4, TRUE);
-+      ret = debug_make_int_type (dhandle, types->intsize, TRUE);
-       name = "unsigned int";
-       break;
-@@ -565,6 +568,8 @@
-     case C_WEAKEXT:
-     case C_EXT:
-+      /* AVR COFF abuses C_EXTDEF */
-+    case C_EXTDEF:
-       if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
-                                  DEBUG_GLOBAL, bfd_asymbol_value (sym)))
-       return FALSE;
-@@ -580,9 +585,9 @@
-       break;
-     case C_REG:
--      /* FIXME: We may need to convert the register number.  */
-       if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type,
--                                 DEBUG_REGISTER, bfd_asymbol_value (sym)))
-+                                 DEBUG_REGISTER,
-+                                 coff_convert_register (abfd, bfd_asymbol_value (sym))))
-       return FALSE;
-       break;
-@@ -596,9 +601,9 @@
-       break;
-     case C_REGPARM:
--      /* FIXME: We may need to convert the register number.  */
-       if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type,
--                                  DEBUG_PARM_REG, bfd_asymbol_value (sym)))
-+                                  DEBUG_PARM_REG,
-+                                  coff_convert_register (abfd, bfd_asymbol_value (sym))))
-       return FALSE;
-       break;
-@@ -648,6 +653,28 @@
-   return FALSE;
- }
-+static bfd_vma
-+coff_convert_register (abfd, val)
-+     bfd *abfd;
-+     bfd_vma val;
++#define coff_pop_type() \
++  tst = info->tstack; \
++  if (tst == NULL) { \
++    fprintf (stderr, _("empty type stack in coff_pop_type()\n")); \
++    return FALSE; \
++  } \
++  info->tstack = tst->next; \
++  tst->next = NULL
++
++#define coff_complain_unsupp(s) \
++  fprintf (stderr, _("%s type not supported in %s\n"), \
++         s, info->abfd->xvec->name); \
++  return FALSE
++
++/* These function is called via the hash traverse routine when freeing
++   a hash table (at the end of a translation unit). */
++static bfd_boolean
++coff_free_type_info (h, p)
++     struct coff_name_type_hash_entry *h;
++     PTR p ATTRIBUTE_UNUSED;
 +{
++  struct coff_type_stack *tst, *otst;
 +
-+  switch (bfd_get_arch (abfd))
++  for (tst = h->types; tst != NULL;)
 +    {
-+    case bfd_arch_avr:
-+      /* AVR COFF wants to describe up to four registers by the four
-+       bytes of the 32-bit value.  Unused bytes are filled with
-+       0xff.  In theory, this would allow for non-contiguous
-+       register usage to hold a single value, but hopefully, no
-+       compiler is going to use that feature.  We could not handle
-+       it anyway. */
-+      return val & 0xff;
++      otst = tst;
++      tst = tst->next;
++      free (otst);
++    }
++  return TRUE;
++}
 +
-+    default:
-+      return val;
++static bfd_boolean
++coff_free_struct_info (h, p)
++     struct coff_struct_hash_entry *h;
++     PTR p ATTRIBUTE_UNUSED;
++{
++  struct coff_type_stack *tst, *otst, *xtst, *xotst;
++  struct coff_struct_fields *fp;
++  long i;
++
++  for (tst = h->types; tst != NULL;)
++    {
++      otst = tst;
++      if (tst->u.ts_struct.tagismalloced)
++      free (tst->u.ts_struct.tag.malloctag);
++      for (i = 0, fp = tst->u.ts_struct.fields;
++         i < tst->u.ts_struct.nfields;
++         i++, fp++)
++      {
++        xtst = fp->types;
++        while (xtst != NULL)
++          {
++            xotst = xtst->next;
++            free (xtst);
++            xtst = xotst;
++          }
++      }
++      free (tst->u.ts_struct.fields);
++      tst = tst->next;
++      free (otst);
 +    }
++  return TRUE;
 +}
 +
- /* This is the main routine.  It looks through all the symbols and
-    handles them.  */
-@@ -674,6 +701,17 @@
-   types.slots = NULL;
-   for (i = 0; i <= T_MAX; i++)
-     types.basic[i] = DEBUG_TYPE_NULL;
-+  switch (bfd_get_arch (abfd))
++static bfd_boolean
++coff_free_enum_info (h, p)
++     struct coff_enum_hash_entry *h;
++     PTR p ATTRIBUTE_UNUSED;
++{
++  struct coff_type_stack *tst, *otst;
++
++  for (tst = h->types; tst != NULL;)
 +    {
-+    case bfd_arch_avr:
-+      types.intsize = 2;
-+      types.doublesize = 4;
-+      break;
++      otst = tst;
++      if (tst->u.ts_enum.tagismalloced)
++      free (tst->u.ts_enum.tag.malloctag);
++      tst = tst->next;
++      free (otst);
++    }
++  return TRUE;
++}
 +
-+    default:
-+      types.intsize = 4;
-+      types.doublesize = 8;
++static unsigned int
++coff_get_fundamental_type (info, tst)
++     struct coff_write_handle *info ATTRIBUTE_UNUSED;
++     struct coff_type_stack *tst;
++{
++  size_t i;
++
++  /* See if one of our predefined types will fit. */
++  if (tst->tsk == TS_INT)
++    {
++      for (i = 0;
++         i < sizeof coff_predef_types / sizeof (struct coff_predef_type);
++         i++)
++      {
++        if (coff_predef_types[i].kind == TS_INT
++            && coff_predef_types[i].size == tst->u.ts_int.size
++            && coff_predef_types[i].isunsigned == tst->u.ts_int.isunsigned)
++          return coff_predef_types[i].slot;
++      }
++      fprintf (stderr,
++             _("%ssigned %d-bit integer type not available in COFF\n"),
++             tst->u.ts_int.isunsigned? "un": "", tst->u.ts_int.size * 8);
++    }
++  else
++    {
++      for (i = 0;
++         i < sizeof coff_predef_types / sizeof (struct coff_predef_type);
++         i++)
++      {
++        if (coff_predef_types[i].kind == TS_FLOAT
++            && coff_predef_types[i].size == tst->u.ts_float.size)
++          return coff_predef_types[i].slot;
++      }
++      fprintf (stderr, _("%d-bit float type not available in COFF\n"),
++             tst->u.ts_float.size * 8);
 +    }
-   next_c_file = -1;
-   fnname = NULL;
-@@ -734,7 +772,6 @@
-       switch (syment.n_sclass)
-       {
-       case C_EFCN:
--      case C_EXTDEF:
-       case C_ULABEL:
-       case C_USTATIC:
-       case C_LINE:
-@@ -757,6 +794,8 @@
-         /* Fall through.  */
-       case C_WEAKEXT:
-       case C_EXT:
-+        /* AVR COFF abuses C_EXTDEF for C_EXT */
-+      case C_EXTDEF:
-         if (ISFCN (syment.n_type))
-           {
-             fnname = name;
-diff -uNdr binutils-2.17.50.0.18-old/binutils/wrcoff.c binutils-2.17.50.0.18/binutils/wrcoff.c
---- binutils-2.17.50.0.18-old/binutils/wrcoff.c        1970-01-01 01:00:00.000000000 +0100
-+++ binutils-2.17.50.0.18/binutils/wrcoff.c    2007-10-20 16:45:53.000000000 +0200
-@@ -0,0 +1,3408 @@
-+/* wrcoff.c -- Generate (AVR) COFF debugging information
-+   Copyright 2003 Free Software Foundation, Inc.
 +
-+   Written by Joerg Wunsch.
++  return T_NULL;
++}
 +
-+   This file is part of GNU Binutils.
++static bfd_boolean
++coff_make_typed_symbol (info, csympp, stopat)
++     struct coff_write_handle *info;
++     coff_symbol_type **csympp;
++     enum ts_kind stopat;
++{
++  struct coff_type_stack *tst;
++  union internal_auxent *aux;
++  struct coff_struct_hash_entry *shash;
++  struct coff_enum_hash_entry *ehash;
++  struct coff_private_symdata *priv;
++  unsigned int type, numaux, arydim, size, i, nele, nderived;
++  const char *name;
++  bfd_boolean oldavrcoff = (info->flags & (COFF_FL_AVR | COFF_FL_EXT_AVR))
++    == COFF_FL_AVR;
 +
-+   This program is free software; you can redistribute it and/or modify
-+   it under the terms of the GNU General Public License as published by
-+   the Free Software Foundation; either version 2 of the License, or
-+   (at your option) any later version.
++  /* Synthesize a new internal COFF symbol. */
++  *csympp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (*csympp == NULL)
++    return FALSE;
 +
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
++  priv = (struct coff_private_symdata *) xmalloc (sizeof *priv);
++  memset (priv, 0, sizeof *priv);
 +
-+   You should have received a copy of the GNU General Public License
-+   along with this program; if not, write to the Free Software
-+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-+   02111-1307, USA.  */
++  type = arydim = size = nderived = 0;
 +
-+/* This file contains code which writes out COFF debugging
-+   information.  By now, this has only been tested on the AVR
-+   platform, though any attempt has been made to keep the conversion
-+   applicable to possible other COFF debugging consumers as well. */
++  aux = &(((*csympp)->native + 1)->u.auxent);
 +
-+#include <assert.h>
-+#include "sysdep.h"
-+#include "bfd.h"
-+#include "coff/internal.h"
-+#include "bucomm.h"
-+#include "libiberty.h"
-+#include "safe-ctype.h"
-+#include "debug.h"
-+#include "budbg.h"
++  /* Now, walk the type stack, and see how we could convert the info
++     we've got to what COFF understands. */
++  for (;;)
++    {
++      if (info->tstack == NULL)
++      break;
 +
-+/* Enabling COFF_DEBUG will trace the internal callback functions and
-+   their parameters as debug_write() calls them. */
-+//#define COFF_DEBUG 1
++      /* If we have been advised to not pop the entire stack, stop
++       here. */
++      if (info->tstack->tsk == stopat && info->tstack->next == NULL)
++      break;
 +
-+#include "libcoff.h"
++      coff_pop_type ();
 +
-+#define N_TMASK (coff_data (info->abfd)->local_n_tmask)
-+#define N_BTSHFT (coff_data (info->abfd)->local_n_btshft)
-+#define N_BTMASK (coff_data (info->abfd)->local_n_btmask)
-+#define N_TSHIFT (coff_data (info->abfd)->local_n_tshift)
++      switch (tst->tsk)
++      {
++      case TS_NONE:
++        /* cannot happen */
++        break;
 +
-+/* Structure of local symbols per compilation unit. */
-+struct coff_compilation_unit
-+{
-+  const char *fname;
-+  asymbol **syms;
-+  long nsyms, totsyms;
-+};
++      case TS_EMPTY:
++        if (info->tstack != NULL && info->tstack->tsk != stopat)
++          fprintf (stderr, _("empty type not last on type stack\n"));
++        /* type |= T_NULL; */
++        break;
 +
-+enum ts_kind
-+{
-+  TS_EMPTY,
-+  TS_VOID,
-+  TS_INT,
-+  TS_FLOAT,
-+  TS_COMPLEX,
-+  TS_ENUM,
-+  TS_POINTER,
-+  TS_FUNC,
-+  TS_ARRAY,
-+  TS_STRUCT,
-+  TS_NONE = -1
-+};
++      case TS_VOID:
++        if (info->tstack != NULL && info->tstack->tsk != stopat)
++          fprintf (stderr, _("void type not last on type stack\n"));
++        type |= T_VOID;
++        break;
 +
-+/* Structure defining the pre-defined types. */
-+struct coff_predef_type
-+{
-+  enum ts_kind kind;
-+  unsigned int size;          /* in bytes */
-+  bfd_boolean isunsigned;
-+  int slot;
-+};
++      case TS_INT:
++        if (info->tstack != NULL && info->tstack->tsk != stopat)
++          fprintf (stderr, _("int type not last on type stack\n"));
++        type |= coff_get_fundamental_type (info, tst);
++        if (size == 0)
++          size = tst->u.ts_int.size;
++        break;
 +
-+struct coff_type_stack;
-+struct coff_hash_entry;
++      case TS_FLOAT:
++        if (info->tstack != NULL && info->tstack->tsk != stopat)
++          fprintf (stderr, _("float type not last on type stack\n"));
++        type |= coff_get_fundamental_type (info, tst);
++        if (size == 0)
++          size = tst->u.ts_float.size;
++        break;
 +
-+struct coff_struct_fields
-+{
-+  const char *name;
-+  bfd_vma bitpos;
-+  bfd_vma bitsize;
-+  enum debug_visibility visibility;
-+  struct coff_type_stack *types;
-+};
++      case TS_POINTER:
++        nderived++;
++        type = ((type & ~N_BTMASK) << N_TSHIFT) | (DT_PTR << N_BTSHFT);
++        size = info->pointersize;
++        break;
 +
-+/* Our type stack. */
-+struct coff_type_stack
-+{
-+  struct coff_type_stack *next;
-+  enum ts_kind tsk;
-+  union
-+  {
-+    /* TS_INT */
-+    struct
-+    {
-+      unsigned int size;
-+      bfd_boolean isunsigned;
-+    }
-+    ts_int;
++      case TS_FUNC:
++        nderived++;
++        type = ((type & ~N_BTMASK) << N_TSHIFT) | (DT_FCN << N_BTSHFT);
++        /* AUX entry for DT_FCN will be filled in elsewhere. */
++        break;
 +
-+    /* TS_FLOAT */
-+    struct
-+    {
-+      unsigned int size;
-+    }
-+    ts_float;
++      case TS_ARRAY:
++        /* We need to limit arydim so the assignment below won't
++           overwrite random locations. */
++        if (arydim >= DIMNUM)
++          {
++            fprintf (stderr,
++                     _("More than %d array dimensions, result is invalid.\n"),
++                     DIMNUM);
++            arydim = DIMNUM - 1;
++          }
++        nderived++;
++        type = ((type & ~N_BTMASK) << N_TSHIFT) | (DT_ARY << N_BTSHFT);
++        aux->x_sym.x_fcnary.x_ary.x_dimen[arydim++] =
++          tst->u.ts_array.high - tst->u.ts_array.low + 1;
 +
-+    /* TS_ENUM */
-+    struct
-+    {
-+      union
-+      {
-+      const char *fixtag;
-+      char *malloctag;
-+      }
-+      tag;
-+      bfd_boolean tagismalloced;
-+      const char **names;
-+      bfd_signed_vma *vals;
-+      struct coff_enum_hash_entry *ehash;
-+    }
-+    ts_enum;
++        break;
++
++      case TS_COMPLEX:
++        coff_complain_unsupp (_("complex"));
++
++      case TS_ENUM:
++        type |= T_ENUM;
++        if (size == 0)
++          size = info->enumsize;
++
++        if (tst->u.ts_enum.ehash != NULL)
++          {
++            /* enum tag will be fixed later. */
++            priv->ehash = tst->u.ts_enum.ehash;
++            break;
++          }
++        if (tst->u.ts_enum.tagismalloced)
++          name = tst->u.ts_enum.tag.malloctag;
++        else
++          name = tst->u.ts_enum.tag.fixtag;
++        ehash = coff_enum_hash_lookup (&info->enums, name,
++                                       TRUE, tst->u.ts_enum.tagismalloced);
++        if (ehash == NULL)
++          return FALSE;
++        if (!ehash->emitted)
++          {
++            if (ehash->types == NULL)
++              {
++                ehash->types = (struct coff_type_stack *)
++                  xmalloc (sizeof (struct coff_type_stack));
++                memcpy (ehash->types, tst, sizeof (struct coff_type_stack));
++              }
++            ehash->emitted = TRUE;
++            coff_emit_enum (info, tst, ehash);
++            if (ehash->nfixidxs != 0)
++              {
++                coff_symbol_type *symp;
++                unsigned i;
 +
-+    /* TS_FUNC */
-+    struct
-+    {
-+      struct coff_type_stack *savedts;
-+    }
-+    ts_func;
++                for (i = 0; i < ehash->nfixidxs; i++)
++                  {
++                    combined_entry_type *np;
 +
-+    /* TS_ARRAY */
-+    struct
-+    {
-+      bfd_signed_vma low;
-+      bfd_signed_vma high;
-+    }
-+    ts_array;
++                    symp = (coff_symbol_type *) info->syms[ehash->fixidxs[i]];
++                    symp->native->u.syment.n_type &= ~N_BTMASK;
++                    symp->native->u.syment.n_type |= T_ENUM;
 +
-+    /* TS_STRUCT */
-+    struct
-+    {
-+      union
-+      {
-+      const char *fixtag;
-+      char *malloctag;
-+      }
-+      tag;
-+      bfd_boolean tagismalloced;
-+      unsigned int id;
-+      bfd_boolean isstruct;
-+      unsigned int size;
-+      long nfields;
-+      struct coff_struct_fields *fields;
-+      struct coff_type_stack *savedts;
-+      struct coff_struct_hash_entry *shash;
-+    }
-+    ts_struct;
-+  }
-+  u;
-+};
++                    if (oldavrcoff)
++                      continue;
 +
-+struct coff_name_type_hash_table
-+{
-+  struct bfd_hash_table root;
-+};
++                    np = symp->native + 1;
++                    np->fix_tag = 1;
++                    np->u.auxent.x_sym.x_tagndx.p = ehash->native;
++                    if (np->u.auxent.x_sym.x_misc.x_fsize == 0)
++                      np->u.auxent.x_sym.x_misc.x_lnsz.x_size = size;
++                  }
 +
-+struct coff_name_type_hash_entry
-+{
-+  struct bfd_hash_entry root;
-+  /* Information for this name.  */
-+  struct coff_type_stack *types;
-+  bfd_boolean emitted;
-+};
++                free (ehash->fixidxs);
++                ehash->nfixidxs = 0;
++              }
++          }
++        if (!oldavrcoff)
++          {
++            ((*csympp)->native + 1)->fix_tag = 1;
++            aux->x_sym.x_tagndx.p = ehash->native;
++            if (aux->x_sym.x_misc.x_fsize == 0)
++              aux->x_sym.x_misc.x_lnsz.x_size = size;
++          }
++        break;
 +
-+struct coff_struct_hash_table
-+{
-+  struct bfd_hash_table root;
-+};
++      case TS_STRUCT:
++        if (tst->u.ts_struct.isstruct)
++          type |= T_STRUCT;
++        else
++          type |= T_UNION;
++        if (size == 0)
++          size = tst->u.ts_struct.size;
 +
-+struct coff_struct_hash_entry
-+{
-+  struct bfd_hash_entry root;
-+  /* Information for this name.  */
-+  struct coff_type_stack *types;
-+  bfd_boolean emitted;
-+  combined_entry_type *native;
-+  /* list of symbol indices that need fixing */
-+  long *fixidxs;
-+  unsigned nfixidxs;
-+};
++        if (tst->u.ts_struct.shash != NULL)
++          {
++            /* struct tag will be fixed later. */
++            priv->shash = tst->u.ts_struct.shash;
++            break;
++          }
++        if (tst->u.ts_struct.tagismalloced)
++          name = tst->u.ts_struct.tag.malloctag;
++        else
++          name = tst->u.ts_struct.tag.fixtag;
++        shash = coff_struct_hash_lookup (&info->structs, name,
++                                         TRUE, tst->u.ts_struct.tagismalloced);
++        if (shash == NULL)
++          return FALSE;
++        if (!shash->emitted)
++          {
++            if (shash->types == NULL)
++              {
++                shash->types = (struct coff_type_stack *)
++                  xmalloc (sizeof (struct coff_type_stack));
++                memcpy (shash->types, tst, sizeof (struct coff_type_stack));
++              }
++            shash->emitted = TRUE;
++            coff_emit_struct (info, tst, shash);
++            if (shash->nfixidxs != 0)
++              {
++                coff_symbol_type *symp;
++                unsigned i;
 +
-+struct coff_enum_hash_table
-+{
-+  struct bfd_hash_table root;
-+};
++                for (i = 0; i < shash->nfixidxs; i++)
++                  {
++                    combined_entry_type *np;
 +
-+struct coff_enum_hash_entry
-+{
-+  struct bfd_hash_entry root;
-+  /* Information for this name.  */
-+  struct coff_type_stack *types;
-+  bfd_boolean emitted;
-+  combined_entry_type *native;
-+  /* list of symbol indices that need fixing */
-+  long *fixidxs;
-+  unsigned nfixidxs;
-+};
++                    symp = (coff_symbol_type *) info->syms[shash->fixidxs[i]];
++                    symp->native->u.syment.n_type &= ~N_BTMASK;
++                    if (tst->u.ts_struct.isstruct)
++                      symp->native->u.syment.n_type |= T_STRUCT;
++                    else
++                      symp->native->u.syment.n_type |= T_UNION;
 +
-+/* COFF private symbol data.  Used as a cookie to pass data around
-+   between various processing stages.  The generic COFF handling code
-+   doesn't use any private data. */
-+struct coff_private_symdata
-+{
-+  unsigned int size;          /* size of symbol, used in AVR register
-+                                 translation */
-+  struct coff_struct_hash_entry *shash; /* TS_STRUCT hash for fixups */
-+  struct coff_enum_hash_entry *ehash; /* TS_ENUM hash for fixups */
-+};
++                    if (oldavrcoff)
++                      continue;
 +
-+/* Stack of tags that need endndx fixing. */
-+struct coff_fix_stack
-+{
-+  struct coff_fix_stack *next;
-+  combined_entry_type *native;
-+};
++                    np = symp->native + 1;
++                    np->fix_tag = 1;
++                    np->u.auxent.x_sym.x_tagndx.p = shash->native;
++                    if (np->u.auxent.x_sym.x_misc.x_fsize == 0)
++                      np->u.auxent.x_sym.x_misc.x_lnsz.x_size = size;
++                  }
 +
-+/* This is the handle passed through debug_write.  */
++                free (shash->fixidxs);
++                shash->nfixidxs = 0;
++              }
++          }
++        if (!oldavrcoff)
++          {
++            ((*csympp)->native + 1)->fix_tag = 1;
++            aux->x_sym.x_tagndx.p = shash->native;
++            if (aux->x_sym.x_misc.x_fsize == 0)
++              aux->x_sym.x_misc.x_lnsz.x_size = size;
++          }
++        break;
++      }
++      free (tst);
++    }
 +
-+struct coff_write_handle
-+{
-+  /* The BFD.  */
-+  bfd *abfd;
-+  /* Pointers to .text and .data sections, can be used as defaults if
-+     no other information is available. */
-+  asection *textsect;
-+  asection *datasect;
-+  /* Some special flags. */
-+  unsigned long flags;
-+  /* Flags describing architecture options. */
-+#define COFF_FL_AVR   0x0001  /* COFF is for AVR platform. */
-+#define COFF_FL_EXT_AVR       0x0002  /* AVR "extended" COFF */
-+  /* Flags describing internal status information. */
-+#define COFF_FL_FIX_ENDNDX    0x10000 /* apply endndx fix at next symbol */
-+#define COFF_FL_START_FCN     0x20000 /* begin of function pending */
-+#define COFF_FL_FIX_BB                0x40000 /* fix last ".bb" symbol */
-+  /* List of our compilation units, from input symbol table. */
-+  struct coff_compilation_unit *units;
-+  long nunits;
-+  struct coff_compilation_unit *currentfile;
-+  /* Global symbols from input symbol table. */
-+  asymbol **globals;
-+  long nglobals;
-+  /* Section syms for named sections. */
-+  coff_symbol_type **secsyms;
-+  long nsecsyms;
-+  /* Our COFF symbols. */
-+  asymbol **syms;
-+  long nsyms;
-+  /* Total line number count. */
-+  unsigned long totlnos;
-+  /* Size of standard objects on this arch. */
-+  unsigned int pointersize;
-+  unsigned int enumsize;
-+  /* Pending information when starting a function.  We have to defer
-+     almost everything, some actions can be taken when seeing the
-+     starting block of that function, some will even have to wait
-+     until we see the end of the function. */
-+  const char *funname;                /* name of function */
-+  bfd_boolean funglobal;              /* global/local function? */
-+  unsigned int lastlno;               /* last line number seen so far */
-+  long funcindex;             /* index of ".func" symbol in syms */
-+  unsigned int nlnos;         /* line numbers recorded for this function*/
-+  bfd_vma endaddr;            /* last .eb address we have seen so far */
-+  unsigned int funlno;                /* first line number in function */
-+  coff_symbol_type **fargs;   /* function arguments */
-+  unsigned int nfargs;
-+  asection *funcsection;      /* section the current function is using */
-+  /* Type information */
-+  struct coff_type_stack *tstack;
-+  struct coff_name_type_hash_table types;
-+  struct coff_struct_hash_table structs;
-+  struct coff_enum_hash_table enums;
-+  unsigned nenums;            /* counter for anonymous enum tags */
-+  /* Stack of pending endndx fixes, see coff_record_symbol(). */
-+  struct coff_fix_stack *fixes;
-+};
++  if (nderived > 6)
++    fprintf (stderr,
++           _("More than 6 derived type specifiers, result is invalid.\n"));
++
++  /* Our type computation so far used the reverse order for derived
++     type specifiers.  Fix this here if there was more than one
++     derived type specifier. */
++  if (nderived > 1)
++    {
++      unsigned int nty, bty;
++      bty = type & N_BTMASK;
++      type = type >> N_BTSHFT;
++      nty = 0;
++      while (nderived-- > 0)
++      {
++        nty = (nty << N_TSHIFT) | (type & (N_TMASK >> N_BTSHFT));
++        type >>= N_TSHIFT;
++      }
++      type = (nty << N_BTSHFT) | bty;
++    }
 +
-+/* Predefined types, default to usual 32-bit architectures.
-+   Arch-dependant different byte sizes will be tuned upon entering
-+   write_coff_debugging_info().  The table is looked up from front to
-+   end, so we put `more popular' types that might have the same size
-+   as other types first (e. g. "int" precedes "long" and "short"). */
-+static struct coff_predef_type coff_predef_types[] =
-+{
-+  { TS_INT, 4, FALSE, 4 },    /* signed int */
-+  { TS_INT, 1, FALSE, 2 },    /* signed char */
-+  { TS_INT, 2, FALSE, 3 },    /* signed short */
-+  { TS_INT, 4, FALSE, 5 },    /* long int */
-+  { TS_FLOAT, 8, FALSE, 7 },  /* double */
-+  { TS_FLOAT, 4, FALSE, 6 },  /* float */
-+  { TS_INT, 4, TRUE, 14 },    /* unsigned int */
-+  { TS_INT, 1, TRUE, 12 },    /* unsigned char */
-+  { TS_INT, 2, TRUE, 13 },    /* unsigned short */
-+  { TS_INT, 4, TRUE, 15 },    /* unsigned long */
-+};
++  if (ISARY (type))
++    {
++      /* Compute size of entire array. */
++      for (i = 0, nele = 1; i < arydim; i++)
++      nele *= aux->x_sym.x_fcnary.x_ary.x_dimen[i];
++      aux->x_sym.x_misc.x_lnsz.x_size = size * nele;
++    }
 +
-+static bfd_boolean coff_copy_symbols
-+  PARAMS ((struct coff_write_handle *, long, asymbol **));
-+static asymbol *coff_find_symbol
-+  PARAMS ((struct coff_write_handle *, const char *, bfd_boolean, bfd_boolean));
-+static void coff_record_symbol
-+  PARAMS ((struct coff_write_handle *, coff_symbol_type *));
-+static symvalue coff_fixup_avr_register PARAMS ((symvalue, int));
-+static struct bfd_hash_entry *coff_name_type_newfunc
-+  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-+static bfd_boolean coff_free_type_info
-+  PARAMS ((struct coff_name_type_hash_entry *, PTR));
-+static struct bfd_hash_entry *coff_struct_newfunc
-+  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-+static bfd_boolean coff_free_struct_info
-+  PARAMS ((struct coff_struct_hash_entry *, PTR));
-+static struct bfd_hash_entry *coff_enum_newfunc
-+  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-+static bfd_boolean coff_free_enum_info
-+  PARAMS ((struct coff_enum_hash_entry *, PTR));
-+static unsigned int coff_get_fundamental_type
-+  PARAMS ((struct coff_write_handle *, struct coff_type_stack *));
-+static bfd_boolean coff_make_typed_symbol
-+  PARAMS ((struct coff_write_handle *, coff_symbol_type **, enum ts_kind));
-+static bfd_boolean coff_emit_struct
-+  PARAMS ((struct coff_write_handle *, struct coff_type_stack *,
-+         struct coff_struct_hash_entry *));
-+static bfd_boolean coff_emit_enum
-+  PARAMS ((struct coff_write_handle *, struct coff_type_stack *,
-+         struct coff_enum_hash_entry *));
-+static bfd_boolean coff_emit_ndebug_sym
-+  PARAMS ((struct coff_write_handle *, asymbol *, bfd_boolean));
++  numaux = 0;
++  if (ISARY (type) || ISFCN (type))
++    numaux++;
++  if ((BTYPE (type) == T_STRUCT || BTYPE (type) == T_UNION
++       || BTYPE (type) == T_ENUM)
++      && !oldavrcoff)
++    numaux++;
++  /* Only AVR COFF uses multiple AUX entries. */
++  if (numaux > 1 && (info->flags & COFF_FL_AVR) == 0)
++    numaux = 1;
 +
-+static bfd_boolean coff_start_compilation_unit PARAMS ((PTR, const char *));
-+static bfd_boolean coff_start_source PARAMS ((PTR, const char *));
-+static bfd_boolean coff_empty_type PARAMS ((PTR));
-+static bfd_boolean coff_void_type PARAMS ((PTR));
-+static bfd_boolean coff_int_type PARAMS ((PTR, unsigned int, bfd_boolean));
-+static bfd_boolean coff_float_type PARAMS ((PTR, unsigned int));
-+static bfd_boolean coff_complex_type PARAMS ((PTR, unsigned int));
-+static bfd_boolean coff_bool_type PARAMS ((PTR, unsigned int));
-+static bfd_boolean coff_enum_type
-+  PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
-+static bfd_boolean coff_pointer_type PARAMS ((PTR));
-+static bfd_boolean coff_function_type PARAMS ((PTR, int, bfd_boolean));
-+static bfd_boolean coff_reference_type PARAMS ((PTR));
-+static bfd_boolean coff_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
-+static bfd_boolean coff_array_type
-+  PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, bfd_boolean));
-+static bfd_boolean coff_set_type PARAMS ((PTR, bfd_boolean));
-+static bfd_boolean coff_offset_type PARAMS ((PTR));
-+static bfd_boolean coff_method_type PARAMS ((PTR, bfd_boolean, int, bfd_boolean));
-+static bfd_boolean coff_const_type PARAMS ((PTR));
-+static bfd_boolean coff_volatile_type PARAMS ((PTR));
-+static bfd_boolean coff_start_struct_type
-+  PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int));
-+static bfd_boolean coff_struct_field
-+  PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
-+static bfd_boolean coff_end_struct_type PARAMS ((PTR));
-+static bfd_boolean coff_start_class_type
-+  PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int, bfd_boolean,
-+         bfd_boolean));
-+static bfd_boolean coff_class_static_member
-+  PARAMS ((PTR, const char *, const char *, enum debug_visibility));
-+static bfd_boolean coff_class_baseclass
-+  PARAMS ((PTR, bfd_vma, bfd_boolean, enum debug_visibility));
-+static bfd_boolean coff_class_start_method PARAMS ((PTR, const char *));
-+static bfd_boolean coff_class_method_variant
-+  PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean, bfd_boolean,
-+         bfd_vma, bfd_boolean));
-+static bfd_boolean coff_class_static_method_variant
-+  PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean, bfd_boolean));
-+static bfd_boolean coff_class_end_method PARAMS ((PTR));
-+static bfd_boolean coff_end_class_type PARAMS ((PTR));
-+static bfd_boolean coff_typedef_type PARAMS ((PTR, const char *));
-+static bfd_boolean coff_tag_type
-+  PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
-+static bfd_boolean coff_typdef PARAMS ((PTR, const char *));
-+static bfd_boolean coff_tag PARAMS ((PTR, const char *));
-+static bfd_boolean coff_int_constant PARAMS ((PTR, const char *, bfd_vma));
-+static bfd_boolean coff_float_constant PARAMS ((PTR, const char *, double));
-+static bfd_boolean coff_typed_constant PARAMS ((PTR, const char *, bfd_vma));
-+static bfd_boolean coff_variable
-+  PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
-+static bfd_boolean coff_start_function PARAMS ((PTR, const char *, bfd_boolean));
-+static bfd_boolean coff_function_parameter
-+  PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
-+static bfd_boolean coff_start_block PARAMS ((PTR, bfd_vma));
-+static bfd_boolean coff_end_block PARAMS ((PTR, bfd_vma));
-+static bfd_boolean coff_end_function PARAMS ((PTR));
-+static bfd_boolean coff_lineno
-+  PARAMS ((PTR, const char *, unsigned long, bfd_vma));
++  priv->size = size;
++  (*csympp)->symbol.udata.p = priv;
++  (*csympp)->native->u.syment.n_type = type;
++  (*csympp)->native->u.syment.n_numaux = numaux;
 +
-+static const struct debug_write_fns coff_fns =
-+{
-+  coff_start_compilation_unit,
-+  coff_start_source,
-+  coff_empty_type,
-+  coff_void_type,
-+  coff_int_type,
-+  coff_float_type,
-+  coff_complex_type,
-+  coff_bool_type,
-+  coff_enum_type,
-+  coff_pointer_type,
-+  coff_function_type,
-+  coff_reference_type,
-+  coff_range_type,
-+  coff_array_type,
-+  coff_set_type,
-+  coff_offset_type,
-+  coff_method_type,
-+  coff_const_type,
-+  coff_volatile_type,
-+  coff_start_struct_type,
-+  coff_struct_field,
-+  coff_end_struct_type,
-+  coff_start_class_type,
-+  coff_class_static_member,
-+  coff_class_baseclass,
-+  coff_class_start_method,
-+  coff_class_method_variant,
-+  coff_class_static_method_variant,
-+  coff_class_end_method,
-+  coff_end_class_type,
-+  coff_typedef_type,
-+  coff_tag_type,
-+  coff_typdef,
-+  coff_tag,
-+  coff_int_constant,
-+  coff_float_constant,
-+  coff_typed_constant,
-+  coff_variable,
-+  coff_start_function,
-+  coff_function_parameter,
-+  coff_start_block,
-+  coff_end_block,
-+  coff_end_function,
-+  coff_lineno
-+};
-+\f
-+/*
-+ * Copy our input (non-debugging) symbols.  Local symbols will be
-+ * maintained in one bucket per each compilation unit, global (and
-+ * weak) symbols will be kept in a simple array.
-+ */
-+static bfd_boolean
-+coff_copy_symbols (info, count, sympp)
++  /* If the fundamental type comes out as T_NULL, this means we don't
++     have any type information.  Just don't emit any aux entries in
++     that case, and drop any derived type information as well. */
++  if (BTYPE (type) == T_NULL)
++    {
++      printf ("coff_make_typed_symbol() -> T_NULL\n");
++      //(*csympp)->native->u.syment.n_type = T_NULL;
++      (*csympp)->native->u.syment.n_numaux = 0;
++    }
++
++  return TRUE;
++}
++
++static bfd_boolean coff_emit_struct (info, tst, shash)
 +     struct coff_write_handle *info;
-+     long count;
-+     asymbol **sympp;
++     struct coff_type_stack *tst;
++     struct coff_struct_hash_entry *shash;
 +{
-+  asymbol *osym;
++  coff_symbol_type *csymp, *scsymp, *ecsymp;
++  union internal_auxent *aux;
++  struct coff_fix_stack *fixp, *ofp;
++  bfd_boolean isstruct = tst->u.ts_struct.isstruct;
++  bfd_boolean isbitfield = FALSE;
++  struct coff_type_stack *savedtst;
++  struct coff_struct_fields *fp;
++  unsigned short sclass;
 +  long i;
-+  struct coff_compilation_unit *up;
 +
-+  up = NULL;
++  if ((info->flags & (COFF_FL_AVR | COFF_FL_EXT_AVR)) ==
++      COFF_FL_AVR)
++    /* old AVR COFF doesn't support struct debugging */
++    return TRUE;
++
++  /* Synthesize a new internal COFF symbol for the struct/union. */
++  scsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (scsymp == NULL)
++    return FALSE;
++
++  if (tst->u.ts_struct.tagismalloced)
++    scsymp->symbol.name = xstrdup (tst->u.ts_struct.tag.malloctag);
++  else
++    scsymp->symbol.name = tst->u.ts_struct.tag.fixtag;
++  scsymp->symbol.flags = BSF_NOT_AT_END;
++  scsymp->symbol.section = bfd_und_section_ptr;
++  scsymp->native->u.syment.n_sclass = isstruct? C_STRTAG: C_UNTAG;
++  scsymp->native->u.syment.n_type = isstruct? T_STRUCT: T_UNION;
++  scsymp->native->u.syment.n_numaux = 1;
++  scsymp->symbol.udata.p = NULL;
++  scsymp->symbol.value = 0;
++
++  shash->native = scsymp->native;
++
++  /* Synthesize a new internal COFF symbol for the end of struct/union. */
++  ecsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (ecsymp == NULL)
++    return FALSE;
++
++  ecsymp->symbol.name = ".eos";
++  ecsymp->symbol.flags = BSF_NOT_AT_END;
++  /* We need to use the com section here since bfd/coffgen.c
++     translates this into an N_UNDEF one without clobbering the
++     value. */
++  ecsymp->symbol.section = bfd_com_section_ptr;
++  ecsymp->native->u.syment.n_sclass = C_EOS;
++  ecsymp->symbol.udata.p = NULL;
++  ecsymp->symbol.value = tst->u.ts_struct.size;
++  ecsymp->native->u.syment.n_numaux = 1;
++  (ecsymp->native + 1)->fix_tag = 1;
++  aux = &((ecsymp->native + 1)->u.auxent);
++  aux->x_sym.x_tagndx.p = scsymp->native;
++  aux->x_sym.x_misc.x_lnsz.x_size = tst->u.ts_struct.size;
++
++  coff_record_symbol (info, scsymp);
 +
-+  for (i = 0; i < count; i++)
++  savedtst = info->tstack;
++
++  if (isstruct)
 +    {
-+      osym = sympp[i];
++      /* First, make a quick walk along all the fields, and figure out
++       * whether we've got a genuine struct or a bitfield struct. */
++      for (i = 0, fp = tst->u.ts_struct.fields;
++         i < tst->u.ts_struct.nfields;
++         i++, fp++)
++      if (fp->bitsize % 8 != 0)
++        {
++          isbitfield = TRUE;
++          break;
++        }
++    }
 +
-+      /* Try to figure out the .text and .data sections from our input
-+       symbols as we walk them.  Unfortunately, this ought to be the
-+       /input/ section pointers, so their ->output_section is
-+       non-NULL.  That's why we can't simply walk through all the
-+       sections of our abfd since this is describing the output
-+       only. */
-+      if (info->textsect == NULL && osym->section->flags & SEC_CODE)
-+      /* Assume this to be our .text section. */
-+      info->textsect = osym->section;
-+      else if (info->datasect == NULL && osym->section->flags & SEC_DATA)
-+      /* Assume this to be our .data section. */
-+      info->datasect = osym->section;
++  sclass = isstruct? (isbitfield? C_FIELD: C_MOS): C_MOU;
 +
-+      if (osym->flags & BSF_FILE)
++  for (i = 0, fp = tst->u.ts_struct.fields;
++       i < tst->u.ts_struct.nfields;
++       i++, fp++)
++    {
++      if (strlen (fp->name) == 0)
 +      {
-+        /* New file name. */
-+        long l;
-+
-+        up = NULL;
++        /* empty name could happen inside bitfield */
++        fp->types = NULL;
++        continue;
++      }
 +
-+        /* Well, maybe an old one actually?  If so, append it there.
-+           This can happen for files that contribute to multiple
-+           (input) sections that were concatenated by the linker
-+           (like crt1.S). */
-+        for (l = 0; l < info->nunits; l++)
-+          {
-+            if (strcmp (info->units[l].fname, osym->name) == 0)
-+              {
-+                up = info->units + l;
-+                break;
-+              }
-+          }
++      info->tstack = fp->types;
++      if (!coff_make_typed_symbol (info, &csymp, TS_NONE))
++      return FALSE;
 +
-+        if (up == NULL)
-+          {
-+            info->units = (struct coff_compilation_unit *)
-+              xrealloc (info->units,
-+                        ++info->nunits * sizeof(struct coff_compilation_unit));
-+            up = info->units + (info->nunits - 1);
-+            up->fname = osym->name;
-+            up->syms = NULL;
-+            up->nsyms = up->totsyms = 0;
-+          }
-+      }
-+      else if (osym->flags & (BSF_GLOBAL | BSF_WEAK))
++      csymp->symbol.name = xstrdup (fp->name);
++      csymp->symbol.flags = BSF_NOT_AT_END;
++      csymp->symbol.section = bfd_com_section_ptr;
++      csymp->native->u.syment.n_sclass = sclass;
++      csymp->symbol.value = isbitfield? fp->bitpos: fp->bitpos / 8;
++      if (isbitfield)
 +      {
-+        /* Global (or weak) symbols are recorded outside compilation
-+           units. */
-+        info->globals = (asymbol **)
-+          xrealloc (info->globals, ++info->nglobals * sizeof(asymbol *));
-+        info->globals[info->nglobals - 1] = osym;
-+        continue;
++        csymp->native->u.syment.n_numaux = 1;
++        aux = &((csymp->native + 1)->u.auxent);
++        aux->x_sym.x_misc.x_lnsz.x_size = fp->bitsize;
 +      }
-+      else if (!bfd_is_const_section(osym->section))
-+      {
-+        if (osym->flags & BSF_SECTION_SYM)
-+          {
-+            coff_symbol_type *csymp;
-+            /* Just record them by now, they'll be fixed up later. */
 +
-+            if (info->nsyms == 0 && (info->flags & COFF_FL_AVR) == 0)
-+              {
-+                /* Very first symbol, fake a compilation unit name
-+                   for it.  Historical precedence seems to dictate
-+                   this, but AVR COFF does not use that. */
-+                csymp = (coff_symbol_type *)
-+                  coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+                if (csymp == NULL)
-+                  return FALSE;
++      coff_record_symbol (info, csymp);
 +
-+                csymp->symbol.name = xstrdup ("<fake>");
-+                csymp->symbol.value = 0;
-+                csymp->symbol.udata.p = NULL;
-+                csymp->native->u.syment.n_sclass = C_FILE;
-+                /* force filename into aux entry */
-+                csymp->native->u.syment.n_numaux = 1;
-+                coff_record_symbol (info, csymp);
-+              }
++      fp->types = NULL;
++    }
 +
-+            /* convert to COFF native section symbol */
-+            csymp = (coff_symbol_type *)
-+              coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+            if (csymp == NULL)
-+              return FALSE;
++  info->tstack = savedtst;
 +
-+            csymp->symbol.name = xstrdup (osym->section->name);
-+            csymp->symbol.value = osym->section->output_section->vma;
-+            csymp->symbol.flags = BSF_DEBUGGING | BSF_SECTION_SYM;
-+            csymp->symbol.section = osym->section;
-+            csymp->symbol.udata.p = NULL;
-+            csymp->native->fix_scnlen = 1;
-+            csymp->native->u.syment.n_sclass = C_STAT;
-+            csymp->native->u.syment.n_type = T_NULL;
-+            csymp->native->u.syment.n_numaux = 1;
++  /* Record our endndx field for later fixing. */
++  fixp = (struct coff_fix_stack *) xmalloc (sizeof (struct coff_fix_stack));
++  fixp->native = scsymp->native + 1;  /* points to first AUX */
++  fixp->next = NULL;
++  if (info->fixes == NULL)
++    info->fixes = fixp;
++  else
++    {
++      for (ofp = info->fixes; ofp->next != NULL;)
++      ofp = ofp->next;
++      ofp->next = fixp;
++    }
 +
-+            coff_record_symbol (info, csymp);
++  coff_record_symbol (info, ecsymp);
++  info->flags |= COFF_FL_FIX_ENDNDX;
 +
-+            info->secsyms = (coff_symbol_type **)
-+              xrealloc (info->secsyms,
-+                        ++info->nsecsyms * sizeof(coff_symbol_type *));
-+            info->secsyms[info->nsecsyms - 1] = csymp;
-+          }
-+        else
-+          {
-+            /* Local symbol in a named section, will be recorded
-+               within the respective compilation unit. */
-+            if (up == NULL)
-+              {
-+                fprintf (stderr,
-+                         _("Discarding local symbol outside any compilation unit"));
-+                if (osym->name)
-+                  fprintf (stderr, ": %s", osym->name);
-+                putc ('\n', stderr);
-+              }
-+            else
-+              {
-+                up->syms = (asymbol **)
-+                  xrealloc (up->syms, ++up->nsyms * sizeof(asymbol *));
-+                up->syms[up->nsyms - 1] = osym;
-+                up->totsyms = up->nsyms;
-+                continue;
-+              }
-+          }
-+      }
++  return TRUE;
++}
++
++static bfd_boolean coff_emit_enum (info, tst, ehash)
++     struct coff_write_handle *info;
++     struct coff_type_stack *tst;
++     struct coff_enum_hash_entry *ehash;
++{
++  coff_symbol_type *csymp, *scsymp, *ecsymp;
++  union internal_auxent *aux;
++  struct coff_fix_stack *fixp, *ofp;
++  int i;
++
++  if ((info->flags & (COFF_FL_AVR | COFF_FL_EXT_AVR)) ==
++      COFF_FL_AVR)
++    /* old AVR COFF doesn't support enum debugging */
++    return TRUE;
++
++  /* Synthesize a new internal COFF symbol for the enum. */
++  scsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (scsymp == NULL)
++    return FALSE;
++
++  if (tst->u.ts_enum.tagismalloced)
++    scsymp->symbol.name = xstrdup (tst->u.ts_enum.tag.malloctag);
++  else
++    scsymp->symbol.name = tst->u.ts_enum.tag.fixtag;
++  scsymp->symbol.flags = BSF_NOT_AT_END;
++  scsymp->symbol.section = bfd_und_section_ptr;
++  scsymp->native->u.syment.n_sclass = C_ENTAG;
++  scsymp->native->u.syment.n_type = T_ENUM;
++  scsymp->native->u.syment.n_numaux = 1;
++  scsymp->symbol.udata.p = NULL;
++  scsymp->symbol.value = 0;
++
++  ehash->native = scsymp->native;
++
++  /* Synthesize a new internal COFF symbol for the end of struct/union. */
++  ecsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (ecsymp == NULL)
++    return FALSE;
++
++  ecsymp->symbol.name = ".eos";
++  ecsymp->symbol.flags = BSF_NOT_AT_END;
++  /* We need to use the com section here since bfd/coffgen.c
++     translates this into an N_UNDEF one without clobbering the
++     value. */
++  ecsymp->symbol.section = bfd_com_section_ptr;
++  ecsymp->native->u.syment.n_sclass = C_EOS;
++  ecsymp->symbol.udata.p = NULL;
++  ecsymp->symbol.value = info->enumsize;
++  ecsymp->native->u.syment.n_numaux = 1;
++  (ecsymp->native + 1)->fix_tag = 1;
++  aux = &((ecsymp->native + 1)->u.auxent);
++  aux->x_sym.x_tagndx.p = scsymp->native;
++  aux->x_sym.x_misc.x_lnsz.x_size = info->enumsize;
++
++  coff_record_symbol (info, scsymp);
++
++  for (i = 0;; i++)
++    {
++      const char *name = tst->u.ts_enum.names[i];
++      if (name == NULL)
++      break;
++
++      /* Synthesize a new internal COFF symbol for the enum. */
++      csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++      if (csymp == NULL)
++      return FALSE;
++
++      csymp->symbol.name = xstrdup (name);
++      csymp->symbol.flags = BSF_NOT_AT_END;
++      csymp->symbol.section = bfd_com_section_ptr;
++      csymp->native->u.syment.n_sclass = C_MOE;
++      csymp->symbol.udata.p = NULL;
++      csymp->symbol.value = tst->u.ts_enum.vals[i];
++
++      coff_record_symbol (info, csymp);
++    }
++
++  /* Record our endndx field for later fixing. */
++  fixp = (struct coff_fix_stack *) xmalloc (sizeof (struct coff_fix_stack));
++  fixp->native = scsymp->native + 1;  /* points to first AUX */
++  fixp->next = NULL;
++  if (info->fixes == NULL)
++    info->fixes = fixp;
++  else
++    {
++      for (ofp = info->fixes; ofp->next != NULL;)
++      ofp = ofp->next;
++      ofp->next = fixp;
 +    }
 +
++  coff_record_symbol (info, ecsymp);
++  info->flags |= COFF_FL_FIX_ENDNDX;
++
 +  return TRUE;
 +}
 +
-+/* Find a name in the symbol table.  If found, the respective entry in
-+   the symbol vector is zeroed, so after processing all debugging
-+   symbols, only non-debugging symbols will remain. */
-+static asymbol *
-+coff_find_symbol (info, name, isfunction, global)
++/* Emit a non-debugging symbol that came from the input symbol table,
++   and has not been claimed by one of the debugging symbols. */
++static bfd_boolean
++coff_emit_ndebug_sym (info, osymp, localp)
 +     struct coff_write_handle *info;
-+     const char *name;
-+     bfd_boolean isfunction;
-+     bfd_boolean global;
++     asymbol *osymp;
++     bfd_boolean localp;
 +{
-+  asymbol *symp;
-+  long i;
-+  size_t namelen;
++  coff_symbol_type *csymp;
 +
-+  if (global)
-+    {
-+      for (i = 0; i < info->nglobals; i++)
-+      {
-+        symp = info->globals[i];
-+        if (symp == NULL)
-+          continue;
-+        if (strcmp (name, symp->name) == 0
-+            && ((symp->flags & BSF_FUNCTION) != 0) == (isfunction == TRUE))
-+          {
-+            info->globals[i] = NULL;
-+            return symp;
-+          }
-+      }
-+      return NULL;
-+    }
++  /* Create new COFF symbol. */
++  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (csymp == NULL)
++    return FALSE;
 +
-+  if (info->currentfile == NULL)
-+    return NULL;
++  csymp->symbol.name = xstrdup (osymp->name);
++  csymp->symbol.value = osymp->value;
++  csymp->symbol.flags = localp? BSF_LOCAL: BSF_GLOBAL;
++  csymp->symbol.section = osymp->section;
++  csymp->symbol.udata.p = NULL;
++  csymp->native->u.syment.n_sclass = localp? C_STAT: C_EXT;
++  csymp->native->u.syment.n_type = T_NULL;
 +
-+  /* For local symbols, the match optionally stops at a dot in the
-+     symtab symbol's name; this is used by gcc to indicate
-+     function-scope static symbols (e. g. symbol "foo" will become
-+     "foo.1" in function scope). */
-+  namelen = strlen (name);
-+  for (i = 0; i < info->currentfile->nsyms; i++)
-+    {
-+      symp = info->currentfile->syms[i];
-+      if (symp == NULL)
-+      continue;
-+      if (strncmp (name, symp->name, namelen) == 0
-+        && (symp->name[namelen] == '\0' || symp->name[namelen] == '.')
-+        && ((symp->flags & BSF_FUNCTION) != 0) == (isfunction == TRUE))
-+      {
-+        info->currentfile->syms[i] = NULL;
-+        info->currentfile->totsyms--;
-+        return symp;
-+      }
-+    }
-+  return NULL;
++  coff_record_symbol (info, csymp);
++
++  return TRUE;
 +}
++\f
++/* The general routine to write out COFF debugging information.  This
++   synthesizes and accumulates the COFF symbols.  Actual symbol table
++   output is performed later on by the BFD functions.  ABFD is the BFD
++   and DHANDLE is the handle for the debugging information.  symcountp
++   and symppp point to the incoming (parsed) symbol list on entry, and
++   will be updated to point to the new symbol table's values upon
++   exit. */
 +
-+static void
-+coff_record_symbol (info, csymp)
-+     struct coff_write_handle *info;
-+     coff_symbol_type *csymp;
++bfd_boolean
++write_coff_debugging_info (abfd, dhandle, symcountp, symppp)
++     bfd *abfd;
++     PTR dhandle;
++     long *symcountp;
++     asymbol ***symppp;
 +{
-+  struct coff_private_symdata *priv;
++  struct coff_write_handle info;
++  long i, l;
++  asymbol *symp;
++  struct coff_compilation_unit *up;
++  coff_symbol_type *csymp;
 +
-+  info->syms = (asymbol **) xrealloc (info->syms,
-+                                    ++info->nsyms * sizeof (asymbol *));
-+  info->syms[info->nsyms - 1] = (asymbol *)csymp;
++  memset ((void *)&info, 0, sizeof info);
 +
-+  if ((priv = csymp->symbol.udata.p) != NULL)
++  info.abfd = abfd;
++
++  info.pointersize = info.enumsize = 4;
++
++  switch (bfd_get_arch (abfd))
 +    {
-+      if (priv->shash != NULL)
-+      {
-+        struct coff_struct_hash_entry *shash = priv->shash;
-+        shash->fixidxs = (long *)
-+          xrealloc (shash->fixidxs, ++shash->nfixidxs * sizeof (long));
-+        shash->fixidxs[shash->nfixidxs - 1] = info->nsyms - 1;
-+      }
-+      if (priv->ehash != NULL)
-+      {
-+        struct coff_enum_hash_entry *ehash = priv->ehash;
-+        ehash->fixidxs = (long *)
-+          xrealloc (ehash->fixidxs, ++ehash->nfixidxs * sizeof (long));
-+        ehash->fixidxs[ehash->nfixidxs - 1] = info->nsyms - 1;
-+      }
-+      free (priv);
-+      csymp->symbol.udata.p = NULL;
-+    }
++    case bfd_arch_avr:
++      info.flags |= COFF_FL_AVR;
++      if (strcmp (abfd->xvec->name, "coff-ext-avr") == 0)
++      info.flags |= COFF_FL_EXT_AVR;
++      /* Fix the builtin type sizes. */
++      coff_predef_types[0].size = 2;  /* sizeof(int) == 2 */
++      coff_predef_types[4].size = 4;  /* sizeof(double) == 4 */
++      coff_predef_types[6].size = 2;  /* sizeof(unsigned int) == 2 */
++      info.pointersize = info.enumsize = 2;
++      break;
 +
-+  /* If there are any pending endndx fixes, pop the last element from
-+     that stack, and record the current symbol for fixing.  We need to
-+     do this here since we need to record our current csymp->native
-+     (where that csymp is completely unrelated to whatever symbol was
-+     previously generated that requested the fixup).  The stack of
-+     pending fixes is required since several endndx fixes could be
-+     nested, e. g. the start of a function has a pending fix that
-+     needs to point to the first symbol after the function, but there
-+     could be an anonymous struct definition inside that function's
-+     local variables where the endndx needs to point after the last
-+     symbol of this struct.  Also, structs and unions could be nested.
++    default:
++      ;
++    }
 +
-+     Each call to coff_record_symbol() can fix at most one endndx
-+     (even if more are pending in the stack), but that's OK.
++  coff_copy_symbols(&info, *symcountp, *symppp);
 +
-+     Note that bfd/coffgen.c converts that csymp->native into a
-+     symtable slot number after coff_renumber_symbols() has been
-+     run. */
-+  if (info->flags & COFF_FL_FIX_ENDNDX)
++  if (info.textsect == NULL)
 +    {
-+      struct coff_fix_stack *fsp, *ofsp;
-+      union internal_auxent *aux;
++      fprintf (stderr, _("Warning: no \"text\" section found in output file\n"));
++      info.textsect = bfd_abs_section_ptr;
++    }
++  if (info.datasect == NULL)
++    {
++      fprintf (stderr, _("Warning: no \"data\" section found in output file\n"));
++      info.datasect = bfd_abs_section_ptr;
++    }
 +
-+      assert (info->fixes != NULL);
++  if (! bfd_hash_table_init (&info.types.root, coff_name_type_newfunc,
++                           sizeof(struct coff_name_type_hash_entry)))
++    return FALSE;
 +
-+      fsp = info->fixes;
-+      ofsp = NULL;
-+      while (fsp->next != NULL)
-+      {
-+        ofsp = fsp;
-+        fsp = fsp->next;
-+      }
-+      if (ofsp == NULL)
-+      info->fixes = NULL;
-+      else
-+      ofsp->next = NULL;
++  if (! bfd_hash_table_init (&info.structs.root, coff_struct_newfunc,
++                           sizeof(struct coff_struct_hash_entry)))
++    return FALSE;
 +
-+      aux = &(fsp->native->u.auxent);
-+      fsp->native->fix_end = 1;
-+      aux->x_sym.x_fcnary.x_fcn.x_endndx.p = csymp->native;
-+      free (fsp);
++  if (! bfd_hash_table_init (&info.enums.root, coff_enum_newfunc,
++                           sizeof(struct coff_enum_hash_entry)))
++    return FALSE;
 +
-+      info->flags &= ~COFF_FL_FIX_ENDNDX;
-+    }
-+}
++  if (! debug_write (dhandle, &coff_fns, (PTR) &info))
++    return FALSE;
 +
-+/* Fixup AVR COFF register handling: they don't only mention the
-+   starting register number, but all registers, each within one byte
-+   of the value.  Unused register positions are filled up with
-+   0xff. */
-+static symvalue
-+coff_fixup_avr_register (val, size)
-+     symvalue val;
-+     int size;
-+{
-+  union
-+  {
-+    unsigned char c[4];
-+    symvalue v;
-+  } u;
++  /* If there is an old compilation unit that has got any local
++     non-debugging symbols left over, send them out now. */
++  if (info.currentfile != NULL && info.currentfile->totsyms != 0)
++    for (i = 0; i < info.currentfile->nsyms; i++)
++      {
++      up = info.currentfile;
 +
-+  u.c[1] = u.c[2] = u.c[3] = 0xff;
-+  u.c[0] = val;
-+  if (size > 8)
-+    u.c[1] = val + 1;
-+  if (size > 16)
-+    {
-+      u.c[2] = val + 2;
-+      u.c[3] = val + 3;
-+    }
++      if (up->syms[i] != NULL)
++        {
++          coff_emit_ndebug_sym (&info, up->syms[i], TRUE);
++          up->syms[i] = NULL;
++          up->totsyms--;
++        }
++      }
++
++  /* See whether there are any non-debugging symbols left from the
++     input symbol table.  First look at all local symbols which must
++     be from entire compilation units we didn't see yet in the
++     debugging information, because anything else has already been
++     handled at the end of each compilation unit (like in the loop
++     immediately above).  Any compilation unit that has already been
++     processed that way is supposed to have its "totsyms" counted down
++     to 0 now, so we can skip them.
 +
-+  return u.v;
-+}
++     Finally, put out all remaining global non-debugging symbols. */
++  for (l = 0; l < info.nunits; l++)
++    {
++      const char *bn;
 +
-+/* Initialize an entry in the hash tables.  */
++      up = info.units + l;
++      if (up->totsyms == 0)
++      continue;
 +
-+static struct bfd_hash_entry *
-+coff_name_type_newfunc (entry, table, string)
-+     struct bfd_hash_entry *entry;
-+     struct bfd_hash_table *table;
-+     const char *string;
-+{
-+  struct coff_name_type_hash_entry *ret =
-+    (struct coff_name_type_hash_entry *) entry;
++      /* Create COFF symbol for this compilation unit. */
++      csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info.abfd, 0, 0);
++      if (csymp == NULL)
++      return FALSE;
 +
-+  /* Allocate the structure if it has not already been allocated by a
-+     subclass.  */
-+  if (ret == NULL)
-+    ret = ((struct coff_name_type_hash_entry *)
-+         bfd_hash_allocate (table, sizeof *ret));
-+  if (ret == NULL)
-+    return NULL;
++      bn = bu_basename (up->fname);
 +
-+  /* Call the allocation method of the superclass.  */
-+  ret = ((struct coff_name_type_hash_entry *)
-+       bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
-+  if (ret)
-+    {
-+      /* Set local fields.  */
-+      ret->types = NULL;
-+      ret->emitted = FALSE;
-+    }
++      if (bfd_coff_long_filenames (info.abfd))
++      csymp->symbol.name = up->fname;
++      else
++      csymp->symbol.name = bn;
 +
-+  return (struct bfd_hash_entry *) ret;
-+}
++      csymp->symbol.value = 0;
++      csymp->symbol.udata.p = NULL;
++      csymp->native->u.syment.n_sclass = C_FILE;
++      csymp->native->u.syment.n_numaux = 1; /* force filename into aux entry */
++      coff_record_symbol (&info, csymp);
 +
-+static struct bfd_hash_entry *
-+coff_struct_newfunc (entry, table, string)
-+     struct bfd_hash_entry *entry;
-+     struct bfd_hash_table *table;
-+     const char *string;
-+{
-+  struct coff_struct_hash_entry *ret =
-+    (struct coff_struct_hash_entry *) entry;
++      for (i = 0; i < up->nsyms; i++)
++      {
++        symp = up->syms[i];
++        if (symp == NULL)
++          continue;
 +
-+  /* Allocate the structure if it has not already been allocated by a
-+     subclass.  */
-+  if (ret == NULL)
-+    ret = ((struct coff_struct_hash_entry *)
-+         bfd_hash_allocate (table, sizeof *ret));
-+  if (ret == NULL)
-+    return NULL;
++        coff_emit_ndebug_sym (&info, symp, TRUE);
++      }
++    }
 +
-+  /* Call the allocation method of the superclass.  */
-+  ret = ((struct coff_struct_hash_entry *)
-+       bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
-+  if (ret)
++  for (i = 0; i < info.nglobals; i++)
 +    {
-+      /* Set local fields.  */
-+      ret->types = NULL;
-+      ret->emitted = FALSE;
-+      ret->fixidxs = NULL;
-+      ret->nfixidxs = 0;
-+      ret->native = NULL;
-+    }
++      symp = info.globals[i];
++      if (symp == NULL)
++      continue;
 +
-+  return (struct bfd_hash_entry *) ret;
-+}
++      coff_emit_ndebug_sym (&info, symp, FALSE);
++    }
 +
-+static struct bfd_hash_entry *
-+coff_enum_newfunc (entry, table, string)
-+     struct bfd_hash_entry *entry;
-+     struct bfd_hash_table *table;
-+     const char *string;
-+{
-+  struct coff_enum_hash_entry *ret =
-+    (struct coff_enum_hash_entry *) entry;
++  /* Fixup the AUX entries for the section symbols we have emitted
++     earlier (so they are guaranteed to be at the beginning of the
++     symbol table).  In particular, the line number count (which we
++     only have for the text section) is known right now. */
++  for (i = 0; i < info.nsecsyms; i++)
++    {
++      union internal_auxent *aux;
 +
-+  /* Allocate the structure if it has not already been allocated by a
-+     subclass.  */
-+  if (ret == NULL)
-+    ret = ((struct coff_enum_hash_entry *)
-+         bfd_hash_allocate (table, sizeof *ret));
-+  if (ret == NULL)
-+    return NULL;
++      csymp = info.secsyms[i];
 +
-+  /* Call the allocation method of the superclass.  */
-+  ret = ((struct coff_enum_hash_entry *)
-+       bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
-+  if (ret)
-+    {
-+      /* Set local fields.  */
-+      ret->types = NULL;
-+      ret->emitted = FALSE;
-+      ret->fixidxs = NULL;
-+      ret->nfixidxs = 0;
-+      ret->native = NULL;
++      aux = &((csymp->native + 1)->u.auxent);
++      aux->x_scn.x_scnlen = csymp->symbol.section->output_section->rawsize;
++      aux->x_scn.x_nreloc = csymp->symbol.section->reloc_count;
++      if (csymp->symbol.section == info.textsect)
++      aux->x_scn.x_nlinno = info.totlnos;
 +    }
++  free (info.secsyms);
 +
-+  return (struct bfd_hash_entry *) ret;
-+}
++  coff_name_type_hash_traverse (&info.types, coff_free_type_info, NULL);
++  bfd_hash_table_free (&info.types.root);
 +
-+/* Look up an entry in the hash tables.  */
++  coff_struct_hash_traverse (&info.structs, coff_free_struct_info, NULL);
++  bfd_hash_table_free (&info.structs.root);
 +
-+#define coff_name_type_hash_lookup(table, string, create, copy) \
-+  ((struct coff_name_type_hash_entry *) \
-+   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
++  coff_enum_hash_traverse (&info.enums, coff_free_enum_info, NULL);
++  bfd_hash_table_free (&info.enums.root);
 +
-+/* Traverse the hash table.  */
++  /* FIXME: free all the other stuff remembered in "info". */
 +
-+#define coff_name_type_hash_traverse(table, func, info)                       \
-+  (bfd_hash_traverse                                                  \
-+   (&(table)->root,                                                   \
-+    (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
-+    (info)))
++  free (*symppp);
 +
-+#define coff_struct_hash_lookup(table, string, create, copy) \
-+  ((struct coff_struct_hash_entry *) \
-+   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
++  *symcountp = info.nsyms;
++  *symppp = (asymbol **)info.syms;
 +
-+/* Traverse the hash table.  */
++  return TRUE;
++}
 +
-+#define coff_struct_hash_traverse(table, func, info)                  \
-+  (bfd_hash_traverse                                                  \
-+   (&(table)->root,                                                   \
-+    (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
-+    (info)))
++/* Start writing out information for a compilation unit.  */
 +
-+#define coff_enum_hash_lookup(table, string, create, copy) \
-+  ((struct coff_enum_hash_entry *) \
-+   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
++static bfd_boolean
++coff_start_compilation_unit (p, filename)
++     PTR p;
++     const char *filename;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  long i;
++  const char *bn;
++  bfd_boolean found;
++  coff_symbol_type *csymp;
 +
-+/* Traverse the hash table.  */
++#if COFF_DEBUG
++  printf ("coff_start_compilation_unit(%s)\n", filename);
++#endif
 +
-+#define coff_enum_hash_traverse(table, func, info)                    \
-+  (bfd_hash_traverse                                                  \
-+   (&(table)->root,                                                   \
-+    (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
-+    (info)))
++  /* If there is an old compilation unit that has got any local
++     non-debugging symbols left over, send them out now. */
++  if (info->currentfile != NULL && info->currentfile->totsyms != 0)
++    for (i = 0; i < info->currentfile->nsyms; i++)
++      {
++      struct coff_compilation_unit *up = info->currentfile;
 +
-+#define coff_push_type(kind) \
-+  tst = (struct coff_type_stack *) xmalloc (sizeof (struct coff_type_stack)); \
-+  memset (tst, 0, sizeof (*tst)); \
-+  tst->next = info->tstack; \
-+  tst->tsk = kind; \
-+  info->tstack = tst
++      if (up->syms[i] != NULL)
++        {
++          coff_emit_ndebug_sym (info, up->syms[i], TRUE);
++          up->syms[i] = NULL;
++          up->totsyms--;
++        }
++      }
 +
-+#define coff_pop_type() \
-+  tst = info->tstack; \
-+  if (tst == NULL) { \
-+    fprintf (stderr, _("empty type stack in coff_pop_type()\n")); \
-+    return FALSE; \
-+  } \
-+  info->tstack = tst->next; \
-+  tst->next = NULL
++  /* symtab (and thus COFF debugging) symbols can only transfer the
++     basename of the file, so strip the dirname */
++  bn = bu_basename (filename);
 +
-+#define coff_complain_unsupp(s) \
-+  fprintf (stderr, _("%s type not supported in %s\n"), \
-+         s, info->abfd->xvec->name); \
-+  return FALSE
++  for (i = 0, found = FALSE; i < info->nunits; i++)
++    {
++      if (strcmp (info->units[i].fname, bn) == 0)
++      {
++        info->currentfile = info->units + i;
++        found = TRUE;
++        break;
++      }
++    }
++  if (!found)
++    {
++      fprintf(stderr,
++            _("Warning: file %s not found in symbol table, ignoring\n"),
++            filename);
++      info->currentfile = NULL;
++      return TRUE;
++    }
 +
-+/* These function is called via the hash traverse routine when freeing
-+   a hash table (at the end of a translation unit). */
-+static bfd_boolean
-+coff_free_type_info (h, p)
-+     struct coff_name_type_hash_entry *h;
-+     PTR p ATTRIBUTE_UNUSED;
-+{
-+  struct coff_type_stack *tst, *otst;
++  /* Synthesize a new internal COFF symbol. */
++  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (csymp == NULL)
++    return FALSE;
++
++  /* Note that coff_fix_symbol_name() [coffgen.c] will fix this for
++     us: the symbol name will be replaced by ".file", and the filename
++     will be moved to the aux entries.  We use the long name obtained
++     from the debugging information (that includes the full path) if
++     our COFF format supports long filenames, otherwise we only use
++     the basename of the file. */
++  if (bfd_coff_long_filenames (info->abfd))
++    csymp->symbol.name = filename;
++  else
++    csymp->symbol.name = bn;
++  csymp->symbol.value = 0;
++  csymp->symbol.udata.p = NULL;
++  csymp->native->u.syment.n_sclass = C_FILE;
++  csymp->native->u.syment.n_numaux = 1;       /* force filename into aux entry */
++  coff_record_symbol (info, csymp);
 +
-+  for (tst = h->types; tst != NULL;)
-+    {
-+      otst = tst;
-+      tst = tst->next;
-+      free (otst);
-+    }
 +  return TRUE;
 +}
 +
++/* Start writing out information for a particular source file.  */
++
 +static bfd_boolean
-+coff_free_struct_info (h, p)
-+     struct coff_struct_hash_entry *h;
++coff_start_source (p, filename)
 +     PTR p ATTRIBUTE_UNUSED;
++     const char *filename ATTRIBUTE_UNUSED;
 +{
-+  struct coff_type_stack *tst, *otst, *xtst, *xotst;
-+  struct coff_struct_fields *fp;
-+  long i;
 +
-+  for (tst = h->types; tst != NULL;)
-+    {
-+      otst = tst;
-+      if (tst->u.ts_struct.tagismalloced)
-+      free (tst->u.ts_struct.tag.malloctag);
-+      for (i = 0, fp = tst->u.ts_struct.fields;
-+         i < tst->u.ts_struct.nfields;
-+         i++, fp++)
-+      {
-+        xtst = fp->types;
-+        while (xtst != NULL)
-+          {
-+            xotst = xtst->next;
-+            free (xtst);
-+            xtst = xotst;
-+          }
-+      }
-+      free (tst->u.ts_struct.fields);
-+      tst = tst->next;
-+      free (otst);
-+    }
++#if COFF_DEBUG
++  printf ("coff_start_source(%s)\n", filename);
++#endif
++
++  /* COFF cannot handle include filenames. */
++
 +  return TRUE;
 +}
 +
++/* Push an empty type.  This shouldn't normally happen.  */
++
 +static bfd_boolean
-+coff_free_enum_info (h, p)
-+     struct coff_enum_hash_entry *h;
-+     PTR p ATTRIBUTE_UNUSED;
++coff_empty_type (p)
++     PTR p;
 +{
-+  struct coff_type_stack *tst, *otst;
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst;
++
++#if COFF_DEBUG
++  printf ("coff_empty_type()\n");
++#endif
++
++  coff_push_type (TS_EMPTY);
 +
-+  for (tst = h->types; tst != NULL;)
-+    {
-+      otst = tst;
-+      if (tst->u.ts_enum.tagismalloced)
-+      free (tst->u.ts_enum.tag.malloctag);
-+      tst = tst->next;
-+      free (otst);
-+    }
 +  return TRUE;
 +}
 +
-+static unsigned int
-+coff_get_fundamental_type (info, tst)
-+     struct coff_write_handle *info ATTRIBUTE_UNUSED;
-+     struct coff_type_stack *tst;
++/* Push a void type.  */
++
++static bfd_boolean
++coff_void_type (p)
++     PTR p;
 +{
-+  size_t i;
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst;
 +
-+  /* See if one of our predefined types will fit. */
-+  if (tst->tsk == TS_INT)
-+    {
-+      for (i = 0;
-+         i < sizeof coff_predef_types / sizeof (struct coff_predef_type);
-+         i++)
-+      {
-+        if (coff_predef_types[i].kind == TS_INT
-+            && coff_predef_types[i].size == tst->u.ts_int.size
-+            && coff_predef_types[i].isunsigned == tst->u.ts_int.isunsigned)
-+          return coff_predef_types[i].slot;
-+      }
-+      fprintf (stderr,
-+             _("%ssigned %d-bit integer type not available in COFF\n"),
-+             tst->u.ts_int.isunsigned? "un": "", tst->u.ts_int.size * 8);
-+    }
-+  else
-+    {
-+      for (i = 0;
-+         i < sizeof coff_predef_types / sizeof (struct coff_predef_type);
-+         i++)
-+      {
-+        if (coff_predef_types[i].kind == TS_FLOAT
-+            && coff_predef_types[i].size == tst->u.ts_float.size)
-+          return coff_predef_types[i].slot;
-+      }
-+      fprintf (stderr, _("%d-bit float type not available in COFF\n"),
-+             tst->u.ts_float.size * 8);
-+    }
++#if COFF_DEBUG
++  printf ("coff_void_type()\n");
++#endif
 +
-+  return T_NULL;
++  coff_push_type (TS_VOID);
++
++  return TRUE;
 +}
 +
++/* Push an integer type.  */
++
 +static bfd_boolean
-+coff_make_typed_symbol (info, csympp, stopat)
-+     struct coff_write_handle *info;
-+     coff_symbol_type **csympp;
-+     enum ts_kind stopat;
++coff_int_type (p, size, unsignedp)
++     PTR p;
++     unsigned int size;
++     bfd_boolean unsignedp;
 +{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
 +  struct coff_type_stack *tst;
-+  union internal_auxent *aux;
-+  struct coff_struct_hash_entry *shash;
-+  struct coff_enum_hash_entry *ehash;
-+  struct coff_private_symdata *priv;
-+  unsigned int type, numaux, arydim, size, i, nele, nderived;
-+  const char *name;
-+  bfd_boolean oldavrcoff = (info->flags & (COFF_FL_AVR | COFF_FL_EXT_AVR))
-+    == COFF_FL_AVR;
-+
-+  /* Synthesize a new internal COFF symbol. */
-+  *csympp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+  if (*csympp == NULL)
-+    return FALSE;
 +
-+  priv = (struct coff_private_symdata *) xmalloc (sizeof *priv);
-+  memset (priv, 0, sizeof *priv);
++#if COFF_DEBUG
++  printf ("coff_int_type(%d, %d)\n", size, unsignedp);
++#endif
 +
-+  type = arydim = size = nderived = 0;
++  coff_push_type (TS_INT);
++  tst->u.ts_int.size = size;
++  tst->u.ts_int.isunsigned = unsignedp;
 +
-+  aux = &(((*csympp)->native + 1)->u.auxent);
++  return TRUE;
++}
 +
-+  /* Now, walk the type stack, and see how we could convert the info
-+     we've got to what COFF understands. */
-+  for (;;)
-+    {
-+      if (info->tstack == NULL)
-+      break;
++/* Push a floating point type.  */
 +
-+      /* If we have been advised to not pop the entire stack, stop
-+       here. */
-+      if (info->tstack->tsk == stopat && info->tstack->next == NULL)
-+      break;
++static bfd_boolean
++coff_float_type (p, size)
++     PTR p;
++     unsigned int size;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst;
 +
-+      coff_pop_type ();
++#if COFF_DEBUG
++  printf ("coff_float_type(%d)\n", size);
++#endif
 +
-+      switch (tst->tsk)
-+      {
-+      case TS_NONE:
-+        /* cannot happen */
-+        break;
++  coff_push_type (TS_FLOAT);
++  tst->u.ts_float.size = size;
 +
-+      case TS_EMPTY:
-+        if (info->tstack != NULL && info->tstack->tsk != stopat)
-+          fprintf (stderr, _("empty type not last on type stack\n"));
-+        /* type |= T_NULL; */
-+        break;
++  return TRUE;
++}
 +
-+      case TS_VOID:
-+        if (info->tstack != NULL && info->tstack->tsk != stopat)
-+          fprintf (stderr, _("void type not last on type stack\n"));
-+        type |= T_VOID;
-+        break;
++/* Push a complex type.  */
 +
-+      case TS_INT:
-+        if (info->tstack != NULL && info->tstack->tsk != stopat)
-+          fprintf (stderr, _("int type not last on type stack\n"));
-+        type |= coff_get_fundamental_type (info, tst);
-+        if (size == 0)
-+          size = tst->u.ts_int.size;
-+        break;
++static bfd_boolean
++coff_complex_type (p, size)
++     PTR p;
++     unsigned int size ATTRIBUTE_UNUSED;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst;
 +
-+      case TS_FLOAT:
-+        if (info->tstack != NULL && info->tstack->tsk != stopat)
-+          fprintf (stderr, _("float type not last on type stack\n"));
-+        type |= coff_get_fundamental_type (info, tst);
-+        if (size == 0)
-+          size = tst->u.ts_float.size;
-+        break;
++#if COFF_DEBUG
++  printf ("coff_complex_type(%d)\n", size);
++#endif
 +
-+      case TS_POINTER:
-+        nderived++;
-+        type = ((type & ~N_BTMASK) << N_TSHIFT) | (DT_PTR << N_BTSHFT);
-+        size = info->pointersize;
-+        break;
++  coff_push_type (TS_COMPLEX);
 +
-+      case TS_FUNC:
-+        nderived++;
-+        type = ((type & ~N_BTMASK) << N_TSHIFT) | (DT_FCN << N_BTSHFT);
-+        /* AUX entry for DT_FCN will be filled in elsewhere. */
-+        break;
++  return TRUE;
++}
 +
-+      case TS_ARRAY:
-+        /* We need to limit arydim so the assignment below won't
-+           overwrite random locations. */
-+        if (arydim >= DIMNUM)
-+          {
-+            fprintf (stderr,
-+                     _("More than %d array dimensions, result is invalid.\n"),
-+                     DIMNUM);
-+            arydim = DIMNUM - 1;
-+          }
-+        nderived++;
-+        type = ((type & ~N_BTMASK) << N_TSHIFT) | (DT_ARY << N_BTSHFT);
-+        aux->x_sym.x_fcnary.x_ary.x_dimen[arydim++] =
-+          tst->u.ts_array.high - tst->u.ts_array.low + 1;
++/* Push a bfd_boolean type. */
 +
-+        break;
++static bfd_boolean
++coff_bool_type (p, size)
++     PTR p;
++     unsigned int size;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst;
 +
-+      case TS_COMPLEX:
-+        coff_complain_unsupp (_("complex"));
++#if COFF_DEBUG
++  printf ("coff_bool_type(%d)\n", size);
++#endif
 +
-+      case TS_ENUM:
-+        type |= T_ENUM;
-+        if (size == 0)
-+          size = info->enumsize;
++  coff_push_type (TS_INT);
++  tst->u.ts_int.size = size;
++  tst->u.ts_int.isunsigned = TRUE;
 +
-+        if (tst->u.ts_enum.ehash != NULL)
-+          {
-+            /* enum tag will be fixed later. */
-+            priv->ehash = tst->u.ts_enum.ehash;
-+            break;
-+          }
-+        if (tst->u.ts_enum.tagismalloced)
-+          name = tst->u.ts_enum.tag.malloctag;
-+        else
-+          name = tst->u.ts_enum.tag.fixtag;
-+        ehash = coff_enum_hash_lookup (&info->enums, name,
-+                                       TRUE, tst->u.ts_enum.tagismalloced);
-+        if (ehash == NULL)
-+          return FALSE;
-+        if (!ehash->emitted)
-+          {
-+            if (ehash->types == NULL)
-+              {
-+                ehash->types = (struct coff_type_stack *)
-+                  xmalloc (sizeof (struct coff_type_stack));
-+                memcpy (ehash->types, tst, sizeof (struct coff_type_stack));
-+              }
-+            ehash->emitted = TRUE;
-+            coff_emit_enum (info, tst, ehash);
-+            if (ehash->nfixidxs != 0)
-+              {
-+                coff_symbol_type *symp;
-+                unsigned i;
++  return TRUE;
++}
 +
-+                for (i = 0; i < ehash->nfixidxs; i++)
-+                  {
-+                    combined_entry_type *np;
++/* Push an enum type.  */
 +
-+                    symp = (coff_symbol_type *) info->syms[ehash->fixidxs[i]];
-+                    symp->native->u.syment.n_type &= ~N_BTMASK;
-+                    symp->native->u.syment.n_type |= T_ENUM;
++static bfd_boolean
++coff_enum_type (p, tag, names, vals)
++     PTR p;
++     const char *tag;
++     const char **names;
++     bfd_signed_vma *vals;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst;
++  char buf[20];
 +
-+                    if (oldavrcoff)
-+                      continue;
++#if COFF_DEBUG
++  int idx;
++  printf ("coff_enum_type(%s [", tag);
++  for (idx = 0; names[idx] != NULL; idx++)
++    printf ("%s -> %d, ", names[idx], (int)vals[idx]);
++  printf ("])\n");
++#endif
 +
-+                    np = symp->native + 1;
-+                    np->fix_tag = 1;
-+                    np->u.auxent.x_sym.x_tagndx.p = ehash->native;
-+                    if (np->u.auxent.x_sym.x_misc.x_fsize == 0)
-+                      np->u.auxent.x_sym.x_misc.x_lnsz.x_size = size;
-+                  }
++  coff_push_type (TS_ENUM);
 +
-+                free (ehash->fixidxs);
-+                ehash->nfixidxs = 0;
-+              }
-+          }
-+        if (!oldavrcoff)
-+          {
-+            ((*csympp)->native + 1)->fix_tag = 1;
-+            aux->x_sym.x_tagndx.p = ehash->native;
-+            if (aux->x_sym.x_misc.x_fsize == 0)
-+              aux->x_sym.x_misc.x_lnsz.x_size = size;
-+          }
-+        break;
++  if (tag == NULL)
++    {
++      sprintf(buf, ".%dfake", info->nenums++);
++      tst->u.ts_enum.tag.malloctag = xstrdup (buf);
++      tst->u.ts_enum.tagismalloced = TRUE;
++    }
++  else
++    tst->u.ts_enum.tag.fixtag = tag;
++  tst->u.ts_enum.names = names;
++  tst->u.ts_enum.vals = vals;
 +
-+      case TS_STRUCT:
-+        if (tst->u.ts_struct.isstruct)
-+          type |= T_STRUCT;
-+        else
-+          type |= T_UNION;
-+        if (size == 0)
-+          size = tst->u.ts_struct.size;
++  return TRUE;
++}
 +
-+        if (tst->u.ts_struct.shash != NULL)
-+          {
-+            /* struct tag will be fixed later. */
-+            priv->shash = tst->u.ts_struct.shash;
-+            break;
-+          }
-+        if (tst->u.ts_struct.tagismalloced)
-+          name = tst->u.ts_struct.tag.malloctag;
-+        else
-+          name = tst->u.ts_struct.tag.fixtag;
-+        shash = coff_struct_hash_lookup (&info->structs, name,
-+                                         TRUE, tst->u.ts_struct.tagismalloced);
-+        if (shash == NULL)
-+          return FALSE;
-+        if (!shash->emitted)
-+          {
-+            if (shash->types == NULL)
-+              {
-+                shash->types = (struct coff_type_stack *)
-+                  xmalloc (sizeof (struct coff_type_stack));
-+                memcpy (shash->types, tst, sizeof (struct coff_type_stack));
-+              }
-+            shash->emitted = TRUE;
-+            coff_emit_struct (info, tst, shash);
-+            if (shash->nfixidxs != 0)
-+              {
-+                coff_symbol_type *symp;
-+                unsigned i;
++/* Push a pointer type.  */
 +
-+                for (i = 0; i < shash->nfixidxs; i++)
-+                  {
-+                    combined_entry_type *np;
++static bfd_boolean
++coff_pointer_type (p)
++     PTR p;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst;
 +
-+                    symp = (coff_symbol_type *) info->syms[shash->fixidxs[i]];
-+                    symp->native->u.syment.n_type &= ~N_BTMASK;
-+                    if (tst->u.ts_struct.isstruct)
-+                      symp->native->u.syment.n_type |= T_STRUCT;
-+                    else
-+                      symp->native->u.syment.n_type |= T_UNION;
++#if COFF_DEBUG
++  printf ("coff_pointer_type()\n");
++#endif
 +
-+                    if (oldavrcoff)
-+                      continue;
++  coff_push_type (TS_POINTER);
 +
-+                    np = symp->native + 1;
-+                    np->fix_tag = 1;
-+                    np->u.auxent.x_sym.x_tagndx.p = shash->native;
-+                    if (np->u.auxent.x_sym.x_misc.x_fsize == 0)
-+                      np->u.auxent.x_sym.x_misc.x_lnsz.x_size = size;
-+                  }
++  return TRUE;
++}
 +
-+                free (shash->fixidxs);
-+                shash->nfixidxs = 0;
-+              }
-+          }
-+        if (!oldavrcoff)
-+          {
-+            ((*csympp)->native + 1)->fix_tag = 1;
-+            aux->x_sym.x_tagndx.p = shash->native;
-+            if (aux->x_sym.x_misc.x_fsize == 0)
-+              aux->x_sym.x_misc.x_lnsz.x_size = size;
-+          }
-+        break;
-+      }
-+      free (tst);
-+    }
++/* Push a function type.  */
 +
-+  if (nderived > 6)
-+    fprintf (stderr,
-+           _("More than 6 derived type specifiers, result is invalid.\n"));
++static bfd_boolean
++coff_function_type (p, argcount, varargs)
++     PTR p;
++     int argcount;
++     bfd_boolean varargs ATTRIBUTE_UNUSED;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst;
 +
-+  /* Our type computation so far used the reverse order for derived
-+     type specifiers.  Fix this here if there was more than one
-+     derived type specifier. */
-+  if (nderived > 1)
-+    {
-+      unsigned int nty, bty;
-+      bty = type & N_BTMASK;
-+      type = type >> N_BTSHFT;
-+      nty = 0;
-+      while (nderived-- > 0)
-+      {
-+        nty = (nty << N_TSHIFT) | (type & (N_TMASK >> N_BTSHFT));
-+        type >>= N_TSHIFT;
-+      }
-+      type = (nty << N_BTSHFT) | bty;
-+    }
++#if COFF_DEBUG
++  printf ("coff_function_type(%d, %d)\n", argcount, varargs);
++#endif
 +
-+  if (ISARY (type))
++  coff_push_type (TS_FUNC);
++
++  /* FIXME should properly discard function arguments */
++  if (argcount > -1)
 +    {
-+      /* Compute size of entire array. */
-+      for (i = 0, nele = 1; i < arydim; i++)
-+      nele *= aux->x_sym.x_fcnary.x_ary.x_dimen[i];
-+      aux->x_sym.x_misc.x_lnsz.x_size = size * nele;
++      fprintf (stderr,
++             _("coff_function_type() called with positive argcount\n"));
++      return FALSE;
 +    }
 +
-+  numaux = 0;
-+  if (ISARY (type) || ISFCN (type))
-+    numaux++;
-+  if ((BTYPE (type) == T_STRUCT || BTYPE (type) == T_UNION
-+       || BTYPE (type) == T_ENUM)
-+      && !oldavrcoff)
-+    numaux++;
-+  /* Only AVR COFF uses multiple AUX entries. */
-+  if (numaux > 1 && (info->flags & COFF_FL_AVR) == 0)
-+    numaux = 1;
++  return TRUE;
++}
 +
-+  priv->size = size;
-+  (*csympp)->symbol.udata.p = priv;
-+  (*csympp)->native->u.syment.n_type = type;
-+  (*csympp)->native->u.syment.n_numaux = numaux;
++/* Push a reference type.  */
++
++static bfd_boolean
++coff_reference_type (p)
++     PTR p;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++
++#if COFF_DEBUG
++  printf ("coff_reference_type()\n");
++#endif
 +
-+  /* If the fundamental type comes out as T_NULL, this means we don't
-+     have any type information.  Just don't emit any aux entries in
-+     that case, and drop any derived type information as well. */
-+  if (BTYPE (type) == T_NULL)
-+    {
-+      printf ("coff_make_typed_symbol() -> T_NULL\n");
-+      //(*csympp)->native->u.syment.n_type = T_NULL;
-+      (*csympp)->native->u.syment.n_numaux = 0;
-+    }
++  coff_complain_unsupp (_("reference"));
 +
 +  return TRUE;
 +}
 +
-+static bfd_boolean coff_emit_struct (info, tst, shash)
-+     struct coff_write_handle *info;
-+     struct coff_type_stack *tst;
-+     struct coff_struct_hash_entry *shash;
-+{
-+  coff_symbol_type *csymp, *scsymp, *ecsymp;
-+  union internal_auxent *aux;
-+  struct coff_fix_stack *fixp, *ofp;
-+  bfd_boolean isstruct = tst->u.ts_struct.isstruct;
-+  bfd_boolean isbitfield = FALSE;
-+  struct coff_type_stack *savedtst;
-+  struct coff_struct_fields *fp;
-+  unsigned short sclass;
-+  long i;
++/* Push a range type.  */
 +
-+  if ((info->flags & (COFF_FL_AVR | COFF_FL_EXT_AVR)) ==
-+      COFF_FL_AVR)
-+    /* old AVR COFF doesn't support struct debugging */
-+    return TRUE;
++static bfd_boolean
++coff_range_type (p, low, high)
++     PTR p;
++     bfd_signed_vma low ATTRIBUTE_UNUSED;
++     bfd_signed_vma high ATTRIBUTE_UNUSED;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
 +
-+  /* Synthesize a new internal COFF symbol for the struct/union. */
-+  scsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+  if (scsymp == NULL)
-+    return FALSE;
++#if COFF_DEBUG
++  printf ("coff_range_type([%d..%d)\n", (int)low, (int)high);
++#endif
 +
-+  if (tst->u.ts_struct.tagismalloced)
-+    scsymp->symbol.name = xstrdup (tst->u.ts_struct.tag.malloctag);
-+  else
-+    scsymp->symbol.name = tst->u.ts_struct.tag.fixtag;
-+  scsymp->symbol.flags = BSF_NOT_AT_END;
-+  scsymp->symbol.section = bfd_und_section_ptr;
-+  scsymp->native->u.syment.n_sclass = isstruct? C_STRTAG: C_UNTAG;
-+  scsymp->native->u.syment.n_type = isstruct? T_STRUCT: T_UNION;
-+  scsymp->native->u.syment.n_numaux = 1;
-+  scsymp->symbol.udata.p = NULL;
-+  scsymp->symbol.value = 0;
++  coff_complain_unsupp (_("range"));
 +
-+  shash->native = scsymp->native;
++  return TRUE;
++}
 +
-+  /* Synthesize a new internal COFF symbol for the end of struct/union. */
-+  ecsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+  if (ecsymp == NULL)
-+    return FALSE;
++/* Push an array type.  */
 +
-+  ecsymp->symbol.name = ".eos";
-+  ecsymp->symbol.flags = BSF_NOT_AT_END;
-+  /* We need to use the com section here since bfd/coffgen.c
-+     translates this into an N_UNDEF one without clobbering the
-+     value. */
-+  ecsymp->symbol.section = bfd_com_section_ptr;
-+  ecsymp->native->u.syment.n_sclass = C_EOS;
-+  ecsymp->symbol.udata.p = NULL;
-+  ecsymp->symbol.value = tst->u.ts_struct.size;
-+  ecsymp->native->u.syment.n_numaux = 1;
-+  (ecsymp->native + 1)->fix_tag = 1;
-+  aux = &((ecsymp->native + 1)->u.auxent);
-+  aux->x_sym.x_tagndx.p = scsymp->native;
-+  aux->x_sym.x_misc.x_lnsz.x_size = tst->u.ts_struct.size;
++static bfd_boolean
++coff_array_type (p, low, high, stringp)
++     PTR p;
++     bfd_signed_vma low;
++     bfd_signed_vma high;
++     bfd_boolean stringp;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst;
 +
-+  coff_record_symbol (info, scsymp);
++#if COFF_DEBUG
++  printf ("coff_array_type([%d..%d], %d)\n",
++        (int)low, (int)high, stringp);
++#endif
 +
-+  savedtst = info->tstack;
++  /* Pop the range type, but ignore it.  COFF doesn't use it. */
++  coff_pop_type ();
 +
-+  if (isstruct)
++  /* FIXME  What to do here? */
++  if (stringp)
 +    {
-+      /* First, make a quick walk along all the fields, and figure out
-+       * whether we've got a genuine struct or a bitfield struct. */
-+      for (i = 0, fp = tst->u.ts_struct.fields;
-+         i < tst->u.ts_struct.nfields;
-+         i++, fp++)
-+      if (fp->bitsize % 8 != 0)
-+        {
-+          isbitfield = TRUE;
-+          break;
-+        }
++      fprintf(stderr, _("coff_array_type(): stringp == TRUE\n"));
++      return FALSE;
 +    }
 +
-+  sclass = isstruct? (isbitfield? C_FIELD: C_MOS): C_MOU;
-+
-+  for (i = 0, fp = tst->u.ts_struct.fields;
-+       i < tst->u.ts_struct.nfields;
-+       i++, fp++)
-+    {
-+      if (strlen (fp->name) == 0)
-+      {
-+        /* empty name could happen inside bitfield */
-+        fp->types = NULL;
-+        continue;
-+      }
-+
-+      info->tstack = fp->types;
-+      if (!coff_make_typed_symbol (info, &csymp, TS_NONE))
-+      return FALSE;
-+
-+      csymp->symbol.name = xstrdup (fp->name);
-+      csymp->symbol.flags = BSF_NOT_AT_END;
-+      csymp->symbol.section = bfd_com_section_ptr;
-+      csymp->native->u.syment.n_sclass = sclass;
-+      csymp->symbol.value = isbitfield? fp->bitpos: fp->bitpos / 8;
-+      if (isbitfield)
-+      {
-+        csymp->native->u.syment.n_numaux = 1;
-+        aux = &((csymp->native + 1)->u.auxent);
-+        aux->x_sym.x_misc.x_lnsz.x_size = fp->bitsize;
-+      }
++  coff_push_type (TS_ARRAY);
++  tst->u.ts_array.low = low;
++  tst->u.ts_array.high = high;
 +
-+      coff_record_symbol (info, csymp);
++  return TRUE;
++}
 +
-+      fp->types = NULL;
-+    }
++/* Push a set type.  */
 +
-+  info->tstack = savedtst;
++static bfd_boolean
++coff_set_type (p, bitstringp)
++     PTR p;
++     bfd_boolean bitstringp ATTRIBUTE_UNUSED;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
 +
-+  /* Record our endndx field for later fixing. */
-+  fixp = (struct coff_fix_stack *) xmalloc (sizeof (struct coff_fix_stack));
-+  fixp->native = scsymp->native + 1;  /* points to first AUX */
-+  fixp->next = NULL;
-+  if (info->fixes == NULL)
-+    info->fixes = fixp;
-+  else
-+    {
-+      for (ofp = info->fixes; ofp->next != NULL;)
-+      ofp = ofp->next;
-+      ofp->next = fixp;
-+    }
++#if COFF_DEBUG
++  printf ("coff_set_type(%d)\n", bitstringp);
++#endif
 +
-+  coff_record_symbol (info, ecsymp);
-+  info->flags |= COFF_FL_FIX_ENDNDX;
++  coff_complain_unsupp (_("set"));
 +
 +  return TRUE;
 +}
 +
-+static bfd_boolean coff_emit_enum (info, tst, ehash)
-+     struct coff_write_handle *info;
-+     struct coff_type_stack *tst;
-+     struct coff_enum_hash_entry *ehash;
-+{
-+  coff_symbol_type *csymp, *scsymp, *ecsymp;
-+  union internal_auxent *aux;
-+  struct coff_fix_stack *fixp, *ofp;
-+  int i;
++/* Push an offset type.  */
 +
-+  if ((info->flags & (COFF_FL_AVR | COFF_FL_EXT_AVR)) ==
-+      COFF_FL_AVR)
-+    /* old AVR COFF doesn't support enum debugging */
-+    return TRUE;
++static bfd_boolean
++coff_offset_type (p)
++     PTR p;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
 +
-+  /* Synthesize a new internal COFF symbol for the enum. */
-+  scsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+  if (scsymp == NULL)
-+    return FALSE;
++#if COFF_DEBUG
++  printf ("coff_offset_type()\n");
++#endif
 +
-+  if (tst->u.ts_enum.tagismalloced)
-+    scsymp->symbol.name = xstrdup (tst->u.ts_enum.tag.malloctag);
-+  else
-+    scsymp->symbol.name = tst->u.ts_enum.tag.fixtag;
-+  scsymp->symbol.flags = BSF_NOT_AT_END;
-+  scsymp->symbol.section = bfd_und_section_ptr;
-+  scsymp->native->u.syment.n_sclass = C_ENTAG;
-+  scsymp->native->u.syment.n_type = T_ENUM;
-+  scsymp->native->u.syment.n_numaux = 1;
-+  scsymp->symbol.udata.p = NULL;
-+  scsymp->symbol.value = 0;
++  coff_complain_unsupp (_("offset"));
 +
-+  ehash->native = scsymp->native;
++  return TRUE;
++}
 +
-+  /* Synthesize a new internal COFF symbol for the end of struct/union. */
-+  ecsymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+  if (ecsymp == NULL)
-+    return FALSE;
++/* Push a method type.  */
 +
-+  ecsymp->symbol.name = ".eos";
-+  ecsymp->symbol.flags = BSF_NOT_AT_END;
-+  /* We need to use the com section here since bfd/coffgen.c
-+     translates this into an N_UNDEF one without clobbering the
-+     value. */
-+  ecsymp->symbol.section = bfd_com_section_ptr;
-+  ecsymp->native->u.syment.n_sclass = C_EOS;
-+  ecsymp->symbol.udata.p = NULL;
-+  ecsymp->symbol.value = info->enumsize;
-+  ecsymp->native->u.syment.n_numaux = 1;
-+  (ecsymp->native + 1)->fix_tag = 1;
-+  aux = &((ecsymp->native + 1)->u.auxent);
-+  aux->x_sym.x_tagndx.p = scsymp->native;
-+  aux->x_sym.x_misc.x_lnsz.x_size = info->enumsize;
++static bfd_boolean
++coff_method_type (p, domainp, argcount, varargs)
++     PTR p;
++     bfd_boolean domainp ATTRIBUTE_UNUSED;
++     int argcount ATTRIBUTE_UNUSED;
++     bfd_boolean varargs ATTRIBUTE_UNUSED;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
 +
-+  coff_record_symbol (info, scsymp);
++#if COFF_DEBUG
++  printf ("coff_method_type(%d, %d, %d)\n",
++        domainp, argcount, varargs);
++#endif
 +
-+  for (i = 0;; i++)
-+    {
-+      const char *name = tst->u.ts_enum.names[i];
-+      if (name == NULL)
-+      break;
++  coff_complain_unsupp (_("method"));
 +
-+      /* Synthesize a new internal COFF symbol for the enum. */
-+      csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+      if (csymp == NULL)
-+      return FALSE;
++  return TRUE;
++}
 +
-+      csymp->symbol.name = xstrdup (name);
-+      csymp->symbol.flags = BSF_NOT_AT_END;
-+      csymp->symbol.section = bfd_com_section_ptr;
-+      csymp->native->u.syment.n_sclass = C_MOE;
-+      csymp->symbol.udata.p = NULL;
-+      csymp->symbol.value = tst->u.ts_enum.vals[i];
++/* Push a const version of a type.  */
 +
-+      coff_record_symbol (info, csymp);
-+    }
++static bfd_boolean
++coff_const_type (p)
++     PTR p ATTRIBUTE_UNUSED;
++{
 +
-+  /* Record our endndx field for later fixing. */
-+  fixp = (struct coff_fix_stack *) xmalloc (sizeof (struct coff_fix_stack));
-+  fixp->native = scsymp->native + 1;  /* points to first AUX */
-+  fixp->next = NULL;
-+  if (info->fixes == NULL)
-+    info->fixes = fixp;
-+  else
-+    {
-+      for (ofp = info->fixes; ofp->next != NULL;)
-+      ofp = ofp->next;
-+      ofp->next = fixp;
-+    }
++#if COFF_DEBUG
++  printf ("coff_const_type()\n");
++#endif
 +
-+  coff_record_symbol (info, ecsymp);
-+  info->flags |= COFF_FL_FIX_ENDNDX;
++  /* const modifier is ignored by COFF */
 +
 +  return TRUE;
 +}
 +
-+/* Emit a non-debugging symbol that came from the input symbol table,
-+   and has not been claimed by one of the debugging symbols. */
++/* Push a volatile version of a type.  */
++
 +static bfd_boolean
-+coff_emit_ndebug_sym (info, osymp, localp)
-+     struct coff_write_handle *info;
-+     asymbol *osymp;
-+     bfd_boolean localp;
++coff_volatile_type (p)
++     PTR p ATTRIBUTE_UNUSED;
 +{
-+  coff_symbol_type *csymp;
-+
-+  /* Create new COFF symbol. */
-+  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+  if (csymp == NULL)
-+    return FALSE;
 +
-+  csymp->symbol.name = xstrdup (osymp->name);
-+  csymp->symbol.value = osymp->value;
-+  csymp->symbol.flags = localp? BSF_LOCAL: BSF_GLOBAL;
-+  csymp->symbol.section = osymp->section;
-+  csymp->symbol.udata.p = NULL;
-+  csymp->native->u.syment.n_sclass = localp? C_STAT: C_EXT;
-+  csymp->native->u.syment.n_type = T_NULL;
++#if COFF_DEBUG
++  printf ("coff_volatile_type()\n");
++#endif
 +
-+  coff_record_symbol (info, csymp);
++  /* volatile modifier is ignored by COFF */
 +
 +  return TRUE;
 +}
-+\f
-+/* The general routine to write out COFF debugging information.  This
-+   synthesizes and accumulates the COFF symbols.  Actual symbol table
-+   output is performed later on by the BFD functions.  ABFD is the BFD
-+   and DHANDLE is the handle for the debugging information.  symcountp
-+   and symppp point to the incoming (parsed) symbol list on entry, and
-+   will be updated to point to the new symbol table's values upon
-+   exit. */
 +
-+bfd_boolean
-+write_coff_debugging_info (abfd, dhandle, symcountp, symppp)
-+     bfd *abfd;
-+     PTR dhandle;
-+     long *symcountp;
-+     asymbol ***symppp;
++/* Start outputting a struct.  */
++
++static bfd_boolean
++coff_start_struct_type (p, tag, id, structp, size)
++     PTR p;
++     const char *tag;
++     unsigned int id;
++     bfd_boolean structp;
++     unsigned int size;
 +{
-+  struct coff_write_handle info;
-+  long i, l;
-+  asymbol *symp;
-+  struct coff_compilation_unit *up;
-+  coff_symbol_type *csymp;
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst, *savedts;
++  struct coff_struct_hash_entry *shash;
++  char buf[20];
++  const char *name;
 +
-+  memset ((void *)&info, 0, sizeof info);
++#if COFF_DEBUG
++  printf ("coff_start_struct_type(%s, %d, %d, %d)\n",
++        tag, id, structp, size);
++#endif
 +
-+  info.abfd = abfd;
++  savedts = info->tstack;
++  info->tstack = NULL;
 +
-+  info.pointersize = info.enumsize = 4;
++  coff_push_type (TS_STRUCT);
 +
-+  switch (bfd_get_arch (abfd))
++  if (tag == NULL)
 +    {
-+    case bfd_arch_avr:
-+      info.flags |= COFF_FL_AVR;
-+      if (strcmp (abfd->xvec->name, "coff-ext-avr") == 0)
-+      info.flags |= COFF_FL_EXT_AVR;
-+      /* Fix the builtin type sizes. */
-+      coff_predef_types[0].size = 2;  /* sizeof(int) == 2 */
-+      coff_predef_types[4].size = 4;  /* sizeof(double) == 4 */
-+      coff_predef_types[6].size = 2;  /* sizeof(unsigned int) == 2 */
-+      info.pointersize = info.enumsize = 2;
-+      break;
++      sprintf(buf, ".%dfake", id);
++      name = tst->u.ts_struct.tag.malloctag = xstrdup (buf);
++      tst->u.ts_struct.tagismalloced = TRUE;
++    }
++  else
++    name = tst->u.ts_struct.tag.fixtag = tag;
++  tst->u.ts_struct.id = id;
++  tst->u.ts_struct.isstruct = structp;
++  tst->u.ts_struct.size = size;
++  tst->u.ts_struct.savedts = savedts;
 +
-+    default:
-+      ;
++  shash = coff_struct_hash_lookup (&info->structs, name, FALSE, FALSE);
++  if (shash != NULL && shash->types != NULL)
++    {
++#if COFF_DEBUG
++      printf ("new %s definition for %s\n",
++            tst->u.ts_struct.isstruct? "struct": "union", name);
++#endif
++      coff_free_struct_info (shash, NULL);
++      shash->types = NULL;
++      shash->emitted = FALSE;
 +    }
++  else
++    (void)coff_struct_hash_lookup (&info->structs, name,
++                           TRUE, tst->u.ts_struct.tagismalloced);
 +
-+  coff_copy_symbols(&info, *symcountp, *symppp);
++  return TRUE;
++}
 +
-+  if (info.textsect == NULL)
++/* Add a field to a struct.  */
++
++static bfd_boolean
++coff_struct_field (p, name, bitpos, bitsize, visibility)
++     PTR p;
++     const char *name;
++     bfd_vma bitpos;
++     bfd_vma bitsize;
++     enum debug_visibility visibility;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst, *otst;
++  struct coff_struct_fields *fp;
++  struct coff_struct_hash_entry *shash;
++  struct coff_enum_hash_entry *ehash;
++  const char *tag;
++
++#if COFF_DEBUG
++  printf ("coff_struct_field(%s, %d, %d, %d)\n",
++        name, (int)bitpos, (int)bitsize, (int)visibility);
++#endif
++
++  /* Find the last element on the type stack. */
++  assert (info->tstack != NULL);
++  for (tst = info->tstack, otst = NULL; tst->next != NULL;)
 +    {
-+      fprintf (stderr, _("Warning: no \"text\" section found in output file\n"));
-+      info.textsect = bfd_abs_section_ptr;
++      otst = tst;
++      tst = tst->next;
 +    }
-+  if (info.datasect == NULL)
++  if (otst != NULL)
++    otst->next = NULL;
++
++  if (tst->tsk != TS_STRUCT)
 +    {
-+      fprintf (stderr, _("Warning: no \"data\" section found in output file\n"));
-+      info.datasect = bfd_abs_section_ptr;
++      fprintf (stderr, "coff_struct_field() not within structure definition\n");
++      return FALSE;
++    }
++  tst->u.ts_struct.fields = (struct coff_struct_fields *)
++    xrealloc (tst->u.ts_struct.fields,
++            ++tst->u.ts_struct.nfields * sizeof (struct coff_struct_fields));
++  fp = tst->u.ts_struct.fields + (tst->u.ts_struct.nfields - 1);
++  fp->name = name;
++  fp->bitpos = bitpos;
++  fp->bitsize = bitsize;
++  fp->visibility = visibility;
++  otst = fp->types = info->tstack;
++  while (otst->next != NULL)
++    otst = otst->next;
++  if (otst->tsk == TS_STRUCT && otst->u.ts_struct.shash == NULL)
++    {
++      if (otst->u.ts_struct.tagismalloced)
++      tag = otst->u.ts_struct.tag.malloctag;
++      else
++      tag = otst->u.ts_struct.tag.fixtag;
++      shash = coff_struct_hash_lookup (&info->structs, tag, FALSE, FALSE);
++      assert (shash != NULL);
++      if (!shash->emitted)
++      {
++        if (shash->types == NULL)
++          {
++            shash->types = (struct coff_type_stack *)
++              xmalloc (sizeof (struct coff_type_stack));
++            memcpy (shash->types, otst, sizeof (struct coff_type_stack));
++          }
++        shash->emitted = TRUE;
++        coff_emit_struct (info, otst, shash);
++      }
++    }
++  else if (otst->tsk == TS_ENUM)
++    {
++      if (otst->u.ts_enum.tagismalloced)
++      tag = otst->u.ts_enum.tag.malloctag;
++      else
++      tag = otst->u.ts_enum.tag.fixtag;
++      ehash = coff_enum_hash_lookup (&info->enums, tag, TRUE, FALSE);
++      assert (ehash != NULL);
++      if (!ehash->emitted)
++      {
++        if (ehash->types == NULL)
++          {
++            ehash->types = (struct coff_type_stack *)
++              xmalloc (sizeof (struct coff_type_stack));
++            memcpy (ehash->types, otst, sizeof (struct coff_type_stack));
++          }
++        ehash->emitted = TRUE;
++        coff_emit_enum (info, otst, ehash);
++      }
 +    }
 +
-+  if (! bfd_hash_table_init (&info.types.root, coff_name_type_newfunc,
-+                           sizeof(struct coff_name_type_hash_entry)))
-+    return FALSE;
-+
-+  if (! bfd_hash_table_init (&info.structs.root, coff_struct_newfunc,
-+                           sizeof(struct coff_struct_hash_entry)))
-+    return FALSE;
-+
-+  if (! bfd_hash_table_init (&info.enums.root, coff_enum_newfunc,
-+                           sizeof(struct coff_enum_hash_entry)))
-+    return FALSE;
-+
-+  if (! debug_write (dhandle, &coff_fns, (PTR) &info))
-+    return FALSE;
++  info->tstack = tst;
 +
-+  /* If there is an old compilation unit that has got any local
-+     non-debugging symbols left over, send them out now. */
-+  if (info.currentfile != NULL && info.currentfile->totsyms != 0)
-+    for (i = 0; i < info.currentfile->nsyms; i++)
-+      {
-+      up = info.currentfile;
++  return TRUE;
++}
 +
-+      if (up->syms[i] != NULL)
-+        {
-+          coff_emit_ndebug_sym (&info, up->syms[i], TRUE);
-+          up->syms[i] = NULL;
-+          up->totsyms--;
-+        }
-+      }
++/* Finish up a struct.  */
 +
-+  /* See whether there are any non-debugging symbols left from the
-+     input symbol table.  First look at all local symbols which must
-+     be from entire compilation units we didn't see yet in the
-+     debugging information, because anything else has already been
-+     handled at the end of each compilation unit (like in the loop
-+     immediately above).  Any compilation unit that has already been
-+     processed that way is supposed to have its "totsyms" counted down
-+     to 0 now, so we can skip them.
++static bfd_boolean
++coff_end_struct_type (p)
++     PTR p;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst, *savedts;
 +
-+     Finally, put out all remaining global non-debugging symbols. */
-+  for (l = 0; l < info.nunits; l++)
++#if COFF_DEBUG
++  printf ("coff_end_struct_type()\n");
++#endif
++
++  /* Our struct definition should be the only type stack element by
++     now. */
++  assert (info->tstack != NULL);
++  tst = info->tstack;
++  if (tst->tsk != TS_STRUCT || tst->next != NULL)
 +    {
-+      const char *bn;
++      fprintf (stderr, "coff_struct_field() not within structure definition\n");
++      return FALSE;
++    }
 +
-+      up = info.units + l;
-+      if (up->totsyms == 0)
-+      continue;
++  /* Restore saved type stack, and push our now complete struct
++     definition on top. */
++  savedts = tst->u.ts_struct.savedts;
++  tst->u.ts_struct.savedts = info->tstack;
++  info->tstack = savedts;
++  tst->next = info->tstack;
++  info->tstack = tst;
 +
-+      /* Create COFF symbol for this compilation unit. */
-+      csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info.abfd, 0, 0);
-+      if (csymp == NULL)
-+      return FALSE;
++  return TRUE;
++}
 +
-+      bn = bu_basename (up->fname);
++/* Start outputting a class.  */
 +
-+      if (bfd_coff_long_filenames (info.abfd))
-+      csymp->symbol.name = up->fname;
-+      else
-+      csymp->symbol.name = bn;
++static bfd_boolean
++coff_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
++     PTR p;
++     const char *tag ATTRIBUTE_UNUSED;
++     unsigned int id ATTRIBUTE_UNUSED;
++     bfd_boolean structp ATTRIBUTE_UNUSED;
++     unsigned int size ATTRIBUTE_UNUSED;
++     bfd_boolean vptr ATTRIBUTE_UNUSED;
++     bfd_boolean ownvptr ATTRIBUTE_UNUSED;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
 +
-+      csymp->symbol.value = 0;
-+      csymp->symbol.udata.p = NULL;
-+      csymp->native->u.syment.n_sclass = C_FILE;
-+      csymp->native->u.syment.n_numaux = 1; /* force filename into aux entry */
-+      coff_record_symbol (&info, csymp);
++#if COFF_DEBUG
++  printf ("coff_start_class_type(%s, %d, %d, %d, %d, %d)\n",
++        tag, id, structp, size, vptr, ownvptr);
++#endif
 +
-+      for (i = 0; i < up->nsyms; i++)
-+      {
-+        symp = up->syms[i];
-+        if (symp == NULL)
-+          continue;
++  coff_complain_unsupp (_("class"));
 +
-+        coff_emit_ndebug_sym (&info, symp, TRUE);
-+      }
-+    }
++  return TRUE;
++}
 +
-+  for (i = 0; i < info.nglobals; i++)
-+    {
-+      symp = info.globals[i];
-+      if (symp == NULL)
-+      continue;
++/* Add a static member to the class on the type stack.  */
 +
-+      coff_emit_ndebug_sym (&info, symp, FALSE);
-+    }
++static bfd_boolean
++coff_class_static_member (p, name, physname, visibility)
++     PTR p ATTRIBUTE_UNUSED;
++     const char *name ATTRIBUTE_UNUSED;
++     const char *physname ATTRIBUTE_UNUSED;
++     enum debug_visibility visibility ATTRIBUTE_UNUSED;
++{
 +
-+  /* Fixup the AUX entries for the section symbols we have emitted
-+     earlier (so they are guaranteed to be at the beginning of the
-+     symbol table).  In particular, the line number count (which we
-+     only have for the text section) is known right now. */
-+  for (i = 0; i < info.nsecsyms; i++)
-+    {
-+      union internal_auxent *aux;
++#if COFF_DEBUG
++  printf ("coff_class_static_member(%s, %s, %d)\n",
++        name, physname, (int)visibility);
++#endif
 +
-+      csymp = info.secsyms[i];
++  return TRUE;
++}
 +
-+      aux = &((csymp->native + 1)->u.auxent);
-+      aux->x_scn.x_scnlen = csymp->symbol.section->output_section->rawsize;
-+      aux->x_scn.x_nreloc = csymp->symbol.section->reloc_count;
-+      if (csymp->symbol.section == info.textsect)
-+      aux->x_scn.x_nlinno = info.totlnos;
-+    }
-+  free (info.secsyms);
++/* Add a base class to the class on the type stack.  */
 +
-+  coff_name_type_hash_traverse (&info.types, coff_free_type_info, NULL);
-+  bfd_hash_table_free (&info.types.root);
++static bfd_boolean
++coff_class_baseclass (p, bitpos, virtual, visibility)
++     PTR p ATTRIBUTE_UNUSED;
++     bfd_vma bitpos ATTRIBUTE_UNUSED;
++     bfd_boolean virtual ATTRIBUTE_UNUSED;
++     enum debug_visibility visibility ATTRIBUTE_UNUSED;
++{
 +
-+  coff_struct_hash_traverse (&info.structs, coff_free_struct_info, NULL);
-+  bfd_hash_table_free (&info.structs.root);
++#if COFF_DEBUG
++  printf ("coff_class_baseclass(%d, %d, %d)\n",
++        (int)bitpos, virtual, (int)visibility);
++#endif
 +
-+  coff_enum_hash_traverse (&info.enums, coff_free_enum_info, NULL);
-+  bfd_hash_table_free (&info.enums.root);
++  return TRUE;
++}
 +
-+  /* FIXME: free all the other stuff remembered in "info". */
++/* Start adding a method to the class on the type stack.  */
 +
-+  free (*symppp);
++static bfd_boolean
++coff_class_start_method (p, name)
++     PTR p ATTRIBUTE_UNUSED;
++     const char *name ATTRIBUTE_UNUSED;
++{
 +
-+  *symcountp = info.nsyms;
-+  *symppp = (asymbol **)info.syms;
++#if COFF_DEBUG
++  printf ("coff_class_start_method(%s)\n", name);
++#endif
 +
 +  return TRUE;
 +}
 +
-+/* Start writing out information for a compilation unit.  */
++/* Add a variant to the current method.  */
 +
 +static bfd_boolean
-+coff_start_compilation_unit (p, filename)
-+     PTR p;
-+     const char *filename;
++coff_class_method_variant (p, physname, visibility, constp, volatilep,
++                         voffset, contextp)
++     PTR p ATTRIBUTE_UNUSED;
++     const char *physname ATTRIBUTE_UNUSED;
++     enum debug_visibility visibility ATTRIBUTE_UNUSED;
++     bfd_boolean constp ATTRIBUTE_UNUSED;
++     bfd_boolean volatilep ATTRIBUTE_UNUSED;
++     bfd_vma voffset ATTRIBUTE_UNUSED;
++     bfd_boolean contextp ATTRIBUTE_UNUSED;
 +{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  long i;
-+  const char *bn;
-+  bfd_boolean found;
-+  coff_symbol_type *csymp;
 +
 +#if COFF_DEBUG
-+  printf ("coff_start_compilation_unit(%s)\n", filename);
++  printf ("coff_class_method_variant(%s, %d, %d, %d, %d, %d)\n",
++        physname, (int)visibility, constp, volatilep,
++        (int)voffset, contextp);
 +#endif
 +
-+  /* If there is an old compilation unit that has got any local
-+     non-debugging symbols left over, send them out now. */
-+  if (info->currentfile != NULL && info->currentfile->totsyms != 0)
-+    for (i = 0; i < info->currentfile->nsyms; i++)
-+      {
-+      struct coff_compilation_unit *up = info->currentfile;
++  return TRUE;
++}
 +
-+      if (up->syms[i] != NULL)
-+        {
-+          coff_emit_ndebug_sym (info, up->syms[i], TRUE);
-+          up->syms[i] = NULL;
-+          up->totsyms--;
-+        }
-+      }
++/* Add a static variant to the current method.  */
 +
-+  /* symtab (and thus COFF debugging) symbols can only transfer the
-+     basename of the file, so strip the dirname */
-+  bn = bu_basename (filename);
++static bfd_boolean
++coff_class_static_method_variant (p, physname, visibility, constp, volatilep)
++     PTR p ATTRIBUTE_UNUSED;
++     const char *physname ATTRIBUTE_UNUSED;
++     enum debug_visibility visibility ATTRIBUTE_UNUSED;
++     bfd_boolean constp ATTRIBUTE_UNUSED;
++     bfd_boolean volatilep ATTRIBUTE_UNUSED;
++{
 +
-+  for (i = 0, found = FALSE; i < info->nunits; i++)
-+    {
-+      if (strcmp (info->units[i].fname, bn) == 0)
-+      {
-+        info->currentfile = info->units + i;
-+        found = TRUE;
-+        break;
-+      }
-+    }
-+  if (!found)
-+    {
-+      fprintf(stderr,
-+            _("Warning: file %s not found in symbol table, ignoring\n"),
-+            filename);
-+      info->currentfile = NULL;
-+      return TRUE;
-+    }
++#if COFF_DEBUG
++  printf ("coff_class_static_method_variant(%s, %d, %d, %d)\n",
++        physname, (int)visibility, constp, volatilep);
++#endif
 +
-+  /* Synthesize a new internal COFF symbol. */
-+  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+  if (csymp == NULL)
-+    return FALSE;
++  return TRUE;
++}
 +
-+  /* Note that coff_fix_symbol_name() [coffgen.c] will fix this for
-+     us: the symbol name will be replaced by ".file", and the filename
-+     will be moved to the aux entries.  We use the long name obtained
-+     from the debugging information (that includes the full path) if
-+     our COFF format supports long filenames, otherwise we only use
-+     the basename of the file. */
-+  if (bfd_coff_long_filenames (info->abfd))
-+    csymp->symbol.name = filename;
-+  else
-+    csymp->symbol.name = bn;
-+  csymp->symbol.value = 0;
-+  csymp->symbol.udata.p = NULL;
-+  csymp->native->u.syment.n_sclass = C_FILE;
-+  csymp->native->u.syment.n_numaux = 1;       /* force filename into aux entry */
-+  coff_record_symbol (info, csymp);
++/* Finish up a method.  */
++
++static bfd_boolean
++coff_class_end_method (p)
++     PTR p ATTRIBUTE_UNUSED;
++{
++
++#if COFF_DEBUG
++  printf ("coff_class_end_method()\n");
++#endif
 +
 +  return TRUE;
 +}
 +
-+/* Start writing out information for a particular source file.  */
++/* Finish up a class.  */
 +
 +static bfd_boolean
-+coff_start_source (p, filename)
++coff_end_class_type (p)
 +     PTR p ATTRIBUTE_UNUSED;
-+     const char *filename ATTRIBUTE_UNUSED;
 +{
 +
 +#if COFF_DEBUG
-+  printf ("coff_start_source(%s)\n", filename);
++  printf ("coff_end_class_type()\n");
 +#endif
 +
-+  /* COFF cannot handle include filenames. */
-+
 +  return TRUE;
 +}
 +
-+/* Push an empty type.  This shouldn't normally happen.  */
++/* Push a typedef which was previously defined.  */
 +
 +static bfd_boolean
-+coff_empty_type (p)
++coff_typedef_type (p, name)
 +     PTR p;
++     const char *name;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst;
++  struct coff_name_type_hash_entry *nthash;
++  struct coff_type_stack *tst, *newchain, *newst, *temp;
 +
 +#if COFF_DEBUG
-+  printf ("coff_empty_type()\n");
++  printf ("coff_typedef_type(%s)\n", name);
 +#endif
 +
-+  coff_push_type (TS_EMPTY);
++  nthash = coff_name_type_hash_lookup (&info->types, name, FALSE, FALSE);
++
++  /* nthash should never be NULL, since that would imply that the
++     generic debugging code has asked for a typedef which it has not
++     yet defined.  */
++  assert (nthash != NULL);
++
++  /* Just push the entire type stack snapshot we've got on top of the
++     existing typestack.  See coff_typdef() below for how this
++     works.  We need to copy over each element however, since anybody
++     popping elements off the typestack is supposed to free() each of
++     them. */
++
++  for (tst = nthash->types, temp = newst = newchain = NULL; tst != NULL;)
++    {
++      temp = newst;
++      newst = (struct coff_type_stack *) xmalloc (sizeof (*newst));
++      if (newchain == NULL)
++      newchain = newst;
++      memcpy (newst, tst, sizeof (*newst));
++      if (temp != NULL)
++      temp->next = newst;
++
++      tst = tst->next;
++    }
++  newst->next = info->tstack;
++  info->tstack = newchain;
 +
 +  return TRUE;
 +}
 +
-+/* Push a void type.  */
++/* Push a struct, union or class tag.  */
 +
 +static bfd_boolean
-+coff_void_type (p)
++coff_tag_type (p, name, id, kind)
 +     PTR p;
++     const char *name;
++     unsigned int id ATTRIBUTE_UNUSED;
++     enum debug_type_kind kind;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst;
++  struct coff_type_stack *tst, *newchain, *newst, *temp;
++  struct coff_struct_hash_entry *shash;
++  struct coff_enum_hash_entry *ehash;
++  char buf[20];
++  bfd_boolean needcopy = FALSE;
++  bfd_boolean isstruct = TRUE;
 +
 +#if COFF_DEBUG
-+  printf ("coff_void_type()\n");
++  printf ("coff_tag_type(%s, %d, %d)\n",
++        name, id, kind);
 +#endif
 +
-+  coff_push_type (TS_VOID);
++  if (name == NULL)
++    {
++      sprintf(buf, ".%dfake", id);
++      needcopy = TRUE;
++    }
++
++  switch (kind)
++    {
++    case DEBUG_KIND_UNION:
++    case DEBUG_KIND_UNION_CLASS:
++      isstruct = FALSE;
++      /* FALLTHROUGH */
++    case DEBUG_KIND_STRUCT:
++    case DEBUG_KIND_CLASS:
++      shash = coff_struct_hash_lookup (&info->structs,
++                                     name == NULL? buf: name, TRUE, needcopy);
++      assert (shash != NULL);
++      tst = shash->types;
++      if (tst == NULL)
++      {
++        /* This is a reference to a tag that has not yet been
++           defined (i. e., a forward reference).  Synthesize a
++           ts_struct entry by now, and mark it for later fixup. */
++        tst = (struct coff_type_stack *) xmalloc (sizeof *tst);
++        memset (tst, 0, sizeof *tst);
++        tst->tsk = TS_STRUCT;
++        tst->u.ts_struct.isstruct = isstruct;
++        tst->u.ts_struct.shash = shash;
++      }
++    docopystack:
++      /* Just push the entire type stack snapshot we've got on top of the
++       existing typestack.  See coff_typdef() below for how this
++       works.  We need to copy over each element however, since anybody
++       popping elements off the typestack is supposed to free() each of
++       them. */
++      for (temp = newst = newchain = NULL; tst != NULL;)
++      {
++        temp = newst;
++        newst = (struct coff_type_stack *) xmalloc (sizeof (*newst));
++        if (newchain == NULL)
++          newchain = newst;
++        memcpy (newst, tst, sizeof (*newst));
++        if (temp != NULL)
++          temp->next = newst;
++
++        tst = tst->next;
++      }
++      if (newst)
++      {
++        newst->next = info->tstack;
++        info->tstack = newchain;
++      }
++      break;
++
++    case DEBUG_KIND_ENUM:
++      ehash = coff_enum_hash_lookup (&info->enums,
++                                   name == NULL? buf: name, TRUE, needcopy);
++      assert (ehash != NULL);
++      tst = ehash->types;
++      if (tst == NULL)
++      {
++        /* This is a reference to a tag that has not yet been
++           defined (i. e., a forward reference).  Synthesize a
++           ts_enum entry by now, and mark it for later fixup. */
++        tst = (struct coff_type_stack *) xmalloc (sizeof *tst);
++        memset (tst, 0, sizeof *tst);
++        tst->tsk = TS_ENUM;
++        tst->u.ts_enum.ehash = ehash;
++      }
++      goto docopystack;
 +
++    default:
++      fprintf (stderr, _("illegal kind %d in coff_tag_type()\n"),
++             (int)kind);
++      return FALSE;
++    }
 +  return TRUE;
 +}
 +
-+/* Push an integer type.  */
++/* Define a typedef.  */
 +
 +static bfd_boolean
-+coff_int_type (p, size, unsignedp)
++coff_typdef (p, name)
 +     PTR p;
-+     unsigned int size;
-+     bfd_boolean unsignedp;
++     const char *name;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst;
++  struct coff_name_type_hash_entry *nthash;
 +
 +#if COFF_DEBUG
-+  printf ("coff_int_type(%d, %d)\n", size, unsignedp);
++  printf ("coff_typdef(%s)\n", name);
 +#endif
 +
-+  coff_push_type (TS_INT);
-+  tst->u.ts_int.size = size;
-+  tst->u.ts_int.isunsigned = unsignedp;
++  /* COFF cannot really handle typedefs.  While there is the option to
++     mark a symbol using the storage class C_TPDEF (so the COFF reader
++     will know that name), there is no way to place a reference to
++     that typedef into the just 16 bits COFF reserves for all of its
++     type information.  Thus, any use of the typedef must always fully
++     dereference the typedef again.  We do this by "snapshotting" the
++     current type stack under the name of our typedef, and later on,
++     when BFD debugging tells us to make use of the typedef (in
++     coff_typedef_type()), we just look it up, and push all we've got
++     completely onto the type stack again. */
++
++  if (info->tstack == NULL)
++    {
++      fprintf (stderr, _("coff_typdef() on an empty type stack\n"));
++      return FALSE;
++    }
++
++  nthash = coff_name_type_hash_lookup (&info->types, name, FALSE, FALSE);
++  if (nthash != NULL)
++    {
++#if COFF_DEBUG
++      printf ("new typedef for %s\n", name);
++#endif
++      coff_free_type_info (nthash, NULL);
++    }
++  else
++    nthash = coff_name_type_hash_lookup (&info->types, name, TRUE, FALSE);
++  if (nthash == NULL)
++    return FALSE;
++  nthash->types = info->tstack;
++
++  /* If the typestack is "sufficiently complex", emit a C_TPDEF symbol
++     for it.  We assume it to be sufficiently complex if there are
++     either at least two derived types, or one derived type where the
++     base type is not a simple scalar one. */
++  if (!nthash->emitted
++      && info->tstack->next != NULL
++      && (info->tstack->next->next != NULL || info->tstack->next->tsk >= TS_ENUM))
++    {
++      struct coff_type_stack *newchain, *otst, *tst, *ntst;
++      coff_symbol_type *csymp;
++
++      nthash->emitted = TRUE;
++
++      for (tst = info->tstack, newchain = otst = NULL;
++         tst != NULL;
++         tst = tst->next)
++      {
++        ntst = (struct coff_type_stack *)
++          xmalloc (sizeof (struct coff_type_stack));
++        memcpy (ntst, tst, sizeof (struct coff_type_stack));
++        if (otst == NULL)
++          newchain = ntst;
++        else
++          otst->next = ntst;
++        otst = ntst;
++      }
++      info->tstack = newchain;
++      if (!coff_make_typed_symbol (info, &csymp, TS_NONE))
++      return FALSE;
++
++      csymp->symbol.name = xstrdup (name);
++      csymp->symbol.flags = BSF_NOT_AT_END;
++      csymp->symbol.section = bfd_com_section_ptr;
++      csymp->native->u.syment.n_sclass = C_TPDEF;
++      csymp->symbol.value = 0;
++
++      coff_record_symbol (info, csymp);
++    }
++  info->tstack = NULL;
 +
 +  return TRUE;
 +}
 +
-+/* Push a floating point type.  */
++/* Define a tag.  */
 +
 +static bfd_boolean
-+coff_float_type (p, size)
++coff_tag (p, tag)
 +     PTR p;
-+     unsigned int size;
++     const char *tag;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst;
++  struct coff_type_stack *tst = NULL;
++  struct coff_struct_hash_entry *shash;
++  struct coff_enum_hash_entry *ehash;
++
++
++#if COFF_DEBUG
++  printf ("coff_tag(%s)\n", tag);
++#endif
++
++  if (info->tstack == NULL)
++    {
++      fprintf (stderr, _("coff_tag() called on an empty typestack\n"));
++      return FALSE;
++    }
++
++  switch (info->tstack->tsk)
++    {
++    case TS_STRUCT:
++      shash = coff_struct_hash_lookup (&info->structs, tag, FALSE, FALSE);
++      assert (shash != NULL);
++      shash->types = info->tstack;
++      info->tstack = NULL;
++      break;
 +
++    case TS_ENUM:
++      ehash = coff_enum_hash_lookup (&info->enums, tag, FALSE, FALSE);
++      if (ehash != NULL && ehash->types != NULL)
++      {
 +#if COFF_DEBUG
-+  printf ("coff_float_type(%d)\n", size);
++        printf ("new enum definition for %s\n", tag);
 +#endif
++        coff_free_enum_info (ehash, NULL);
++      }
++      else
++      ehash = coff_enum_hash_lookup (&info->enums, tag, TRUE, FALSE);
++      if (ehash == NULL)
++      return FALSE;
++      ehash->types = info->tstack;
++      info->tstack = NULL;
++      break;
 +
-+  coff_push_type (TS_FLOAT);
-+  tst->u.ts_float.size = size;
++    default:
++      fprintf (stderr, _("Illegal typestack (%d) in coff_tag()\n"), tst->tsk);
++      return FALSE;
++    }
 +
 +  return TRUE;
 +}
 +
-+/* Push a complex type.  */
++/* Define an integer constant.  */
 +
 +static bfd_boolean
-+coff_complex_type (p, size)
++coff_int_constant (p, name, val)
 +     PTR p;
-+     unsigned int size ATTRIBUTE_UNUSED;
++     const char *name ATTRIBUTE_UNUSED;
++     bfd_vma val ATTRIBUTE_UNUSED;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst;
 +
 +#if COFF_DEBUG
-+  printf ("coff_complex_type(%d)\n", size);
++  printf ("coff_int_constant(%s, %d)\n", name, (int)val);
 +#endif
 +
-+  coff_push_type (TS_COMPLEX);
++  coff_complain_unsupp (_("int constant"));
 +
 +  return TRUE;
 +}
 +
-+/* Push a bfd_boolean type. */
++/* Define a floating point constant.  */
 +
 +static bfd_boolean
-+coff_bool_type (p, size)
++coff_float_constant (p, name, val)
 +     PTR p;
-+     unsigned int size;
++     const char *name ATTRIBUTE_UNUSED;
++     double val ATTRIBUTE_UNUSED;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst;
 +
 +#if COFF_DEBUG
-+  printf ("coff_bool_type(%d)\n", size);
++  printf ("coff_float_constant(%s, %g)\n", name, val);
 +#endif
 +
-+  coff_push_type (TS_INT);
-+  tst->u.ts_int.size = size;
-+  tst->u.ts_int.isunsigned = TRUE;
++  coff_complain_unsupp (_("float constant"));
 +
 +  return TRUE;
 +}
 +
-+/* Push an enum type.  */
++/* Define a typed constant.  */
 +
 +static bfd_boolean
-+coff_enum_type (p, tag, names, vals)
++coff_typed_constant (p, name, val)
 +     PTR p;
-+     const char *tag;
-+     const char **names;
-+     bfd_signed_vma *vals;
++     const char *name ATTRIBUTE_UNUSED;
++     bfd_vma val ATTRIBUTE_UNUSED;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst;
-+  char buf[20];
 +
 +#if COFF_DEBUG
-+  int idx;
-+  printf ("coff_enum_type(%s [", tag);
-+  for (idx = 0; names[idx] != NULL; idx++)
-+    printf ("%s -> %d, ", names[idx], (int)vals[idx]);
-+  printf ("])\n");
++  printf ("coff_typed_constant(%s, %d)\n", name, (int)val);
 +#endif
 +
-+  coff_push_type (TS_ENUM);
-+
-+  if (tag == NULL)
-+    {
-+      sprintf(buf, ".%dfake", info->nenums++);
-+      tst->u.ts_enum.tag.malloctag = xstrdup (buf);
-+      tst->u.ts_enum.tagismalloced = TRUE;
-+    }
-+  else
-+    tst->u.ts_enum.tag.fixtag = tag;
-+  tst->u.ts_enum.names = names;
-+  tst->u.ts_enum.vals = vals;
++  coff_complain_unsupp (_("typed constant"));
 +
 +  return TRUE;
 +}
 +
-+/* Push a pointer type.  */
++/* Record a variable.  */
 +
 +static bfd_boolean
-+coff_pointer_type (p)
++coff_variable (p, name, kind, val)
 +     PTR p;
++     const char *name;
++     enum debug_var_kind kind;
++     bfd_vma val;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst;
++  unsigned char class;
++  asymbol *symp = NULL;
++  coff_symbol_type *csymp;
++  bfd_boolean global = FALSE;
++  flagword flags = BSF_LOCAL;
++  bfd_vma vmadiff = 0;
 +
 +#if COFF_DEBUG
-+  printf ("coff_pointer_type()\n");
++  printf ("coff_variable(%s, %d, %d)\n",
++        name, (int)kind, (int)val);
 +#endif
 +
-+  coff_push_type (TS_POINTER);
++  switch (kind)
++    {
++    default:
++      abort ();
 +
-+  return TRUE;
-+}
++    case DEBUG_GLOBAL:
++      flags = BSF_GLOBAL;
++      global = TRUE;
++      /* AVR COFF historically used C_EXTDEF for global variables, and
++       C_EXT for global functions.  Since some AVR COFF consumers
++       apparently depend on this, we mimic this behaviour as
++       well. */
++      class = info->flags & COFF_FL_AVR? C_EXTDEF: C_EXT;
++      break;
 +
-+/* Push a function type.  */
++    case DEBUG_STATIC:
++    case DEBUG_LOCAL_STATIC:
++      class = C_STAT;
++      break;
 +
-+static bfd_boolean
-+coff_function_type (p, argcount, varargs)
-+     PTR p;
-+     int argcount;
-+     bfd_boolean varargs ATTRIBUTE_UNUSED;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst;
++    case DEBUG_LOCAL:
++      class = C_AUTO;
++      break;
 +
-+#if COFF_DEBUG
-+  printf ("coff_function_type(%d, %d)\n", argcount, varargs);
-+#endif
++    case DEBUG_REGISTER:
++      class = C_REG;
++      break;
++    }
 +
-+  coff_push_type (TS_FUNC);
++  if (!coff_make_typed_symbol (info, &csymp, TS_NONE))
++    return FALSE;
 +
-+  /* FIXME should properly discard function arguments */
-+  if (argcount > -1)
++  if (class == C_REG && (info->flags & COFF_FL_AVR) != 0)
 +    {
-+      fprintf (stderr,
-+             _("coff_function_type() called with positive argcount\n"));
-+      return FALSE;
++      struct coff_private_symdata *priv = (struct coff_private_symdata *)
++      csymp->symbol.udata.p;
++      val = coff_fixup_avr_register (val, priv->size * 8);
 +    }
 +
-+  return TRUE;
-+}
-+
-+/* Push a reference type.  */
-+
-+static bfd_boolean
-+coff_reference_type (p)
-+     PTR p;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  csymp->symbol.name = name;
++  csymp->symbol.flags = flags;        /* Note: this clears BSF_DEBUGGING. */
 +
-+#if COFF_DEBUG
-+  printf ("coff_reference_type()\n");
-+#endif
++  /* Match the debugging symbol against the input symtab symbols.  If
++     we found one, use the section information from it.  Otherwise, we
++     are lost here and just use the absolute section that was
++     predeclared by coff_bfd_make_debug_symbol().  C_REG and C_AUTO
++     symbols (which we do not attempt to lookup in the symtab symbols
++     at all) go into the ABS section anyway. */
++  if (class != C_REG && class != C_AUTO)
++    {
++      symp = coff_find_symbol (info, name, FALSE, global);
++      if (symp)
++      {
++        csymp->symbol.section = symp->section;
++        vmadiff = symp->section->vma;
++      }
++    }
 +
-+  coff_complain_unsupp (_("reference"));
++  /* Symbols are relative to section vma. */
++  csymp->symbol.value = val - vmadiff;
++  csymp->native->u.syment.n_sclass = class;
++  coff_record_symbol (info, csymp);
 +
 +  return TRUE;
 +}
 +
-+/* Push a range type.  */
++/* Start outputting a function.  */
 +
 +static bfd_boolean
-+coff_range_type (p, low, high)
++coff_start_function (p, name, globalp)
 +     PTR p;
-+     bfd_signed_vma low ATTRIBUTE_UNUSED;
-+     bfd_signed_vma high ATTRIBUTE_UNUSED;
++     const char *name;
++     bfd_boolean globalp;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst, *savedts;
 +
 +#if COFF_DEBUG
-+  printf ("coff_range_type([%d..%d)\n", (int)low, (int)high);
++  printf ("coff_start_function(%s, %d)\n",
++        name, globalp);
 +#endif
 +
-+  coff_complain_unsupp (_("range"));
++  savedts = info->tstack;
++  info->tstack = NULL;
++
++  coff_push_type (TS_FUNC);
++
++  if (info->funname != NULL)
++    {
++      fprintf (stderr,
++             _("coff_start_function() called twice, pending %s, new %s\n"),
++             info->funname, name);
++      return FALSE;
++    }
++  info->funname = name;
++  info->funglobal = globalp;
++  info->flags |= COFF_FL_START_FCN;
++  tst->u.ts_func.savedts = savedts;
 +
 +  return TRUE;
 +}
 +
-+/* Push an array type.  */
++/* Output a function parameter.  */
 +
 +static bfd_boolean
-+coff_array_type (p, low, high, stringp)
++coff_function_parameter (p, name, kind, val)
 +     PTR p;
-+     bfd_signed_vma low;
-+     bfd_signed_vma high;
-+     bfd_boolean stringp;
++     const char *name;
++     enum debug_parm_kind kind;
++     bfd_vma val;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst;
++  coff_symbol_type *csymp;
++  unsigned char class;
 +
 +#if COFF_DEBUG
-+  printf ("coff_array_type([%d..%d], %d)\n",
-+        (int)low, (int)high, stringp);
++  printf ("coff_function_parameter(%s, %d, %d)\n",
++        name, (int)kind, (int)val);
 +#endif
 +
-+  /* Pop the range type, but ignore it.  COFF doesn't use it. */
-+  coff_pop_type ();
-+
-+  /* FIXME  What to do here? */
-+  if (stringp)
++  switch (kind)
 +    {
-+      fprintf(stderr, _("coff_array_type(): stringp == TRUE\n"));
-+      return FALSE;
-+    }
++    default:
++      abort ();
 +
-+  coff_push_type (TS_ARRAY);
-+  tst->u.ts_array.low = low;
-+  tst->u.ts_array.high = high;
++    case DEBUG_PARM_STACK:
++      class = C_ARG;
++      break;
 +
-+  return TRUE;
-+}
++    case DEBUG_PARM_REG:
++      class = C_REGPARM;
++      break;
++
++    case DEBUG_PARM_REFERENCE:
++    case DEBUG_PARM_REF_REG:
++      fprintf (stderr, _("Reference parameters not available in COFF\n"));
++      return TRUE;
++    }
 +
-+/* Push a set type.  */
++  if (!coff_make_typed_symbol (info, &csymp, TS_FUNC))
++    return FALSE;
 +
-+static bfd_boolean
-+coff_set_type (p, bitstringp)
-+     PTR p;
-+     bfd_boolean bitstringp ATTRIBUTE_UNUSED;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  if (class == C_REGPARM && (info->flags & COFF_FL_AVR) != 0)
++    {
++      struct coff_private_symdata *priv = (struct coff_private_symdata *)
++      csymp->symbol.udata.p;
++      val = coff_fixup_avr_register (val, priv->size * 8);
++    }
 +
-+#if COFF_DEBUG
-+  printf ("coff_set_type(%d)\n", bitstringp);
-+#endif
++  csymp->symbol.name = name;
++  csymp->symbol.value = val;
++  csymp->symbol.flags |= BSF_LOCAL;
++  csymp->native->u.syment.n_sclass = class;
 +
-+  coff_complain_unsupp (_("set"));
++  /* Since function parameters precede the actual function definition,
++     defer their output until the function has been created. */
++  info->fargs = (coff_symbol_type **)
++    xrealloc (info->fargs, ++info->nfargs * sizeof (coff_symbol_type *));
++  info->fargs[info->nfargs - 1] = csymp;
 +
 +  return TRUE;
 +}
 +
-+/* Push an offset type.  */
++/* Start a block.  */
 +
 +static bfd_boolean
-+coff_offset_type (p)
++coff_start_block (p, addr)
 +     PTR p;
++     bfd_vma addr;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst, *otst;
++  struct coff_fix_stack *fixp, *ofp;
++  asymbol *symp;
++  coff_symbol_type *csymp;
++  unsigned int i;
++  bfd_boolean is_start_fcn;
 +
 +#if COFF_DEBUG
-+  printf ("coff_offset_type()\n");
++  printf ("coff_start_block(%#x)\n", (int)addr);
 +#endif
 +
-+  coff_complain_unsupp (_("offset"));
++  is_start_fcn = info->flags & COFF_FL_START_FCN;
 +
-+  return TRUE;
-+}
++  if (is_start_fcn)
++    {
++      /* This is the starting block of a function.  We are going to
++         write three symbols here, one for the function itself, one
++         ".bf" symbol to indicate the begin of the function, and
++         finally one ".bb" for the first block inside the function. */
++      info->flags &= ~COFF_FL_START_FCN;
 +
-+/* Push a method type.  */
++      /* Our function definition should be the only type stack element
++       by now. */
++      assert (info->tstack != NULL);
++      tst = info->tstack;
++      if (tst->tsk != TS_FUNC || tst->next != NULL)
++      {
++        fprintf (stderr,
++                 _("coff_start_block() not within function definition\n"));
++        return FALSE;
++      }
 +
-+static bfd_boolean
-+coff_method_type (p, domainp, argcount, varargs)
-+     PTR p;
-+     bfd_boolean domainp ATTRIBUTE_UNUSED;
-+     int argcount ATTRIBUTE_UNUSED;
-+     bfd_boolean varargs ATTRIBUTE_UNUSED;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
++      /* Restore saved type stack, and push our now complete function
++       definition on top. */
++      info->tstack = tst->u.ts_func.savedts;
++      tst->next = info->tstack;
++      info->tstack = tst;
 +
-+#if COFF_DEBUG
-+  printf ("coff_method_type(%d, %d, %d)\n",
-+        domainp, argcount, varargs);
-+#endif
++      if (info->currentfile == NULL)
++      {
++        fprintf (stderr,
++                 _("Warning: ignoring function %s() outside any compilation unit\n"),
++                 info->funname);
++        for (tst = info->tstack, otst = NULL; tst != NULL;)
++          {
++            otst = tst;
++            tst = otst->next;
++            if (otst->tsk == TS_ENUM &&
++                otst->u.ts_enum.tagismalloced)
++              free (otst->u.ts_enum.tag.malloctag);
++            else if (otst->tsk == TS_STRUCT &&
++                     otst->u.ts_struct.tagismalloced)
++              free (otst->u.ts_struct.tag.malloctag);
++            free (otst);
++          }
++        info->tstack = NULL;
++        info->funname = NULL;
 +
-+  coff_complain_unsupp (_("method"));
++        return TRUE;
++      }
 +
-+  return TRUE;
-+}
++      if (!coff_make_typed_symbol (info, &csymp, TS_NONE))
++      return FALSE;
 +
-+/* Push a const version of a type.  */
++      csymp->symbol.name = info->funname;
++      csymp->symbol.flags = BSF_FUNCTION |
++      (info->funglobal? BSF_GLOBAL: BSF_LOCAL);
++      symp = coff_find_symbol (info, info->funname, TRUE, info->funglobal);
++      if (symp == NULL)
++      {
++        fprintf (stderr,
++                 _("function %s not found in symbol table, defaulting to \"text\" section\n"),
++                 info->funname);
++        csymp->symbol.section = info->funcsection = info->textsect;
++      }
++      else
++      csymp->symbol.section = info->funcsection = symp->section;
 +
-+static bfd_boolean
-+coff_const_type (p)
-+     PTR p ATTRIBUTE_UNUSED;
-+{
++      /* Symbol addresses are relative to section vma. */
++      csymp->symbol.value = addr - info->funcsection->vma;
++      csymp->native->u.syment.n_sclass = info->funglobal? C_EXT: C_STAT;
++      /* Create two initial line number entries.  The first one holds
++       the function symbol, the second one is the trailing record
++       that is required by coffgen.c::coff_write_native_symbol() to
++       have a line number of zero. */
++      csymp->lineno = (alent *) xmalloc (2 * sizeof (alent));
++      memset (csymp->lineno, 0, 2 * sizeof (alent));
++      info->nlnos = 2;
++      info->totlnos++;
++      csymp->lineno[0].u.sym = (asymbol *)csymp;
++      coff_record_symbol (info, csymp);
++      info->funcindex = info->nsyms - 1; /* remember for later */
++      /* Record our endndx field for later fixing. */
++      fixp = (struct coff_fix_stack *) xmalloc (sizeof (struct coff_fix_stack));
++      fixp->native = csymp->native + 1;       /* points to first AUX */
++      fixp->next = NULL;
++      if (info->fixes == NULL)
++      info->fixes = fixp;
++      else
++      {
++        for (ofp = info->fixes; ofp->next != NULL;)
++          ofp = ofp->next;
++        ofp->next = fixp;
++      }
 +
-+#if COFF_DEBUG
-+  printf ("coff_const_type()\n");
-+#endif
++      csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++      if (csymp == NULL)
++      return FALSE;
 +
-+  /* const modifier is ignored by COFF */
++      csymp->symbol.name = ".bf";
++      csymp->native->u.syment.n_sclass = C_FCN;
++      csymp->native->u.syment.n_numaux = 1;
++      csymp->symbol.value = addr - info->funcsection->vma;
++      csymp->symbol.section = info->funcsection;
++      csymp->symbol.udata.p = NULL;
++      coff_record_symbol (info, csymp);
++    }
 +
-+  return TRUE;
-+}
++  if (info->funname == NULL)
++    return TRUE;
 +
-+/* Push a volatile version of a type.  */
++  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (csymp == NULL)
++    return FALSE;
 +
-+static bfd_boolean
-+coff_volatile_type (p)
-+     PTR p ATTRIBUTE_UNUSED;
-+{
++  csymp->symbol.name = ".bb";
++  csymp->native->u.syment.n_sclass = C_BLOCK;
++  csymp->native->u.syment.n_numaux = 1;
++  csymp->symbol.value = addr - info->funcsection->vma;
++  csymp->symbol.section = info->funcsection;
++  csymp->symbol.udata.p = NULL;
++  coff_record_symbol (info, csymp);
 +
-+#if COFF_DEBUG
-+  printf ("coff_volatile_type()\n");
-+#endif
++  info->flags |= COFF_FL_FIX_BB;
 +
-+  /* volatile modifier is ignored by COFF */
++  /* Output any pending function parameters, if any. */
++  if (is_start_fcn && info->nfargs)
++    {
++      for (i = 0; i < info->nfargs; i++)
++      coff_record_symbol (info, info->fargs[i]);
++
++      free (info->fargs);
++      info->fargs = NULL;
++      info->nfargs = 0;
++    }
 +
 +  return TRUE;
 +}
 +
-+/* Start outputting a struct.  */
++/* End a block.  */
 +
 +static bfd_boolean
-+coff_start_struct_type (p, tag, id, structp, size)
++coff_end_block (p, addr)
 +     PTR p;
-+     const char *tag;
-+     unsigned int id;
-+     bfd_boolean structp;
-+     unsigned int size;
++     bfd_vma addr;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst, *savedts;
-+  struct coff_struct_hash_entry *shash;
-+  char buf[20];
-+  const char *name;
++  coff_symbol_type *csymp;
++  union internal_auxent *aux;
 +
 +#if COFF_DEBUG
-+  printf ("coff_start_struct_type(%s, %d, %d, %d)\n",
-+        tag, id, structp, size);
++  printf ("coff_end_block(%#x)\n", (int)addr);
 +#endif
 +
-+  savedts = info->tstack;
-+  info->tstack = NULL;
-+
-+  coff_push_type (TS_STRUCT);
++  if (info->funname == NULL)
++    return TRUE;
 +
-+  if (tag == NULL)
-+    {
-+      sprintf(buf, ".%dfake", id);
-+      name = tst->u.ts_struct.tag.malloctag = xstrdup (buf);
-+      tst->u.ts_struct.tagismalloced = TRUE;
-+    }
-+  else
-+    name = tst->u.ts_struct.tag.fixtag = tag;
-+  tst->u.ts_struct.id = id;
-+  tst->u.ts_struct.isstruct = structp;
-+  tst->u.ts_struct.size = size;
-+  tst->u.ts_struct.savedts = savedts;
++  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (csymp == NULL)
++    return FALSE;
 +
-+  shash = coff_struct_hash_lookup (&info->structs, name, FALSE, FALSE);
-+  if (shash != NULL && shash->types != NULL)
-+    {
-+#if COFF_DEBUG
-+      printf ("new %s definition for %s\n",
-+            tst->u.ts_struct.isstruct? "struct": "union", name);
-+#endif
-+      coff_free_struct_info (shash, NULL);
-+      shash->types = NULL;
-+      shash->emitted = FALSE;
-+    }
-+  else
-+    (void)coff_struct_hash_lookup (&info->structs, name,
-+                           TRUE, tst->u.ts_struct.tagismalloced);
++  csymp->symbol.name = ".eb";
++  csymp->symbol.value = addr - info->funcsection->vma;
++  csymp->native->u.syment.n_sclass = C_BLOCK;
++  csymp->native->u.syment.n_numaux = 1;
++  csymp->symbol.udata.p = NULL;
++  csymp->symbol.section = info->funcsection;
++  aux = &((csymp->native + 1)->u.auxent);
++  aux->x_sym.x_misc.x_lnsz.x_lnno = info->lastlno;
++  coff_record_symbol (info, csymp);
++
++  info->endaddr = addr;
 +
 +  return TRUE;
 +}
 +
-+/* Add a field to a struct.  */
++/* End a function.  */
 +
 +static bfd_boolean
-+coff_struct_field (p, name, bitpos, bitsize, visibility)
++coff_end_function (p)
 +     PTR p;
-+     const char *name;
-+     bfd_vma bitpos;
-+     bfd_vma bitsize;
-+     enum debug_visibility visibility;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst, *otst;
-+  struct coff_struct_fields *fp;
-+  struct coff_struct_hash_entry *shash;
-+  struct coff_enum_hash_entry *ehash;
-+  const char *tag;
++  coff_symbol_type *csymp;
++  union internal_auxent *aux;
 +
 +#if COFF_DEBUG
-+  printf ("coff_struct_field(%s, %d, %d, %d)\n",
-+        name, (int)bitpos, (int)bitsize, (int)visibility);
++  printf ("coff_end_function()\n");
 +#endif
 +
-+  /* Find the last element on the type stack. */
-+  assert (info->tstack != NULL);
-+  for (tst = info->tstack, otst = NULL; tst->next != NULL;)
-+    {
-+      otst = tst;
-+      tst = tst->next;
-+    }
-+  if (otst != NULL)
-+    otst->next = NULL;
++  if (info->funname == NULL)
++    return TRUE;
 +
-+  if (tst->tsk != TS_STRUCT)
-+    {
-+      fprintf (stderr, "coff_struct_field() not within structure definition\n");
-+      return FALSE;
-+    }
-+  tst->u.ts_struct.fields = (struct coff_struct_fields *)
-+    xrealloc (tst->u.ts_struct.fields,
-+            ++tst->u.ts_struct.nfields * sizeof (struct coff_struct_fields));
-+  fp = tst->u.ts_struct.fields + (tst->u.ts_struct.nfields - 1);
-+  fp->name = name;
-+  fp->bitpos = bitpos;
-+  fp->bitsize = bitsize;
-+  fp->visibility = visibility;
-+  otst = fp->types = info->tstack;
-+  while (otst->next != NULL)
-+    otst = otst->next;
-+  if (otst->tsk == TS_STRUCT && otst->u.ts_struct.shash == NULL)
-+    {
-+      if (otst->u.ts_struct.tagismalloced)
-+      tag = otst->u.ts_struct.tag.malloctag;
-+      else
-+      tag = otst->u.ts_struct.tag.fixtag;
-+      shash = coff_struct_hash_lookup (&info->structs, tag, FALSE, FALSE);
-+      assert (shash != NULL);
-+      if (!shash->emitted)
-+      {
-+        if (shash->types == NULL)
-+          {
-+            shash->types = (struct coff_type_stack *)
-+              xmalloc (sizeof (struct coff_type_stack));
-+            memcpy (shash->types, otst, sizeof (struct coff_type_stack));
-+          }
-+        shash->emitted = TRUE;
-+        coff_emit_struct (info, otst, shash);
-+      }
-+    }
-+  else if (otst->tsk == TS_ENUM)
-+    {
-+      if (otst->u.ts_enum.tagismalloced)
-+      tag = otst->u.ts_enum.tag.malloctag;
-+      else
-+      tag = otst->u.ts_enum.tag.fixtag;
-+      ehash = coff_enum_hash_lookup (&info->enums, tag, TRUE, FALSE);
-+      assert (ehash != NULL);
-+      if (!ehash->emitted)
-+      {
-+        if (ehash->types == NULL)
-+          {
-+            ehash->types = (struct coff_type_stack *)
-+              xmalloc (sizeof (struct coff_type_stack));
-+            memcpy (ehash->types, otst, sizeof (struct coff_type_stack));
-+          }
-+        ehash->emitted = TRUE;
-+        coff_emit_enum (info, otst, ehash);
-+      }
-+    }
++  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (csymp == NULL)
++    return FALSE;
 +
-+  info->tstack = tst;
++  csymp->symbol.name = ".ef";
++  csymp->symbol.value = info->endaddr - info->funcsection->vma;
++  csymp->native->u.syment.n_sclass = C_FCN;
++  csymp->native->u.syment.n_numaux = 1;
++  csymp->symbol.udata.p = NULL;
++  csymp->symbol.section = info->funcsection;
++  aux = &((csymp->native + 1)->u.auxent);
++  aux->x_sym.x_misc.x_lnsz.x_lnno = info->lastlno;
++
++  coff_record_symbol (info, csymp);
++
++  csymp = (coff_symbol_type *) info->syms[info->funcindex];
++  aux = &((csymp->native + 1)->u.auxent);
++  aux->x_sym.x_misc.x_fsize = info->endaddr - csymp->symbol.value;
++
++  info->flags |= COFF_FL_FIX_ENDNDX;
++  info->funname = NULL;
 +
 +  return TRUE;
 +}
 +
-+/* Finish up a struct.  */
++/* Output a line number.  */
 +
 +static bfd_boolean
-+coff_end_struct_type (p)
++coff_lineno (p, file, lineno, addr)
 +     PTR p;
++     const char *file ATTRIBUTE_UNUSED;
++     unsigned long lineno;
++     bfd_vma addr;
 +{
 +  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst, *savedts;
++  coff_symbol_type *csymp;
++  union internal_auxent *aux;
++  long i;
 +
 +#if COFF_DEBUG
-+  printf ("coff_end_struct_type()\n");
++  printf ("coff_lineno(%s, %ld, %d)\n",
++        file, lineno, (int)addr);
 +#endif
 +
-+  /* Our struct definition should be the only type stack element by
-+     now. */
-+  assert (info->tstack != NULL);
-+  tst = info->tstack;
-+  if (tst->tsk != TS_STRUCT || tst->next != NULL)
++  /* COFF can inherently only handle line numbers inside of functions.
++     If we are not inside a function, punt. */
++  if (info->funname == NULL)
++    return TRUE;
++
++  if (info->nlnos == 2)
 +    {
-+      fprintf (stderr, "coff_struct_field() not within structure definition\n");
-+      return FALSE;
++      /* This is the first line number of this function.  Fix the line
++       number for the .bf symbol immediately following the start of
++       function.  We also have to remember the starting line number
++       of our function since all line number entries are relative to
++       it in COFF.  Since regular line numbers must always be
++       non-zero, we artificially force the function to start one
++       line earlier. */
++      csymp = (coff_symbol_type *) info->syms[info->funcindex + 1];
++      aux = &((csymp->native + 1)->u.auxent);
++      aux->x_sym.x_misc.x_lnsz.x_lnno = lineno;
++      info->funlno = lineno - 1;
 +    }
 +
-+  /* Restore saved type stack, and push our now complete struct
-+     definition on top. */
-+  savedts = tst->u.ts_struct.savedts;
-+  tst->u.ts_struct.savedts = info->tstack;
-+  info->tstack = savedts;
-+  tst->next = info->tstack;
-+  info->tstack = tst;
-+
-+  return TRUE;
-+}
-+
-+/* Start outputting a class.  */
++  if (info->flags & COFF_FL_FIX_BB)
++    {
++      /* This is the first line number after one (or more) .bb
++       symbols.  Fix them.  In order to cope with multiple blocks
++       starting at the same line number, we walk back the list of
++       symbols until we find a C_BLOCK one that had already been
++       fixed, or until we find a C_FCN symbol (presumably, the start
++       of our current function). */
++      info->flags &= ~COFF_FL_FIX_BB;
 +
-+static bfd_boolean
-+coff_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
-+     PTR p;
-+     const char *tag ATTRIBUTE_UNUSED;
-+     unsigned int id ATTRIBUTE_UNUSED;
-+     bfd_boolean structp ATTRIBUTE_UNUSED;
-+     unsigned int size ATTRIBUTE_UNUSED;
-+     bfd_boolean vptr ATTRIBUTE_UNUSED;
-+     bfd_boolean ownvptr ATTRIBUTE_UNUSED;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
++      for (i = info->nsyms - 1; i >= 0; i--)
++      {
++        csymp = (coff_symbol_type *) info->syms[i];
++        if (csymp->native->u.syment.n_sclass == C_FCN)
++          break;
++        if (csymp->native->u.syment.n_sclass == C_BLOCK)
++          {
++            aux = &((csymp->native + 1)->u.auxent);
++            if (aux->x_sym.x_misc.x_lnsz.x_lnno != 0)
++              /* already set up properly */
++              break;
++            aux->x_sym.x_misc.x_lnsz.x_lnno = lineno;
++          }
++      }
++    }
 +
-+#if COFF_DEBUG
-+  printf ("coff_start_class_type(%s, %d, %d, %d, %d, %d)\n",
-+        tag, id, structp, size, vptr, ownvptr);
-+#endif
++  csymp = (coff_symbol_type *) info->syms[info->funcindex];
++  csymp->lineno = (alent *) xrealloc (csymp->lineno,
++                                    ++info->nlnos * sizeof (alent));
++  memset (csymp->lineno + info->nlnos - 1, 0, sizeof (alent));
++  if (lineno > info->funlno)
++    csymp->lineno[info->nlnos - 2].line_number = lineno - info->funlno;
++  else
++    /* Line number unreasonable.  Can e. g. happen for a line number
++       from an include file, which we cannot process in COFF.  Just
++       set it to the first line, to avoid generating a large unsigned
++       short (~ 65000) line number. */
++    csymp->lineno[info->nlnos - 2].line_number = 1;
++  csymp->lineno[info->nlnos - 2].u.offset = addr;
 +
-+  coff_complain_unsupp (_("class"));
++  info->lastlno = lineno;
++  info->totlnos++;
 +
 +  return TRUE;
 +}
+--- binutils-2.18.orig/bfd/Makefile.am Tue Oct 23 21:44:07 2007
++++ binutils-2.18/bfd/Makefile.am      Tue Oct 23 22:41:01 2007
+@@ -208,6 +208,8 @@
+       coff-apollo.lo \
+       coff-arm.lo \
+       coff-aux.lo \
++      coff-avr.lo \
++      coff-ext-avr.lo \
+       coff-h8300.lo \
+       coff-h8500.lo \
+       coff-i386.lo \
+@@ -387,6 +389,8 @@
+       coff-apollo.c \
+       coff-arm.c \
+       coff-aux.c \
++      coff-avr.c \
++      coff-ext-avr.c \
+       coff-h8300.c \
+       coff-h8500.c \
+       coff-i386.c \
+@@ -976,13 +980,13 @@
+ bfdver.h: $(srcdir)/version.h $(srcdir)/Makefile.in
+       @echo "creating $@"
+       @bfd_version=`echo "$(VERSION)" | sed -e 's/\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\).*/\1.00\2.00\3.00\4.00\5/' -e 's/\([^\.]*\)\..*\(..\)\..*\(..\)\..*\(..\)\..*\(..\)$$/\1\2\3\4\5/'` ;\
+-      bfd_version_string="\"$(VERSION)\"" ;\
++      bfd_version_string="\"$(VERSION) + coff-avr-patch (20050630)\"" ;\
+       bfd_soversion="$(VERSION)" ;\
+       bfd_version_package="\"$(PKGVERSION)\"" ;\
+       report_bugs_to="\"$(REPORT_BUGS_TO)\"" ;\
+       if test "x$(RELEASE)" = x ; then \
+         bfd_version_date=`sed -n -e 's/.*DATE //p' < $(srcdir)/version.h` ;\
+-        bfd_version_string="\"$(VERSION).$${bfd_version_date}\"" ;\
++        bfd_version_string="\"$(VERSION).$${bfd_version_date} + coff-avr-patch (20050630)\"" ;\
+         bfd_soversion="$(VERSION).$${bfd_version_date}" ;\
+       fi ;\
+       sed -e "s,@bfd_version@,$$bfd_version," \
+@@ -1186,6 +1190,12 @@
+   coff-m68k.c $(INCDIR)/hashtab.h $(INCDIR)/coff/m68k.h \
+   $(INCDIR)/coff/internal.h libcoff.h $(INCDIR)/bfdlink.h \
+   coffcode.h coffswap.h
++coff-avr.lo: coff-avr.c $(INCDIR)/filenames.h $(INCDIR)/coff/avr.h \
++  $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
++  libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
++coff-ext-avr.lo: coff-ext-avr.c $(INCDIR)/filenames.h $(INCDIR)/coff/avr.h \
++  $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
++  libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
+ coff-h8300.lo: coff-h8300.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+   $(INCDIR)/bfdlink.h genlink.h $(INCDIR)/coff/h8300.h \
+   $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
+--- binutils-2.18.orig/bfd/Makefile.in Tue Oct 23 21:44:07 2007
++++ binutils-2.18/bfd/Makefile.in      Tue Oct 23 22:41:31 2007
+@@ -458,6 +458,8 @@
+       coff-apollo.lo \
+       coff-arm.lo \
+       coff-aux.lo \
++      coff-avr.lo \
++      coff-ext-avr.lo \
+       coff-h8300.lo \
+       coff-h8500.lo \
+       coff-i386.lo \
+@@ -637,6 +639,8 @@
+       coff-apollo.c \
+       coff-arm.c \
+       coff-aux.c \
++      coff-avr.c \
++      coff-ext-avr.c \
+       coff-h8300.c \
+       coff-h8500.c \
+       coff-i386.c \
+@@ -1556,13 +1560,13 @@
+ bfdver.h: $(srcdir)/version.h $(srcdir)/Makefile.in
+       @echo "creating $@"
+       @bfd_version=`echo "$(VERSION)" | sed -e 's/\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\)\.*\([^\.]*\).*/\1.00\2.00\3.00\4.00\5/' -e 's/\([^\.]*\)\..*\(..\)\..*\(..\)\..*\(..\)\..*\(..\)$$/\1\2\3\4\5/'` ;\
+-      bfd_version_string="\"$(VERSION)\"" ;\
++      bfd_version_string="\"$(VERSION) + coff-avr-patch (20050630)\"" ;\
+       bfd_soversion="$(VERSION)" ;\
+       bfd_version_package="\"$(PKGVERSION)\"" ;\
+       report_bugs_to="\"$(REPORT_BUGS_TO)\"" ;\
+       if test "x$(RELEASE)" = x ; then \
+         bfd_version_date=`sed -n -e 's/.*DATE //p' < $(srcdir)/version.h` ;\
+-        bfd_version_string="\"$(VERSION).$${bfd_version_date}\"" ;\
++        bfd_version_string="\"$(VERSION).$${bfd_version_date} + coff-avr-patch (20050630)\"" ;\
+         bfd_soversion="$(VERSION).$${bfd_version_date}" ;\
+       fi ;\
+       sed -e "s,@bfd_version@,$$bfd_version," \
+@@ -1766,6 +1770,12 @@
+   coff-m68k.c $(INCDIR)/hashtab.h $(INCDIR)/coff/m68k.h \
+   $(INCDIR)/coff/internal.h libcoff.h $(INCDIR)/bfdlink.h \
+   coffcode.h coffswap.h
++coff-avr.lo: coff-avr.c $(INCDIR)/filenames.h $(INCDIR)/coff/avr.h \
++  $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
++  libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
++coff-ext-avr.lo: coff-ext-avr.c $(INCDIR)/filenames.h $(INCDIR)/coff/avr.h \
++  $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
++  libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
+ coff-h8300.lo: coff-h8300.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+   $(INCDIR)/bfdlink.h genlink.h $(INCDIR)/coff/h8300.h \
+   $(INCDIR)/coff/external.h $(INCDIR)/coff/internal.h \
+--- binutils-2.18.orig/bfd/coff-avr.c  Thu Jan  1 01:00:00 1970
++++ binutils-2.18/bfd/coff-avr.c       Tue Oct 23 22:18:44 2007
+@@ -0,0 +1,613 @@
++/* BFD back-end for Atmel AVR COFF files.
++   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2003
++   Free Software Foundation, Inc.
++   Created mostly by substituting "avr" for "i860" in coff-i860.c
 +
-+/* Add a static member to the class on the type stack.  */
++This file is part of BFD, the Binary File Descriptor library.
 +
-+static bfd_boolean
-+coff_class_static_member (p, name, physname, visibility)
-+     PTR p ATTRIBUTE_UNUSED;
-+     const char *name ATTRIBUTE_UNUSED;
-+     const char *physname ATTRIBUTE_UNUSED;
-+     enum debug_visibility visibility ATTRIBUTE_UNUSED;
-+{
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2 of the License, or
++(at your option) any later version.
 +
-+#if COFF_DEBUG
-+  printf ("coff_class_static_member(%s, %s, %d)\n",
-+        name, physname, (int)visibility);
-+#endif
++This program is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
 +
-+  return TRUE;
-+}
++You should have received a copy of the GNU General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 +
-+/* Add a base class to the class on the type stack.  */
++#include "bfd.h"
++#include "sysdep.h"
++#include "libbfd.h"
 +
-+static bfd_boolean
-+coff_class_baseclass (p, bitpos, virtual, visibility)
-+     PTR p ATTRIBUTE_UNUSED;
-+     bfd_vma bitpos ATTRIBUTE_UNUSED;
-+     bfd_boolean virtual ATTRIBUTE_UNUSED;
-+     enum debug_visibility visibility ATTRIBUTE_UNUSED;
-+{
++#include "coff/avr.h"
 +
-+#if COFF_DEBUG
-+  printf ("coff_class_baseclass(%d, %d, %d)\n",
-+        (int)bitpos, virtual, (int)visibility);
-+#endif
++#include "coff/internal.h"
 +
-+  return TRUE;
-+}
++#include "libcoff.h"
 +
-+/* Start adding a method to the class on the type stack.  */
++static bfd_reloc_status_type coff_avr_reloc
++  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
++static reloc_howto_type *coff_avr_rtype_to_howto
++  PARAMS ((bfd *, asection *, struct internal_reloc *,
++         struct coff_link_hash_entry *, struct internal_syment *,
++         bfd_vma *));
++static const bfd_target * coff_avr_object_p PARAMS ((bfd *));
 +
-+static bfd_boolean
-+coff_class_start_method (p, name)
-+     PTR p ATTRIBUTE_UNUSED;
-+     const char *name ATTRIBUTE_UNUSED;
-+{
++#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
++/* The page size is a guess based on ELF.  */
 +
-+#if COFF_DEBUG
-+  printf ("coff_class_start_method(%s)\n", name);
-+#endif
++#define COFF_PAGE_SIZE 0x1000
 +
-+  return TRUE;
-+}
++/* For some reason when using avr COFF the value stored in the .text
++   section for a reference to a common symbol is the value itself plus
++   any desired offset.  Ian Taylor, Cygnus Support.  */
 +
-+/* Add a variant to the current method.  */
++/* If we are producing relocateable output, we need to do some
++   adjustments to the object file that are not done by the
++   bfd_perform_relocation function.  This function is called by every
++   reloc type to make any required adjustments.  */
 +
-+static bfd_boolean
-+coff_class_method_variant (p, physname, visibility, constp, volatilep,
-+                         voffset, contextp)
-+     PTR p ATTRIBUTE_UNUSED;
-+     const char *physname ATTRIBUTE_UNUSED;
-+     enum debug_visibility visibility ATTRIBUTE_UNUSED;
-+     bfd_boolean constp ATTRIBUTE_UNUSED;
-+     bfd_boolean volatilep ATTRIBUTE_UNUSED;
-+     bfd_vma voffset ATTRIBUTE_UNUSED;
-+     bfd_boolean contextp ATTRIBUTE_UNUSED;
++static bfd_reloc_status_type
++coff_avr_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
++               error_message)
++     bfd *abfd;
++     arelent *reloc_entry;
++     asymbol *symbol;
++     PTR data;
++     asection *input_section ATTRIBUTE_UNUSED;
++     bfd *output_bfd;
++     char **error_message ATTRIBUTE_UNUSED;
 +{
++  symvalue diff;
 +
-+#if COFF_DEBUG
-+  printf ("coff_class_method_variant(%s, %d, %d, %d, %d, %d)\n",
-+        physname, (int)visibility, constp, volatilep,
-+        (int)voffset, contextp);
-+#endif
-+
-+  return TRUE;
-+}
++  if (output_bfd == (bfd *) NULL)
++    return bfd_reloc_continue;
 +
-+/* Add a static variant to the current method.  */
++  if (bfd_is_com_section (symbol->section))
++    {
++      /* We are relocating a common symbol.  The current value in the
++       object file is ORIG + OFFSET, where ORIG is the value of the
++       common symbol as seen by the object file when it was compiled
++       (this may be zero if the symbol was undefined) and OFFSET is
++       the offset into the common symbol (normally zero, but may be
++       non-zero when referring to a field in a common structure).
++       ORIG is the negative of reloc_entry->addend, which is set by
++       the CALC_ADDEND macro below.  We want to replace the value in
++       the object file with NEW + OFFSET, where NEW is the value of
++       the common symbol which we are going to put in the final
++       object file.  NEW is symbol->value.  */
++      diff = symbol->value + reloc_entry->addend;
++    }
++  else
++    {
++      /* For some reason bfd_perform_relocation always effectively
++       ignores the addend for a COFF target when producing
++       relocateable output.  This seems to be always wrong for 860
++       COFF, so we handle the addend here instead.  */
++      diff = reloc_entry->addend;
++    }
 +
-+static bfd_boolean
-+coff_class_static_method_variant (p, physname, visibility, constp, volatilep)
-+     PTR p ATTRIBUTE_UNUSED;
-+     const char *physname ATTRIBUTE_UNUSED;
-+     enum debug_visibility visibility ATTRIBUTE_UNUSED;
-+     bfd_boolean constp ATTRIBUTE_UNUSED;
-+     bfd_boolean volatilep ATTRIBUTE_UNUSED;
-+{
++#define DOIT(x) \
++  x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
 +
-+#if COFF_DEBUG
-+  printf ("coff_class_static_method_variant(%s, %d, %d, %d)\n",
-+        physname, (int)visibility, constp, volatilep);
-+#endif
++    if (diff != 0)
++      {
++      reloc_howto_type *howto = reloc_entry->howto;
++      unsigned char *addr = (unsigned char *) data + reloc_entry->address;
 +
-+  return TRUE;
-+}
++      switch (howto->size)
++        {
++        case 0:
++          {
++            char x = bfd_get_8 (abfd, addr);
++            DOIT (x);
++            bfd_put_8 (abfd, x, addr);
++          }
++          break;
 +
-+/* Finish up a method.  */
++        case 1:
++          {
++            short x = bfd_get_16 (abfd, addr);
++            DOIT (x);
++            bfd_put_16 (abfd, (bfd_vma) x, addr);
++          }
++          break;
 +
-+static bfd_boolean
-+coff_class_end_method (p)
-+     PTR p ATTRIBUTE_UNUSED;
-+{
++        case 2:
++          {
++            long x = bfd_get_32 (abfd, addr);
++            DOIT (x);
++            bfd_put_32 (abfd, (bfd_vma) x, addr);
++          }
++          break;
 +
-+#if COFF_DEBUG
-+  printf ("coff_class_end_method()\n");
-+#endif
++        default:
++          abort ();
++        }
++      }
 +
-+  return TRUE;
++  /* Now let bfd_perform_relocation finish everything up.  */
++  return bfd_reloc_continue;
 +}
 +
-+/* Finish up a class.  */
-+
-+static bfd_boolean
-+coff_end_class_type (p)
-+     PTR p ATTRIBUTE_UNUSED;
-+{
-+
-+#if COFF_DEBUG
-+  printf ("coff_end_class_type()\n");
++#ifndef PCRELOFFSET
++#define PCRELOFFSET FALSE
 +#endif
 +
-+  return TRUE;
-+}
-+
-+/* Push a typedef which was previously defined.  */
-+
-+static bfd_boolean
-+coff_typedef_type (p, name)
-+     PTR p;
-+     const char *name;
++static reloc_howto_type howto_table[] =
 +{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_name_type_hash_entry *nthash;
-+  struct coff_type_stack *tst, *newchain, *newst, *temp;
-+
-+#if COFF_DEBUG
-+  printf ("coff_typedef_type(%s)\n", name);
-+#endif
++  EMPTY_HOWTO (0),
++  EMPTY_HOWTO (1),
++  EMPTY_HOWTO (2),
++  EMPTY_HOWTO (3),
++  EMPTY_HOWTO (4),
++  EMPTY_HOWTO (5),
++  HOWTO (R_DIR32,               /* type */
++       0,                     /* rightshift */
++       2,                     /* size (0 = byte, 1 = short, 2 = long) */
++       32,                    /* bitsize */
++       FALSE,                 /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_bitfield, /* complain_on_overflow */
++       coff_avr_reloc,       /* special_function */
++       "dir32",               /* name */
++       TRUE,                  /* partial_inplace */
++       0xffffffff,            /* src_mask */
++       0xffffffff,            /* dst_mask */
++       TRUE),                /* pcrel_offset */
++  /* {7}, */
++  HOWTO (R_IMAGEBASE,            /* type */
++       0,                     /* rightshift */
++       2,                     /* size (0 = byte, 1 = short, 2 = long) */
++       32,                    /* bitsize */
++       FALSE,                 /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_bitfield, /* complain_on_overflow */
++       coff_avr_reloc,       /* special_function */
++       "rva32",                  /* name */
++       TRUE,                  /* partial_inplace */
++       0xffffffff,            /* src_mask */
++       0xffffffff,            /* dst_mask */
++       FALSE),                /* pcrel_offset */
++  EMPTY_HOWTO (010),
++  EMPTY_HOWTO (011),
++  EMPTY_HOWTO (012),
++  EMPTY_HOWTO (013),
++  EMPTY_HOWTO (014),
++  EMPTY_HOWTO (015),
++  EMPTY_HOWTO (016),
++  HOWTO (R_RELBYTE,           /* type */
++       0,                     /* rightshift */
++       0,                     /* size (0 = byte, 1 = short, 2 = long) */
++       8,                     /* bitsize */
++       FALSE,                 /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_bitfield, /* complain_on_overflow */
++       coff_avr_reloc,        /* special_function */
++       "8",                   /* name */
++       TRUE,                  /* partial_inplace */
++       0x000000ff,            /* src_mask */
++       0x000000ff,            /* dst_mask */
++       PCRELOFFSET),          /* pcrel_offset */
++  HOWTO (R_RELWORD,           /* type */
++       0,                     /* rightshift */
++       1,                     /* size (0 = byte, 1 = short, 2 = long) */
++       16,                    /* bitsize */
++       FALSE,                 /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_bitfield, /* complain_on_overflow */
++       coff_avr_reloc,        /* special_function */
++       "16",                  /* name */
++       TRUE,                  /* partial_inplace */
++       0x0000ffff,            /* src_mask */
++       0x0000ffff,            /* dst_mask */
++       PCRELOFFSET),          /* pcrel_offset */
++  HOWTO (R_RELLONG,           /* type */
++       0,                     /* rightshift */
++       2,                     /* size (0 = byte, 1 = short, 2 = long) */
++       32,                    /* bitsize */
++       FALSE,                 /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_bitfield, /* complain_on_overflow */
++       coff_avr_reloc,        /* special_function */
++       "32",                  /* name */
++       TRUE,                  /* partial_inplace */
++       0xffffffff,            /* src_mask */
++       0xffffffff,            /* dst_mask */
++       PCRELOFFSET),          /* pcrel_offset */
++  HOWTO (R_PCRBYTE,           /* type */
++       0,                     /* rightshift */
++       0,                     /* size (0 = byte, 1 = short, 2 = long) */
++       8,                     /* bitsize */
++       TRUE,                  /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_signed, /* complain_on_overflow */
++       coff_avr_reloc,        /* special_function */
++       "DISP8",               /* name */
++       TRUE,                  /* partial_inplace */
++       0x000000ff,            /* src_mask */
++       0x000000ff,            /* dst_mask */
++       PCRELOFFSET),          /* pcrel_offset */
++  HOWTO (R_PCRWORD,           /* type */
++       0,                     /* rightshift */
++       1,                     /* size (0 = byte, 1 = short, 2 = long) */
++       16,                    /* bitsize */
++       TRUE,                  /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_signed, /* complain_on_overflow */
++       coff_avr_reloc,        /* special_function */
++       "DISP16",              /* name */
++       TRUE,                  /* partial_inplace */
++       0x0000ffff,            /* src_mask */
++       0x0000ffff,            /* dst_mask */
++       PCRELOFFSET),          /* pcrel_offset */
++  HOWTO (R_PCRLONG,           /* type */
++       0,                     /* rightshift */
++       2,                     /* size (0 = byte, 1 = short, 2 = long) */
++       32,                    /* bitsize */
++       TRUE,                  /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_signed, /* complain_on_overflow */
++       coff_avr_reloc,        /* special_function */
++       "DISP32",              /* name */
++       TRUE,                  /* partial_inplace */
++       0xffffffff,            /* src_mask */
++       0xffffffff,            /* dst_mask */
++       PCRELOFFSET)           /* pcrel_offset */
++};
 +
-+  nthash = coff_name_type_hash_lookup (&info->types, name, FALSE, FALSE);
++/* Turn a howto into a reloc  nunmber */
 +
-+  /* nthash should never be NULL, since that would imply that the
-+     generic debugging code has asked for a typedef which it has not
-+     yet defined.  */
-+  assert (nthash != NULL);
++#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
++#define BADMAG(x) AVRBADMAG(x)
++#define AVR 1                 /* Customize coffcode.h */
 +
-+  /* Just push the entire type stack snapshot we've got on top of the
-+     existing typestack.  See coff_typdef() below for how this
-+     works.  We need to copy over each element however, since anybody
-+     popping elements off the typestack is supposed to free() each of
-+     them. */
++#define RTYPE2HOWTO(cache_ptr, dst) \
++          (cache_ptr)->howto = howto_table + (dst)->r_type;
 +
-+  for (tst = nthash->types, temp = newst = newchain = NULL; tst != NULL;)
-+    {
-+      temp = newst;
-+      newst = (struct coff_type_stack *) xmalloc (sizeof (*newst));
-+      if (newchain == NULL)
-+      newchain = newst;
-+      memcpy (newst, tst, sizeof (*newst));
-+      if (temp != NULL)
-+      temp->next = newst;
++/* For AVR COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
++   library.  On some other COFF targets STYP_BSS is normally
++   STYP_NOLOAD.  */
++#define BSS_NOLOAD_IS_SHARED_LIBRARY
 +
-+      tst = tst->next;
-+    }
-+  newst->next = info->tstack;
-+  info->tstack = newchain;
++/* Compute the addend of a reloc.  If the reloc is to a common symbol,
++   the object file contains the value of the common symbol.  By the
++   time this is called, the linker may be using a different symbol
++   from a different object file with a different value.  Therefore, we
++   hack wildly to locate the original symbol from this file so that we
++   can make the correct adjustment.  This macro sets coffsym to the
++   symbol from the original file, and uses it to set the addend value
++   correctly.  If this is not a common symbol, the usual addend
++   calculation is done, except that an additional tweak is needed for
++   PC relative relocs.
++   FIXME: This macro refers to symbols and asect; these are from the
++   calling function, not the macro arguments.  */
 +
-+  return TRUE;
-+}
++#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)              \
++  {                                                           \
++    coff_symbol_type *coffsym = (coff_symbol_type *) NULL;    \
++    if (ptr && bfd_asymbol_bfd (ptr) != abfd)                 \
++      coffsym = (obj_symbols (abfd)                           \
++               + (cache_ptr->sym_ptr_ptr - symbols));         \
++    else if (ptr)                                             \
++      coffsym = coff_symbol_from (abfd, ptr);                 \
++    if (coffsym != (coff_symbol_type *) NULL                  \
++      && coffsym->native->u.syment.n_scnum == 0)              \
++      cache_ptr->addend = - coffsym->native->u.syment.n_value;        \
++    else if (ptr && bfd_asymbol_bfd (ptr) == abfd             \
++           && ptr->section != (asection *) NULL)              \
++      cache_ptr->addend = - (ptr->section->vma + ptr->value); \
++    else                                                      \
++      cache_ptr->addend = 0;                                  \
++    if (ptr && howto_table[reloc.r_type].pc_relative)         \
++      cache_ptr->addend += asect->vma;                                \
++  }
 +
-+/* Push a struct, union or class tag.  */
++/* We use the special COFF backend linker.  */
++#define coff_relocate_section _bfd_coff_generic_relocate_section
 +
-+static bfd_boolean
-+coff_tag_type (p, name, id, kind)
-+     PTR p;
-+     const char *name;
-+     unsigned int id ATTRIBUTE_UNUSED;
-+     enum debug_type_kind kind;
++static reloc_howto_type *
++coff_avr_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
++     bfd *abfd ATTRIBUTE_UNUSED;
++     asection *sec;
++     struct internal_reloc *rel;
++     struct coff_link_hash_entry *h;
++     struct internal_syment *sym;
++     bfd_vma *addendp;
 +{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst, *newchain, *newst, *temp;
-+  struct coff_struct_hash_entry *shash;
-+  struct coff_enum_hash_entry *ehash;
-+  char buf[20];
-+  bfd_boolean needcopy = FALSE;
-+  bfd_boolean isstruct = TRUE;
-+
-+#if COFF_DEBUG
-+  printf ("coff_tag_type(%s, %d, %d)\n",
-+        name, id, kind);
-+#endif
-+
-+  if (name == NULL)
-+    {
-+      sprintf(buf, ".%dfake", id);
-+      needcopy = TRUE;
-+    }
-+
-+  switch (kind)
-+    {
-+    case DEBUG_KIND_UNION:
-+    case DEBUG_KIND_UNION_CLASS:
-+      isstruct = FALSE;
-+      /* FALLTHROUGH */
-+    case DEBUG_KIND_STRUCT:
-+    case DEBUG_KIND_CLASS:
-+      shash = coff_struct_hash_lookup (&info->structs,
-+                                     name == NULL? buf: name, TRUE, needcopy);
-+      assert (shash != NULL);
-+      tst = shash->types;
-+      if (tst == NULL)
-+      {
-+        /* This is a reference to a tag that has not yet been
-+           defined (i. e., a forward reference).  Synthesize a
-+           ts_struct entry by now, and mark it for later fixup. */
-+        tst = (struct coff_type_stack *) xmalloc (sizeof *tst);
-+        memset (tst, 0, sizeof *tst);
-+        tst->tsk = TS_STRUCT;
-+        tst->u.ts_struct.isstruct = isstruct;
-+        tst->u.ts_struct.shash = shash;
-+      }
-+    docopystack:
-+      /* Just push the entire type stack snapshot we've got on top of the
-+       existing typestack.  See coff_typdef() below for how this
-+       works.  We need to copy over each element however, since anybody
-+       popping elements off the typestack is supposed to free() each of
-+       them. */
-+      for (temp = newst = newchain = NULL; tst != NULL;)
-+      {
-+        temp = newst;
-+        newst = (struct coff_type_stack *) xmalloc (sizeof (*newst));
-+        if (newchain == NULL)
-+          newchain = newst;
-+        memcpy (newst, tst, sizeof (*newst));
-+        if (temp != NULL)
-+          temp->next = newst;
 +
-+        tst = tst->next;
-+      }
-+      if (newst)
-+      {
-+        newst->next = info->tstack;
-+        info->tstack = newchain;
-+      }
-+      break;
++  reloc_howto_type *howto;
 +
-+    case DEBUG_KIND_ENUM:
-+      ehash = coff_enum_hash_lookup (&info->enums,
-+                                   name == NULL? buf: name, TRUE, needcopy);
-+      assert (ehash != NULL);
-+      tst = ehash->types;
-+      if (tst == NULL)
-+      {
-+        /* This is a reference to a tag that has not yet been
-+           defined (i. e., a forward reference).  Synthesize a
-+           ts_enum entry by now, and mark it for later fixup. */
-+        tst = (struct coff_type_stack *) xmalloc (sizeof *tst);
-+        memset (tst, 0, sizeof *tst);
-+        tst->tsk = TS_ENUM;
-+        tst->u.ts_enum.ehash = ehash;
-+      }
-+      goto docopystack;
++  howto = howto_table + rel->r_type;
 +
-+    default:
-+      fprintf (stderr, _("illegal kind %d in coff_tag_type()\n"),
-+             (int)kind);
-+      return FALSE;
++  if (howto->pc_relative)
++    *addendp += sec->vma;
++
++  if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
++    {
++      /* This is a common symbol.  The section contents include the
++       size (sym->n_value) as an addend.  The relocate_section
++       function will be adding in the final value of the symbol.  We
++       need to subtract out the current size in order to get the
++       correct result.  */
++
++      BFD_ASSERT (h != NULL);
++
++      /* I think we *do* want to bypass this.  If we don't, I have seen some data
++       parameters get the wrong relcation address.  If I link two versions
++       with and without this section bypassed and then do a binary comparison,
++       the addresses which are different can be looked up in the map.  The
++       case in which this section has been bypassed has addresses which correspond
++       to values I can find in the map.  */
++      *addendp -= sym->n_value;
 +    }
-+  return TRUE;
++
++  /* If the output symbol is common (in which case this must be a
++     relocateable link), we need to add in the final size of the
++     common symbol.  */
++  if (h != NULL && h->root.type == bfd_link_hash_common)
++    *addendp += h->root.u.c.size;
++
++  return howto;
 +}
 +
-+/* Define a typedef.  */
++#define coff_rtype_to_howto coff_avr_rtype_to_howto
 +
-+static bfd_boolean
-+coff_typdef (p, name)
-+     PTR p;
-+     const char *name;
++#ifndef bfd_pe_print_pdata
++#define bfd_pe_print_pdata    NULL
++#endif
++
++#include "coffcode.h"
++
++static const bfd_target *
++coff_avr_object_p(a)
++     bfd *a;
 +{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_name_type_hash_entry *nthash;
++  return coff_object_p (a);
++}
 +
-+#if COFF_DEBUG
-+  printf ("coff_typdef(%s)\n", name);
-+#endif
++/* Handle all the abominations of AVR COFF:
 +
-+  /* COFF cannot really handle typedefs.  While there is the option to
-+     mark a symbol using the storage class C_TPDEF (so the COFF reader
-+     will know that name), there is no way to place a reference to
-+     that typedef into the just 16 bits COFF reserves for all of its
-+     type information.  Thus, any use of the typedef must always fully
-+     dereference the typedef again.  We do this by "snapshotting" the
-+     current type stack under the name of our typedef, and later on,
-+     when BFD debugging tells us to make use of the typedef (in
-+     coff_typedef_type()), we just look it up, and push all we've got
-+     completely onto the type stack again. */
++   Generic COFF always uses the D1 slot to indicate the "most
++   important" derived type, and the D2...Dn slots for decreasing
++   importance.  E. g., a function symbol will always have its DT_FCN
++   element in D1, an array its DT_ARY (its first DT_ARY in a
++   multi-dimensional array).  In contrast, AVR COFF expects this most
++   important derived type specifier in the upmost Dn slot that is
++   allocated at all (i. e. that is != 0).
 +
-+  if (info->tstack == NULL)
-+    {
-+      fprintf (stderr, _("coff_typdef() on an empty type stack\n"));
-+      return FALSE;
-+    }
++   Generic COFF says that "Any symbol that satisfies more than one
++   condition [... for AUX entries] should have a union format in its
++   auxiliary entry."  AVR COFF uses sepearate AUX entries for multiple
++   derived types, and in some cases (like the ISFCN one), even puts
++   the most important one into the last allocated AUX entry.  We
++   join/split them here at the border as well.  Note that when
++   generating AUX entries (where we need to split them), the n_numaux
++   field must already have been set up properly (e. g. in
++   binutils/wrcoff.c) since the entry renumbering and pointerization
++   would not work otherwise.  Thus, we only split the information into
++   multiple records if n_numaux > 1.  For similar reasons, we keep
++   n_numaux > 1 on input to keep the appropriate AUX entries
++   allocated, so a symbol can be reconstructed if it is being passed
++   through one of the GNU tools.
 +
-+  nthash = coff_name_type_hash_lookup (&info->types, name, FALSE, FALSE);
-+  if (nthash != NULL)
++   Note that this adjustment is called after the symbol itself has
++   been swapped in, but before the AUX entries are swapped in.  This
++   is the only hook available that could swap (or merge) AUX entries
++   at all, so we have to operate on the external AUX entries still. */
++
++void
++avr_coff_adjust_sym_in_post (abfd, ext, in)
++     bfd *abfd;
++     PTR ext;
++     PTR in;
++{
++  struct internal_syment *dst = (struct internal_syment *)in;
++  unsigned short dt, bt, ndt;
++  dt = dst->n_type & ~N_BTMASK;
++  bt = BTYPE (dst->n_type);
++
++  /* Some AVR COFF producers seem to violate the COFF specs, and
++     produce symbols for tag names that have the C_FOO filled in
++     properly, but T_NULL as the base type value.  Patch up here,
++     since some of our generic COFF tools (in particular
++     binutils/rdcoff.c) rely on the correct data. */
++  if (bt == T_NULL)
++    switch (dst->n_sclass)
++      {
++      case C_STRTAG:
++      bt = T_STRUCT;
++      break;
++
++      case C_UNTAG:
++      bt = T_UNION;
++      break;
++
++      case C_ENTAG:
++      bt = T_ENUM;
++      break;
++      }
++
++  /* Swap the derived type slots. */
++  if (dt != 0)
 +    {
-+#if COFF_DEBUG
-+      printf ("new typedef for %s\n", name);
-+#endif
-+      coff_free_type_info (nthash, NULL);
++      ndt = 0;
++      while (dt != 0)
++      {
++        ndt = (ndt << N_TSHIFT) | (dt & (N_TMASK >> N_BTSHFT));
++        dt >>= N_TSHIFT;
++      }
++      dst->n_type = (ndt << N_BTSHFT) | bt;
 +    }
 +  else
-+    nthash = coff_name_type_hash_lookup (&info->types, name, TRUE, FALSE);
-+  if (nthash == NULL)
-+    return FALSE;
-+  nthash->types = info->tstack;
++    dst->n_type = bt;
 +
-+  /* If the typestack is "sufficiently complex", emit a C_TPDEF symbol
-+     for it.  We assume it to be sufficiently complex if there are
-+     either at least two derived types, or one derived type where the
-+     base type is not a simple scalar one. */
-+  if (!nthash->emitted
-+      && info->tstack->next != NULL
-+      && (info->tstack->next->next != NULL || info->tstack->next->tsk >= TS_ENUM))
++  /* If the derived type is function, and there is more than one AUX
++     entry, swap the first and the last AUX entry, so the most
++     interesting one will become the first.
++
++     If the fundamental type is a tagged type (struct/union/enum), try
++     to find the AUX entry describing the tagged type (the one that
++     has x_sym.x_tagndx filled in), and merge the tag index into the
++     first AUX entry.  Depending on the actual input file, there might
++     be further DT_PTR entries which we just ignore, since we could
++     not handle that information anyway. */
++  if (dst->n_numaux > 1 && dst->n_sclass != C_FILE)
 +    {
-+      struct coff_type_stack *newchain, *otst, *tst, *ntst;
-+      coff_symbol_type *csymp;
++      AUXENT caux, *auxp1, *auxp2;
++      size_t symesz;
++      unsigned int i;
 +
-+      nthash->emitted = TRUE;
++      symesz = bfd_coff_symesz (abfd);
++      i = dst->n_numaux;
 +
-+      for (tst = info->tstack, newchain = otst = NULL;
-+         tst != NULL;
-+         tst = tst->next)
++      auxp1 = (AUXENT *)((char *)ext + symesz);
++      auxp2 = (AUXENT *)((char *)ext + i * symesz);
++
++      if (ISFCN (dst->n_type)
++        || (ISPTR(dst->n_type)
++            && (bt == T_STRUCT || bt == T_UNION || bt == T_ENUM)))
 +      {
-+        ntst = (struct coff_type_stack *)
-+          xmalloc (sizeof (struct coff_type_stack));
-+        memcpy (ntst, tst, sizeof (struct coff_type_stack));
-+        if (otst == NULL)
-+          newchain = ntst;
-+        else
-+          otst->next = ntst;
-+        otst = ntst;
++        caux = *auxp2;
++        *auxp2 = *auxp1;
++        *auxp1 = caux;
 +      }
-+      info->tstack = newchain;
-+      if (!coff_make_typed_symbol (info, &csymp, TS_NONE))
-+      return FALSE;
++      else
++      caux = *auxp1;
 +
-+      csymp->symbol.name = xstrdup (name);
-+      csymp->symbol.flags = BSF_NOT_AT_END;
-+      csymp->symbol.section = bfd_com_section_ptr;
-+      csymp->native->u.syment.n_sclass = C_TPDEF;
-+      csymp->symbol.value = 0;
++      if ((ISFCN (dst->n_type) || ISARY (dst->n_type))
++        && (bt == T_STRUCT || bt == T_UNION || bt == T_ENUM))
++      {
++        while (i > 1)
++          {
++            auxp2 = (AUXENT *)((char *)ext + i * symesz);
 +
-+      coff_record_symbol (info, csymp);
++            if (auxp2->x_sym.x_tagndx[0] != 0 || auxp2->x_sym.x_tagndx[1] != 0
++                || auxp2->x_sym.x_tagndx[2] != 0 || auxp2->x_sym.x_tagndx[3] != 0)
++              {
++                memcpy (caux.x_sym.x_tagndx, auxp2->x_sym.x_tagndx,
++                        4 * sizeof (char));
++                break;
++              }
++            i--;
++          }
++        if (i > 1)
++          *auxp1 = caux;
++      }
 +    }
-+  info->tstack = NULL;
-+
-+  return TRUE;
 +}
 +
-+/* Define a tag.  */
-+
-+static bfd_boolean
-+coff_tag (p, tag)
-+     PTR p;
-+     const char *tag;
++/* When exporting an AVR COFF file, just undo all that has been done
++   above.  Again, we are called after the symbol itself has been
++   swapped out, but before the AUX entries are being written.
++   Unfortunately, we are only given a pointer to the symbol itself, so
++   we have to derive the pointer to the respective aux entries from
++   that address, which is a bit clumsy. */
++void
++avr_coff_adjust_sym_out_post (abfd, in, ext)
++     bfd *abfd;
++     PTR in;
++     PTR ext;
 +{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst = NULL;
-+  struct coff_struct_hash_entry *shash;
-+  struct coff_enum_hash_entry *ehash;
-+
++  struct internal_syment *src = (struct internal_syment *)(in);
++  struct external_syment *dst = (struct external_syment *)(ext);
++  unsigned short dt, bt, ndt;
 +
-+#if COFF_DEBUG
-+  printf ("coff_tag(%s)\n", tag);
-+#endif
++  dt = src->n_type & ~N_BTMASK;
++  bt = BTYPE (src->n_type);
 +
-+  if (info->tstack == NULL)
++  if (dt != 0)
 +    {
-+      fprintf (stderr, _("coff_tag() called on an empty typestack\n"));
-+      return FALSE;
++      ndt = 0;
++      while (dt != 0)
++      {
++        ndt = (ndt << N_TSHIFT) | (dt & (N_TMASK >> N_BTSHFT));
++        dt >>= N_TSHIFT;
++      }
++      H_PUT_16 (abfd, (ndt << N_BTSHFT) | bt, dst->e_type);
 +    }
 +
-+  switch (info->tstack->tsk)
++  if (src->n_numaux > 1 && src->n_sclass != C_FILE)
 +    {
-+    case TS_STRUCT:
-+      shash = coff_struct_hash_lookup (&info->structs, tag, FALSE, FALSE);
-+      assert (shash != NULL);
-+      shash->types = info->tstack;
-+      info->tstack = NULL;
-+      break;
++      combined_entry_type *srce, *dste;
++      char *hackp;
++      unsigned int i;
 +
-+    case TS_ENUM:
-+      ehash = coff_enum_hash_lookup (&info->enums, tag, FALSE, FALSE);
-+      if (ehash != NULL && ehash->types != NULL)
++      /* Recover the original combinend_entry_type *. */
++      hackp = (char *)in;
++      hackp -= offsetof(combined_entry_type, u.syment);
++      srce = (combined_entry_type *)hackp;
++      srce++;
++
++      /* We simply duplicate the first AUX entry as many times as
++       needed.  Since COFF itself normally uses just a single AUX
++       entry for all the information, this will work -- each COFF
++       consumer will then just pick the fields it is particularly
++       interested in.  This would not work for the AVR COFF specific
++       DT_PTR AUX entries, but we don't support them anyway. */
++      for (i = 1; i < src->n_numaux; i++)
 +      {
-+#if COFF_DEBUG
-+        printf ("new enum definition for %s\n", tag);
-+#endif
-+        coff_free_enum_info (ehash, NULL);
++        dste = srce + i;
++        *dste = *srce;
 +      }
-+      else
-+      ehash = coff_enum_hash_lookup (&info->enums, tag, TRUE, FALSE);
-+      if (ehash == NULL)
-+      return FALSE;
-+      ehash->types = info->tstack;
-+      info->tstack = NULL;
-+      break;
-+
-+    default:
-+      fprintf (stderr, _("Illegal typestack (%d) in coff_tag()\n"), tst->tsk);
-+      return FALSE;
 +    }
-+
-+  return TRUE;
 +}
 +
-+/* Define an integer constant.  */
-+
-+static bfd_boolean
-+coff_int_constant (p, name, val)
-+     PTR p;
-+     const char *name ATTRIBUTE_UNUSED;
-+     bfd_vma val ATTRIBUTE_UNUSED;
++const bfd_target
++#ifdef TARGET_SYM
++  TARGET_SYM =
++#else
++  avrcoff_vec =
++#endif
 +{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+
-+#if COFF_DEBUG
-+  printf ("coff_int_constant(%s, %d)\n", name, (int)val);
++#ifdef TARGET_NAME
++  TARGET_NAME,
++#else
++  "coff-avr",                 /* name */
 +#endif
++  bfd_target_coff_flavour,
++  BFD_ENDIAN_LITTLE,          /* data byte order is little */
++  BFD_ENDIAN_LITTLE,          /* header byte order is little */
 +
-+  coff_complain_unsupp (_("int constant"));
++  (HAS_RELOC | EXEC_P |               /* object flags */
++   HAS_LINENO | HAS_DEBUG |
++   HAS_SYMS | HAS_LOCALS | WP_TEXT),
 +
-+  return TRUE;
-+}
++  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
++  0,                          /* leading char */
++  '/',                                /* ar_pad_char */
++  15,                         /* ar_max_namelen */
 +
-+/* Define a floating point constant.  */
++  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
++     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
++     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
++  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
++     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
++     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
 +
-+static bfd_boolean
-+coff_float_constant (p, name, val)
-+     PTR p;
-+     const char *name ATTRIBUTE_UNUSED;
-+     double val ATTRIBUTE_UNUSED;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
++/* Note that we allow an object file to be treated as a core file as well.  */
++    {_bfd_dummy_target, coff_avr_object_p, /* bfd_check_format */
++       bfd_generic_archive_p, coff_avr_object_p},
++    {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
++       bfd_false},
++    {bfd_false, coff_write_object_contents, /* bfd_write_contents */
++       _bfd_write_archive_contents, bfd_false},
 +
-+#if COFF_DEBUG
-+  printf ("coff_float_constant(%s, %g)\n", name, val);
-+#endif
++     BFD_JUMP_TABLE_GENERIC (coff),
++     BFD_JUMP_TABLE_COPY (coff),
++     BFD_JUMP_TABLE_CORE (_bfd_nocore),
++     BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
++     BFD_JUMP_TABLE_SYMBOLS (coff),
++     BFD_JUMP_TABLE_RELOCS (coff),
++     BFD_JUMP_TABLE_WRITE (coff),
++     BFD_JUMP_TABLE_LINK (coff),
++     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
 +
-+  coff_complain_unsupp (_("float constant"));
++  NULL,
 +
-+  return TRUE;
-+}
++  COFF_SWAP_TABLE
++};
+--- binutils-2.18.orig/bfd/coff-ext-avr.c      Thu Jan  1 01:00:00 1970
++++ binutils-2.18/bfd/coff-ext-avr.c   Tue Oct 23 22:18:44 2007
+@@ -0,0 +1,428 @@
++/* BFD back-end for Atmel AVR "extended" COFF files.
++   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2003
++   Free Software Foundation, Inc.
++   This is mostly the same as avr-coff, except of the presence of the
++   COFF optional header.
 +
-+/* Define a typed constant.  */
++This file is part of BFD, the Binary File Descriptor library.
 +
-+static bfd_boolean
-+coff_typed_constant (p, name, val)
-+     PTR p;
-+     const char *name ATTRIBUTE_UNUSED;
-+     bfd_vma val ATTRIBUTE_UNUSED;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2 of the License, or
++(at your option) any later version.
 +
-+#if COFF_DEBUG
-+  printf ("coff_typed_constant(%s, %d)\n", name, (int)val);
-+#endif
++This program is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
 +
-+  coff_complain_unsupp (_("typed constant"));
++You should have received a copy of the GNU General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 +
-+  return TRUE;
-+}
++#include "bfd.h"
++#include "sysdep.h"
++#include "libbfd.h"
 +
-+/* Record a variable.  */
++#define AVR_EXT_COFF 1
++#include "coff/avr.h"
 +
-+static bfd_boolean
-+coff_variable (p, name, kind, val)
-+     PTR p;
-+     const char *name;
-+     enum debug_var_kind kind;
-+     bfd_vma val;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  unsigned char class;
-+  asymbol *symp = NULL;
-+  coff_symbol_type *csymp;
-+  bfd_boolean global = FALSE;
-+  flagword flags = BSF_LOCAL;
-+  bfd_vma vmadiff = 0;
++#include "coff/internal.h"
 +
-+#if COFF_DEBUG
-+  printf ("coff_variable(%s, %d, %d)\n",
-+        name, (int)kind, (int)val);
-+#endif
++#include "libcoff.h"
 +
-+  switch (kind)
-+    {
-+    default:
-+      abort ();
++static bfd_reloc_status_type coff_ext_avr_reloc
++  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
++static reloc_howto_type *coff_ext_avr_rtype_to_howto
++  PARAMS ((bfd *, asection *, struct internal_reloc *,
++         struct coff_link_hash_entry *, struct internal_syment *,
++         bfd_vma *));
++static const bfd_target * coff_ext_avr_object_p PARAMS ((bfd *));
 +
-+    case DEBUG_GLOBAL:
-+      flags = BSF_GLOBAL;
-+      global = TRUE;
-+      /* AVR COFF historically used C_EXTDEF for global variables, and
-+       C_EXT for global functions.  Since some AVR COFF consumers
-+       apparently depend on this, we mimic this behaviour as
-+       well. */
-+      class = info->flags & COFF_FL_AVR? C_EXTDEF: C_EXT;
-+      break;
++#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
++/* The page size is a guess based on ELF.  */
 +
-+    case DEBUG_STATIC:
-+    case DEBUG_LOCAL_STATIC:
-+      class = C_STAT;
-+      break;
++#define COFF_PAGE_SIZE 0x1000
 +
-+    case DEBUG_LOCAL:
-+      class = C_AUTO;
-+      break;
++/* For some reason when using avr COFF the value stored in the .text
++   section for a reference to a common symbol is the value itself plus
++   any desired offset.  Ian Taylor, Cygnus Support.  */
 +
-+    case DEBUG_REGISTER:
-+      class = C_REG;
-+      break;
-+    }
++/* If we are producing relocateable output, we need to do some
++   adjustments to the object file that are not done by the
++   bfd_perform_relocation function.  This function is called by every
++   reloc type to make any required adjustments.  */
++
++static bfd_reloc_status_type
++coff_ext_avr_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
++               error_message)
++     bfd *abfd;
++     arelent *reloc_entry;
++     asymbol *symbol;
++     PTR data;
++     asection *input_section ATTRIBUTE_UNUSED;
++     bfd *output_bfd;
++     char **error_message ATTRIBUTE_UNUSED;
++{
++  symvalue diff;
 +
-+  if (!coff_make_typed_symbol (info, &csymp, TS_NONE))
-+    return FALSE;
++  if (output_bfd == (bfd *) NULL)
++    return bfd_reloc_continue;
 +
-+  if (class == C_REG && (info->flags & COFF_FL_AVR) != 0)
++  if (bfd_is_com_section (symbol->section))
 +    {
-+      struct coff_private_symdata *priv = (struct coff_private_symdata *)
-+      csymp->symbol.udata.p;
-+      val = coff_fixup_avr_register (val, priv->size * 8);
++      /* We are relocating a common symbol.  The current value in the
++       object file is ORIG + OFFSET, where ORIG is the value of the
++       common symbol as seen by the object file when it was compiled
++       (this may be zero if the symbol was undefined) and OFFSET is
++       the offset into the common symbol (normally zero, but may be
++       non-zero when referring to a field in a common structure).
++       ORIG is the negative of reloc_entry->addend, which is set by
++       the CALC_ADDEND macro below.  We want to replace the value in
++       the object file with NEW + OFFSET, where NEW is the value of
++       the common symbol which we are going to put in the final
++       object file.  NEW is symbol->value.  */
++      diff = symbol->value + reloc_entry->addend;
 +    }
-+
-+  csymp->symbol.name = name;
-+  csymp->symbol.flags = flags;        /* Note: this clears BSF_DEBUGGING. */
-+
-+  /* Match the debugging symbol against the input symtab symbols.  If
-+     we found one, use the section information from it.  Otherwise, we
-+     are lost here and just use the absolute section that was
-+     predeclared by coff_bfd_make_debug_symbol().  C_REG and C_AUTO
-+     symbols (which we do not attempt to lookup in the symtab symbols
-+     at all) go into the ABS section anyway. */
-+  if (class != C_REG && class != C_AUTO)
++  else
 +    {
-+      symp = coff_find_symbol (info, name, FALSE, global);
-+      if (symp)
-+      {
-+        csymp->symbol.section = symp->section;
-+        vmadiff = symp->section->vma;
-+      }
++      /* For some reason bfd_perform_relocation always effectively
++       ignores the addend for a COFF target when producing
++       relocateable output.  This seems to be always wrong for 860
++       COFF, so we handle the addend here instead.  */
++      diff = reloc_entry->addend;
 +    }
 +
-+  /* Symbols are relative to section vma. */
-+  csymp->symbol.value = val - vmadiff;
-+  csymp->native->u.syment.n_sclass = class;
-+  coff_record_symbol (info, csymp);
-+
-+  return TRUE;
-+}
-+
-+/* Start outputting a function.  */
++#define DOIT(x) \
++  x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
 +
-+static bfd_boolean
-+coff_start_function (p, name, globalp)
-+     PTR p;
-+     const char *name;
-+     bfd_boolean globalp;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst, *savedts;
++    if (diff != 0)
++      {
++      reloc_howto_type *howto = reloc_entry->howto;
++      unsigned char *addr = (unsigned char *) data + reloc_entry->address;
 +
-+#if COFF_DEBUG
-+  printf ("coff_start_function(%s, %d)\n",
-+        name, globalp);
-+#endif
++      switch (howto->size)
++        {
++        case 0:
++          {
++            char x = bfd_get_8 (abfd, addr);
++            DOIT (x);
++            bfd_put_8 (abfd, x, addr);
++          }
++          break;
 +
-+  savedts = info->tstack;
-+  info->tstack = NULL;
++        case 1:
++          {
++            short x = bfd_get_16 (abfd, addr);
++            DOIT (x);
++            bfd_put_16 (abfd, (bfd_vma) x, addr);
++          }
++          break;
 +
-+  coff_push_type (TS_FUNC);
++        case 2:
++          {
++            long x = bfd_get_32 (abfd, addr);
++            DOIT (x);
++            bfd_put_32 (abfd, (bfd_vma) x, addr);
++          }
++          break;
 +
-+  if (info->funname != NULL)
-+    {
-+      fprintf (stderr,
-+             _("coff_start_function() called twice, pending %s, new %s\n"),
-+             info->funname, name);
-+      return FALSE;
-+    }
-+  info->funname = name;
-+  info->funglobal = globalp;
-+  info->flags |= COFF_FL_START_FCN;
-+  tst->u.ts_func.savedts = savedts;
++        default:
++          abort ();
++        }
++      }
 +
-+  return TRUE;
++  /* Now let bfd_perform_relocation finish everything up.  */
++  return bfd_reloc_continue;
 +}
 +
-+/* Output a function parameter.  */
-+
-+static bfd_boolean
-+coff_function_parameter (p, name, kind, val)
-+     PTR p;
-+     const char *name;
-+     enum debug_parm_kind kind;
-+     bfd_vma val;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  coff_symbol_type *csymp;
-+  unsigned char class;
-+
-+#if COFF_DEBUG
-+  printf ("coff_function_parameter(%s, %d, %d)\n",
-+        name, (int)kind, (int)val);
++#ifndef PCRELOFFSET
++#define PCRELOFFSET FALSE
 +#endif
 +
-+  switch (kind)
-+    {
-+    default:
-+      abort ();
-+
-+    case DEBUG_PARM_STACK:
-+      class = C_ARG;
-+      break;
-+
-+    case DEBUG_PARM_REG:
-+      class = C_REGPARM;
-+      break;
++static reloc_howto_type howto_table[] =
++{
++  EMPTY_HOWTO (0),
++  EMPTY_HOWTO (1),
++  EMPTY_HOWTO (2),
++  EMPTY_HOWTO (3),
++  EMPTY_HOWTO (4),
++  EMPTY_HOWTO (5),
++  HOWTO (R_DIR32,               /* type */
++       0,                     /* rightshift */
++       2,                     /* size (0 = byte, 1 = short, 2 = long) */
++       32,                    /* bitsize */
++       FALSE,                 /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_bitfield, /* complain_on_overflow */
++       coff_ext_avr_reloc,       /* special_function */
++       "dir32",               /* name */
++       TRUE,                  /* partial_inplace */
++       0xffffffff,            /* src_mask */
++       0xffffffff,            /* dst_mask */
++       TRUE),                /* pcrel_offset */
++  /* {7}, */
++  HOWTO (R_IMAGEBASE,            /* type */
++       0,                     /* rightshift */
++       2,                     /* size (0 = byte, 1 = short, 2 = long) */
++       32,                    /* bitsize */
++       FALSE,                 /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_bitfield, /* complain_on_overflow */
++       coff_ext_avr_reloc,       /* special_function */
++       "rva32",                  /* name */
++       TRUE,                  /* partial_inplace */
++       0xffffffff,            /* src_mask */
++       0xffffffff,            /* dst_mask */
++       FALSE),                /* pcrel_offset */
++  EMPTY_HOWTO (010),
++  EMPTY_HOWTO (011),
++  EMPTY_HOWTO (012),
++  EMPTY_HOWTO (013),
++  EMPTY_HOWTO (014),
++  EMPTY_HOWTO (015),
++  EMPTY_HOWTO (016),
++  HOWTO (R_RELBYTE,           /* type */
++       0,                     /* rightshift */
++       0,                     /* size (0 = byte, 1 = short, 2 = long) */
++       8,                     /* bitsize */
++       FALSE,                 /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_bitfield, /* complain_on_overflow */
++       coff_ext_avr_reloc,    /* special_function */
++       "8",                   /* name */
++       TRUE,                  /* partial_inplace */
++       0x000000ff,            /* src_mask */
++       0x000000ff,            /* dst_mask */
++       PCRELOFFSET),          /* pcrel_offset */
++  HOWTO (R_RELWORD,           /* type */
++       0,                     /* rightshift */
++       1,                     /* size (0 = byte, 1 = short, 2 = long) */
++       16,                    /* bitsize */
++       FALSE,                 /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_bitfield, /* complain_on_overflow */
++       coff_ext_avr_reloc,    /* special_function */
++       "16",                  /* name */
++       TRUE,                  /* partial_inplace */
++       0x0000ffff,            /* src_mask */
++       0x0000ffff,            /* dst_mask */
++       PCRELOFFSET),          /* pcrel_offset */
++  HOWTO (R_RELLONG,           /* type */
++       0,                     /* rightshift */
++       2,                     /* size (0 = byte, 1 = short, 2 = long) */
++       32,                    /* bitsize */
++       FALSE,                 /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_bitfield, /* complain_on_overflow */
++       coff_ext_avr_reloc,    /* special_function */
++       "32",                  /* name */
++       TRUE,                  /* partial_inplace */
++       0xffffffff,            /* src_mask */
++       0xffffffff,            /* dst_mask */
++       PCRELOFFSET),          /* pcrel_offset */
++  HOWTO (R_PCRBYTE,           /* type */
++       0,                     /* rightshift */
++       0,                     /* size (0 = byte, 1 = short, 2 = long) */
++       8,                     /* bitsize */
++       TRUE,                  /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_signed, /* complain_on_overflow */
++       coff_ext_avr_reloc,    /* special_function */
++       "DISP8",               /* name */
++       TRUE,                  /* partial_inplace */
++       0x000000ff,            /* src_mask */
++       0x000000ff,            /* dst_mask */
++       PCRELOFFSET),          /* pcrel_offset */
++  HOWTO (R_PCRWORD,           /* type */
++       0,                     /* rightshift */
++       1,                     /* size (0 = byte, 1 = short, 2 = long) */
++       16,                    /* bitsize */
++       TRUE,                  /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_signed, /* complain_on_overflow */
++       coff_ext_avr_reloc,    /* special_function */
++       "DISP16",              /* name */
++       TRUE,                  /* partial_inplace */
++       0x0000ffff,            /* src_mask */
++       0x0000ffff,            /* dst_mask */
++       PCRELOFFSET),          /* pcrel_offset */
++  HOWTO (R_PCRLONG,           /* type */
++       0,                     /* rightshift */
++       2,                     /* size (0 = byte, 1 = short, 2 = long) */
++       32,                    /* bitsize */
++       TRUE,                  /* pc_relative */
++       0,                     /* bitpos */
++       complain_overflow_signed, /* complain_on_overflow */
++       coff_ext_avr_reloc,    /* special_function */
++       "DISP32",              /* name */
++       TRUE,                  /* partial_inplace */
++       0xffffffff,            /* src_mask */
++       0xffffffff,            /* dst_mask */
++       PCRELOFFSET)           /* pcrel_offset */
++};
 +
-+    case DEBUG_PARM_REFERENCE:
-+    case DEBUG_PARM_REF_REG:
-+      fprintf (stderr, _("Reference parameters not available in COFF\n"));
-+      return TRUE;
-+    }
++/* Turn a howto into a reloc  nunmber */
 +
-+  if (!coff_make_typed_symbol (info, &csymp, TS_FUNC))
-+    return FALSE;
++#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
++#define BADMAG(x) AVRBADMAG(x)
++#define AVR 1                 /* Customize coffcode.h */
 +
-+  if (class == C_REGPARM && (info->flags & COFF_FL_AVR) != 0)
-+    {
-+      struct coff_private_symdata *priv = (struct coff_private_symdata *)
-+      csymp->symbol.udata.p;
-+      val = coff_fixup_avr_register (val, priv->size * 8);
-+    }
++#define RTYPE2HOWTO(cache_ptr, dst) \
++          (cache_ptr)->howto = howto_table + (dst)->r_type;
 +
-+  csymp->symbol.name = name;
-+  csymp->symbol.value = val;
-+  csymp->symbol.flags |= BSF_LOCAL;
-+  csymp->native->u.syment.n_sclass = class;
++/* For AVR COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
++   library.  On some other COFF targets STYP_BSS is normally
++   STYP_NOLOAD.  */
++#define BSS_NOLOAD_IS_SHARED_LIBRARY
 +
-+  /* Since function parameters precede the actual function definition,
-+     defer their output until the function has been created. */
-+  info->fargs = (coff_symbol_type **)
-+    xrealloc (info->fargs, ++info->nfargs * sizeof (coff_symbol_type *));
-+  info->fargs[info->nfargs - 1] = csymp;
++/* Compute the addend of a reloc.  If the reloc is to a common symbol,
++   the object file contains the value of the common symbol.  By the
++   time this is called, the linker may be using a different symbol
++   from a different object file with a different value.  Therefore, we
++   hack wildly to locate the original symbol from this file so that we
++   can make the correct adjustment.  This macro sets coffsym to the
++   symbol from the original file, and uses it to set the addend value
++   correctly.  If this is not a common symbol, the usual addend
++   calculation is done, except that an additional tweak is needed for
++   PC relative relocs.
++   FIXME: This macro refers to symbols and asect; these are from the
++   calling function, not the macro arguments.  */
 +
-+  return TRUE;
-+}
++#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)              \
++  {                                                           \
++    coff_symbol_type *coffsym = (coff_symbol_type *) NULL;    \
++    if (ptr && bfd_asymbol_bfd (ptr) != abfd)                 \
++      coffsym = (obj_symbols (abfd)                           \
++               + (cache_ptr->sym_ptr_ptr - symbols));         \
++    else if (ptr)                                             \
++      coffsym = coff_symbol_from (abfd, ptr);                 \
++    if (coffsym != (coff_symbol_type *) NULL                  \
++      && coffsym->native->u.syment.n_scnum == 0)              \
++      cache_ptr->addend = - coffsym->native->u.syment.n_value;        \
++    else if (ptr && bfd_asymbol_bfd (ptr) == abfd             \
++           && ptr->section != (asection *) NULL)              \
++      cache_ptr->addend = - (ptr->section->vma + ptr->value); \
++    else                                                      \
++      cache_ptr->addend = 0;                                  \
++    if (ptr && howto_table[reloc.r_type].pc_relative)         \
++      cache_ptr->addend += asect->vma;                                \
++  }
 +
-+/* Start a block.  */
++/* We use the special COFF backend linker.  */
++#define coff_relocate_section _bfd_coff_generic_relocate_section
 +
-+static bfd_boolean
-+coff_start_block (p, addr)
-+     PTR p;
-+     bfd_vma addr;
++static reloc_howto_type *
++coff_ext_avr_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
++     bfd *abfd ATTRIBUTE_UNUSED;
++     asection *sec;
++     struct internal_reloc *rel;
++     struct coff_link_hash_entry *h;
++     struct internal_syment *sym;
++     bfd_vma *addendp;
 +{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  struct coff_type_stack *tst, *otst;
-+  struct coff_fix_stack *fixp, *ofp;
-+  asymbol *symp;
-+  coff_symbol_type *csymp;
-+  unsigned int i;
-+  bfd_boolean is_start_fcn;
-+
-+#if COFF_DEBUG
-+  printf ("coff_start_block(%#x)\n", (int)addr);
-+#endif
-+
-+  is_start_fcn = info->flags & COFF_FL_START_FCN;
-+
-+  if (is_start_fcn)
-+    {
-+      /* This is the starting block of a function.  We are going to
-+         write three symbols here, one for the function itself, one
-+         ".bf" symbol to indicate the begin of the function, and
-+         finally one ".bb" for the first block inside the function. */
-+      info->flags &= ~COFF_FL_START_FCN;
-+
-+      /* Our function definition should be the only type stack element
-+       by now. */
-+      assert (info->tstack != NULL);
-+      tst = info->tstack;
-+      if (tst->tsk != TS_FUNC || tst->next != NULL)
-+      {
-+        fprintf (stderr,
-+                 _("coff_start_block() not within function definition\n"));
-+        return FALSE;
-+      }
-+
-+      /* Restore saved type stack, and push our now complete function
-+       definition on top. */
-+      info->tstack = tst->u.ts_func.savedts;
-+      tst->next = info->tstack;
-+      info->tstack = tst;
-+
-+      if (info->currentfile == NULL)
-+      {
-+        fprintf (stderr,
-+                 _("Warning: ignoring function %s() outside any compilation unit\n"),
-+                 info->funname);
-+        for (tst = info->tstack, otst = NULL; tst != NULL;)
-+          {
-+            otst = tst;
-+            tst = otst->next;
-+            if (otst->tsk == TS_ENUM &&
-+                otst->u.ts_enum.tagismalloced)
-+              free (otst->u.ts_enum.tag.malloctag);
-+            else if (otst->tsk == TS_STRUCT &&
-+                     otst->u.ts_struct.tagismalloced)
-+              free (otst->u.ts_struct.tag.malloctag);
-+            free (otst);
-+          }
-+        info->tstack = NULL;
-+        info->funname = NULL;
-+
-+        return TRUE;
-+      }
-+
-+      if (!coff_make_typed_symbol (info, &csymp, TS_NONE))
-+      return FALSE;
-+
-+      csymp->symbol.name = info->funname;
-+      csymp->symbol.flags = BSF_FUNCTION |
-+      (info->funglobal? BSF_GLOBAL: BSF_LOCAL);
-+      symp = coff_find_symbol (info, info->funname, TRUE, info->funglobal);
-+      if (symp == NULL)
-+      {
-+        fprintf (stderr,
-+                 _("function %s not found in symbol table, defaulting to \"text\" section\n"),
-+                 info->funname);
-+        csymp->symbol.section = info->funcsection = info->textsect;
-+      }
-+      else
-+      csymp->symbol.section = info->funcsection = symp->section;
-+
-+      /* Symbol addresses are relative to section vma. */
-+      csymp->symbol.value = addr - info->funcsection->vma;
-+      csymp->native->u.syment.n_sclass = info->funglobal? C_EXT: C_STAT;
-+      /* Create two initial line number entries.  The first one holds
-+       the function symbol, the second one is the trailing record
-+       that is required by coffgen.c::coff_write_native_symbol() to
-+       have a line number of zero. */
-+      csymp->lineno = (alent *) xmalloc (2 * sizeof (alent));
-+      memset (csymp->lineno, 0, 2 * sizeof (alent));
-+      info->nlnos = 2;
-+      info->totlnos++;
-+      csymp->lineno[0].u.sym = (asymbol *)csymp;
-+      coff_record_symbol (info, csymp);
-+      info->funcindex = info->nsyms - 1; /* remember for later */
-+      /* Record our endndx field for later fixing. */
-+      fixp = (struct coff_fix_stack *) xmalloc (sizeof (struct coff_fix_stack));
-+      fixp->native = csymp->native + 1;       /* points to first AUX */
-+      fixp->next = NULL;
-+      if (info->fixes == NULL)
-+      info->fixes = fixp;
-+      else
-+      {
-+        for (ofp = info->fixes; ofp->next != NULL;)
-+          ofp = ofp->next;
-+        ofp->next = fixp;
-+      }
-+
-+      csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+      if (csymp == NULL)
-+      return FALSE;
-+
-+      csymp->symbol.name = ".bf";
-+      csymp->native->u.syment.n_sclass = C_FCN;
-+      csymp->native->u.syment.n_numaux = 1;
-+      csymp->symbol.value = addr - info->funcsection->vma;
-+      csymp->symbol.section = info->funcsection;
-+      csymp->symbol.udata.p = NULL;
-+      coff_record_symbol (info, csymp);
-+    }
-+
-+  if (info->funname == NULL)
-+    return TRUE;
 +
-+  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+  if (csymp == NULL)
-+    return FALSE;
++  reloc_howto_type *howto;
 +
-+  csymp->symbol.name = ".bb";
-+  csymp->native->u.syment.n_sclass = C_BLOCK;
-+  csymp->native->u.syment.n_numaux = 1;
-+  csymp->symbol.value = addr - info->funcsection->vma;
-+  csymp->symbol.section = info->funcsection;
-+  csymp->symbol.udata.p = NULL;
-+  coff_record_symbol (info, csymp);
++  howto = howto_table + rel->r_type;
 +
-+  info->flags |= COFF_FL_FIX_BB;
++  if (howto->pc_relative)
++    *addendp += sec->vma;
 +
-+  /* Output any pending function parameters, if any. */
-+  if (is_start_fcn && info->nfargs)
++  if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
 +    {
-+      for (i = 0; i < info->nfargs; i++)
-+      coff_record_symbol (info, info->fargs[i]);
-+
-+      free (info->fargs);
-+      info->fargs = NULL;
-+      info->nfargs = 0;
-+    }
-+
-+  return TRUE;
-+}
-+
-+/* End a block.  */
-+
-+static bfd_boolean
-+coff_end_block (p, addr)
-+     PTR p;
-+     bfd_vma addr;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  coff_symbol_type *csymp;
-+  union internal_auxent *aux;
++      /* This is a common symbol.  The section contents include the
++       size (sym->n_value) as an addend.  The relocate_section
++       function will be adding in the final value of the symbol.  We
++       need to subtract out the current size in order to get the
++       correct result.  */
 +
-+#if COFF_DEBUG
-+  printf ("coff_end_block(%#x)\n", (int)addr);
-+#endif
++      BFD_ASSERT (h != NULL);
 +
-+  if (info->funname == NULL)
-+    return TRUE;
++      /* I think we *do* want to bypass this.  If we don't, I have seen some data
++       parameters get the wrong relcation address.  If I link two versions
++       with and without this section bypassed and then do a binary comparison,
++       the addresses which are different can be looked up in the map.  The
++       case in which this section has been bypassed has addresses which correspond
++       to values I can find in the map.  */
++      *addendp -= sym->n_value;
++    }
 +
-+  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+  if (csymp == NULL)
-+    return FALSE;
++  /* If the output symbol is common (in which case this must be a
++     relocateable link), we need to add in the final size of the
++     common symbol.  */
++  if (h != NULL && h->root.type == bfd_link_hash_common)
++    *addendp += h->root.u.c.size;
 +
-+  csymp->symbol.name = ".eb";
-+  csymp->symbol.value = addr - info->funcsection->vma;
-+  csymp->native->u.syment.n_sclass = C_BLOCK;
-+  csymp->native->u.syment.n_numaux = 1;
-+  csymp->symbol.udata.p = NULL;
-+  csymp->symbol.section = info->funcsection;
-+  aux = &((csymp->native + 1)->u.auxent);
-+  aux->x_sym.x_misc.x_lnsz.x_lnno = info->lastlno;
-+  coff_record_symbol (info, csymp);
++  return howto;
++}
 +
-+  info->endaddr = addr;
++#define coff_rtype_to_howto coff_ext_avr_rtype_to_howto
 +
-+  return TRUE;
-+}
++#ifndef bfd_pe_print_pdata
++#define bfd_pe_print_pdata    NULL
++#endif
 +
-+/* End a function.  */
++#include "coffcode.h"
 +
-+static bfd_boolean
-+coff_end_function (p)
-+     PTR p;
++static const bfd_target *
++coff_ext_avr_object_p(a)
++     bfd *a;
 +{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  coff_symbol_type *csymp;
-+  union internal_auxent *aux;
++  return coff_object_p (a);
++}
 +
-+#if COFF_DEBUG
-+  printf ("coff_end_function()\n");
++const bfd_target
++#ifdef TARGET_SYM
++  TARGET_SYM =
++#else
++  avrextcoff_vec =
++#endif
++{
++#ifdef TARGET_NAME
++  TARGET_NAME,
++#else
++  "coff-ext-avr",                     /* name */
 +#endif
++  bfd_target_coff_flavour,
++  BFD_ENDIAN_LITTLE,          /* data byte order is little */
++  BFD_ENDIAN_LITTLE,          /* header byte order is little */
 +
-+  if (info->funname == NULL)
-+    return TRUE;
++  (HAS_RELOC | EXEC_P |               /* object flags */
++   HAS_LINENO | HAS_DEBUG |
++   HAS_SYMS | HAS_LOCALS | WP_TEXT),
 +
-+  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
-+  if (csymp == NULL)
-+    return FALSE;
++  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
++  0,                          /* leading char */
++  '/',                                /* ar_pad_char */
++  15,                         /* ar_max_namelen */
 +
-+  csymp->symbol.name = ".ef";
-+  csymp->symbol.value = info->endaddr - info->funcsection->vma;
-+  csymp->native->u.syment.n_sclass = C_FCN;
-+  csymp->native->u.syment.n_numaux = 1;
-+  csymp->symbol.udata.p = NULL;
-+  csymp->symbol.section = info->funcsection;
-+  aux = &((csymp->native + 1)->u.auxent);
-+  aux->x_sym.x_misc.x_lnsz.x_lnno = info->lastlno;
++  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
++     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
++     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
++  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
++     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
++     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
 +
-+  coff_record_symbol (info, csymp);
++/* Note that we allow an object file to be treated as a core file as well.  */
++    {_bfd_dummy_target, coff_ext_avr_object_p, /* bfd_check_format */
++       bfd_generic_archive_p, coff_ext_avr_object_p},
++    {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
++       bfd_false},
++    {bfd_false, coff_write_object_contents, /* bfd_write_contents */
++       _bfd_write_archive_contents, bfd_false},
 +
-+  csymp = (coff_symbol_type *) info->syms[info->funcindex];
-+  aux = &((csymp->native + 1)->u.auxent);
-+  aux->x_sym.x_misc.x_fsize = info->endaddr - csymp->symbol.value;
++     BFD_JUMP_TABLE_GENERIC (coff),
++     BFD_JUMP_TABLE_COPY (coff),
++     BFD_JUMP_TABLE_CORE (_bfd_nocore),
++     BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
++     BFD_JUMP_TABLE_SYMBOLS (coff),
++     BFD_JUMP_TABLE_RELOCS (coff),
++     BFD_JUMP_TABLE_WRITE (coff),
++     BFD_JUMP_TABLE_LINK (coff),
++     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
 +
-+  info->flags |= COFF_FL_FIX_ENDNDX;
-+  info->funname = NULL;
++  NULL,
 +
-+  return TRUE;
-+}
++  COFF_SWAP_TABLE
++};
+--- binutils-2.18.orig/bfd/coffcode.h  Tue Oct 23 21:44:07 2007
++++ binutils-2.18/bfd/coffcode.h       Tue Oct 23 22:18:44 2007
+@@ -1,3 +1,4 @@
 +
-+/* Output a line number.  */
+ /* Support for the generic parts of most COFF variants, for BFD.
+    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+@@ -1769,6 +1770,17 @@
+   coff->relocbase = 0;
+   coff->local_toc_sym_map = 0;
++  /* These members communicate important constants about the symbol
++     table to GDB's symbol-reading code.  These `constants'
++     unfortunately vary among coff implementations...  */
++  coff->local_n_btmask = N_BTMASK;
++  coff->local_n_btshft = N_BTSHFT;
++  coff->local_n_tmask = N_TMASK;
++  coff->local_n_tshift = N_TSHIFT;
++  coff->local_symesz = bfd_coff_symesz (abfd);
++  coff->local_auxesz = bfd_coff_auxesz (abfd);
++  coff->local_linesz = bfd_coff_linesz (abfd);
 +
-+static bfd_boolean
-+coff_lineno (p, file, lineno, addr)
-+     PTR p;
-+     const char *file ATTRIBUTE_UNUSED;
-+     unsigned long lineno;
-+     bfd_vma addr;
-+{
-+  struct coff_write_handle *info = (struct coff_write_handle *) p;
-+  coff_symbol_type *csymp;
-+  union internal_auxent *aux;
-+  long i;
+ /*  make_abs_section(abfd);*/
+   return TRUE;
+@@ -1793,17 +1805,6 @@
+   coff->sym_filepos = internal_f->f_symptr;
+-  /* These members communicate important constants about the symbol
+-     table to GDB's symbol-reading code.  These `constants'
+-     unfortunately vary among coff implementations...  */
+-  coff->local_n_btmask = N_BTMASK;
+-  coff->local_n_btshft = N_BTSHFT;
+-  coff->local_n_tmask = N_TMASK;
+-  coff->local_n_tshift = N_TSHIFT;
+-  coff->local_symesz = bfd_coff_symesz (abfd);
+-  coff->local_auxesz = bfd_coff_auxesz (abfd);
+-  coff->local_linesz = bfd_coff_linesz (abfd);
+-
+   coff->timestamp = internal_f->f_timdat;
+   obj_raw_syment_count (abfd) =
+@@ -1930,6 +1931,11 @@
+       }
+       break;
+ #endif
++#ifdef AVRMAGIC
++    case AVRMAGIC:
++      arch = bfd_arch_avr;
++      break;
++#endif
+ #ifdef MC68MAGIC
+     case MC68MAGIC:
+     case M68MAGIC:
+@@ -2726,6 +2732,13 @@
+       return TRUE;
+ #endif
++#ifdef AVRMAGIC
++    case bfd_arch_avr:
++      *magicp = AVRMAGIC;
++      return TRUE;
++      break;
++#endif
 +
-+#if COFF_DEBUG
-+  printf ("coff_lineno(%s, %ld, %d)\n",
-+        file, lineno, (int)addr);
+ #ifdef PPCMAGIC
+     case bfd_arch_powerpc:
+       *magicp = PPCMAGIC;
+@@ -3522,6 +3535,11 @@
+       section.s_page = coff_get_section_load_page (current);
+ #endif
++#ifdef AVR
++      /* AVR uses s_paddr the way GNU uses s_vaddr, and effectively
++       ignores s_vaddr. */
++      section.s_paddr = current->vma;
++#endif
+ #ifdef COFF_WITH_PE
+       section.s_paddr = 0;
+ #endif
+@@ -3866,6 +3884,17 @@
+     internal_a.magic = ZMAGIC;
+ #endif
++#ifdef AVR
++    /* a.out is a dummy for non-extended COFF */
++    internal_a.magic = AVRAOUTMAGIC;
++    /* Upper nibble of f_flags must be set for historical reasons.
++       The upper byte remains blank on coff-avr, so undo the F_AR32WR
++       setting performed above. */
++    internal_f.f_flags |= F_JUNK;
++    internal_f.f_flags &= ~F_UNUSED;
++#define __A_MAGIC_SET__
++#endif /* AVR */
++
+ #if defined(PPC_PE)
+ #define __A_MAGIC_SET__
+     internal_a.magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
+@@ -3933,8 +3962,16 @@
+ #endif
+   }
++#ifdef AVR_EXT_COFF
++    /* Note that we do not set F_PTRINFO because the GNU toolchain
++       doesn't provide any information about the target of a pointer,
++       so we cannot derive which section our pointer target would be
++       in. */
++  internal_a.vstamp = F_FULLPATHS | F_STRUCTINFO;
++#else
+   /* FIXME: Does anybody ever set this to another value?  */
+   internal_a.vstamp = 0;
++#endif
+   /* Now should write relocs, strings, syms.  */
+   obj_sym_filepos (abfd) = sym_base;
+@@ -4120,22 +4157,29 @@
+       char * buff;
+       bfd_size_type amount = bfd_coff_aoutsz (abfd);
+-      buff = bfd_malloc (amount);
+-      if (buff == NULL)
+-      return FALSE;
++      /* Do not attempt to malloc() zero bytes.  According to the
++         C standard, the behaviour is implementation-defined, and
++       malloc() might return NULL in that case, which would confuse
++       us to assume an error where it actually isn't. */
++      if (amount != 0)
++      {
++        buff = bfd_malloc (amount);
++        if (buff == NULL)
++          return FALSE;
+-      coff_swap_aouthdr_out (abfd, & internal_a, buff);
+-      amount = bfd_bwrite (buff, amount, abfd);
++        coff_swap_aouthdr_out (abfd, & internal_a, buff);
++        amount = bfd_bwrite (buff, amount, abfd);
+-      free (buff);
++        free (buff);
+-      if (amount != bfd_coff_aoutsz (abfd))
+-      return FALSE;
++        if (amount != bfd_coff_aoutsz (abfd))
++          return FALSE;
+ #ifdef COFF_IMAGE_WITH_PE
+-      if (! coff_apply_checksum (abfd))
+-      return FALSE;
++        if (! coff_apply_checksum (abfd))
++          return FALSE;
+ #endif
++      }
+     }
+ #ifdef RS6000COFF_C
+   else
+@@ -4491,6 +4535,10 @@
+           /* In PE, 0x69 (105) denotes a weak external symbol.  */
+           case C_NT_WEAK:
+ #endif
++#ifdef AVR
++          /* Some AVR COFF compilers handle EXTDEF like EXT. */
++          case C_EXTDEF:      /* external definition           */
 +#endif
+             switch (coff_classify_symbol (abfd, &src->u.syment))
+               {
+               case COFF_SYMBOL_GLOBAL:
+@@ -4714,7 +4762,9 @@
+                 && src->u.syment.n_scnum == 0)
+               break;
+             /* Fall through.  */
++#if !defined(AVR)
+           case C_EXTDEF:      /* External definition.  */
++#endif
+           case C_ULABEL:      /* Undefined label.  */
+           case C_USTATIC:     /* Undefined static.  */
+ #ifndef COFF_WITH_PE
+--- binutils-2.18.orig/bfd/coffgen.c   Tue Oct 23 21:44:07 2007
++++ binutils-2.18/bfd/coffgen.c        Tue Oct 23 23:07:23 2007
+@@ -687,6 +687,20 @@
+             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;
 +
-+  /* COFF can inherently only handle line numbers inside of functions.
-+     If we are not inside a function, punt. */
-+  if (info->funname == NULL)
-+    return TRUE;
-+
-+  if (info->nlnos == 2)
-+    {
-+      /* This is the first line number of this function.  Fix the line
-+       number for the .bf symbol immediately following the start of
-+       function.  We also have to remember the starting line number
-+       of our function since all line number entries are relative to
-+       it in COFF.  Since regular line numbers must always be
-+       non-zero, we artificially force the function to start one
-+       line earlier. */
-+      csymp = (coff_symbol_type *) info->syms[info->funcindex + 1];
-+      aux = &((csymp->native + 1)->u.auxent);
-+      aux->x_sym.x_misc.x_lnsz.x_lnno = lineno;
-+      info->funlno = lineno - 1;
-+    }
-+
-+  if (info->flags & COFF_FL_FIX_BB)
-+    {
-+      /* This is the first line number after one (or more) .bb
-+       symbols.  Fix them.  In order to cope with multiple blocks
-+       starting at the same line number, we walk back the list of
-+       symbols until we find a C_BLOCK one that had already been
-+       fixed, or until we find a C_FCN symbol (presumably, the start
-+       of our current function). */
-+      info->flags &= ~COFF_FL_FIX_BB;
-+
-+      for (i = info->nsyms - 1; i >= 0; i--)
-+      {
-+        csymp = (coff_symbol_type *) info->syms[i];
-+        if (csymp->native->u.syment.n_sclass == C_FCN)
-+          break;
-+        if (csymp->native->u.syment.n_sclass == C_BLOCK)
++                s->u.syment.n_numaux = n > NAUXENTS? NAUXENTS: n;
++              }
+           }
+         else
+           /* Modify the symbol values according to their section and
+@@ -815,6 +829,20 @@
+       {
+         if (name_length <= filnmlen)
+           strncpy (auxent->x_file.x_fname, name, filnmlen);
++        else if (bfd_get_arch (abfd) == bfd_arch_avr)
 +          {
-+            aux = &((csymp->native + 1)->u.auxent);
-+            if (aux->x_sym.x_misc.x_lnsz.x_lnno != 0)
-+              /* already set up properly */
-+              break;
-+            aux->x_sym.x_misc.x_lnsz.x_lnno = lineno;
++            /* 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);
 +          }
-+      }
-+    }
-+
-+  csymp = (coff_symbol_type *) info->syms[info->funcindex];
-+  csymp->lineno = (alent *) xrealloc (csymp->lineno,
-+                                    ++info->nlnos * sizeof (alent));
-+  memset (csymp->lineno + info->nlnos - 1, 0, sizeof (alent));
-+  if (lineno > info->funlno)
-+    csymp->lineno[info->nlnos - 2].line_number = lineno - info->funlno;
-+  else
-+    /* Line number unreasonable.  Can e. g. happen for a line number
-+       from an include file, which we cannot process in COFF.  Just
-+       set it to the first line, to avoid generating a large unsigned
-+       short (~ 65000) line number. */
-+    csymp->lineno[info->nlnos - 2].line_number = 1;
-+  csymp->lineno[info->nlnos - 2].u.offset = addr;
-+
-+  info->lastlno = lineno;
-+  info->totlnos++;
-+
-+  return TRUE;
-+}
-diff -uNdr binutils-2.17.50.0.18-old/include/coff/avr.h binutils-2.17.50.0.18/include/coff/avr.h
---- binutils-2.17.50.0.18-old/include/coff/avr.h       1970-01-01 01:00:00.000000000 +0100
-+++ binutils-2.17.50.0.18/include/coff/avr.h   2007-10-20 16:45:33.000000000 +0200
+         else
+           {
+             auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE;
+@@ -1218,7 +1246,11 @@
+                 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 @@
+           {
+             /* 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 @@
+   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;
+--- binutils-2.18.orig/bfd/coffswap.h  Tue Oct 23 21:44:07 2007
++++ binutils-2.18/bfd/coffswap.h       Tue Oct 23 22:18:44 2007
+@@ -383,7 +383,11 @@
+                 void * ext1,
+                 int type,
+                 int class,
+-                int indx,
++                int indx
++#if defined(AVR) && __GNUC__
++                __attribute__((unused))
++#endif
++                ,
+                 int numaux,
+                 void * in1)
+ {
+@@ -409,9 +413,13 @@
+ #else
+         if (numaux > 1)
+           {
++#if defined(AVR)
++            memcpy (in->x_file.x_fname, ext->x_file.x_fname, sizeof (AUXENT));
++#else
+             if (indx == 0)
+               memcpy (in->x_file.x_fname, ext->x_file.x_fname,
+                       numaux * sizeof (AUXENT));
++#endif
+           }
+         else
+           memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
+--- binutils-2.18.orig/bfd/config.bfd  Tue Oct 23 21:44:07 2007
++++ binutils-2.18/bfd/config.bfd       Tue Oct 23 22:18:44 2007
+@@ -327,6 +327,7 @@
+   avr-*-*)
+     targ_defvec=bfd_elf32_avr_vec
++    targ_selvecs="bfd_elf32_avr_vec avrcoff_vec avrextcoff_vec"
+     ;;
+   bfin-*-*)
+--- binutils-2.18.orig/bfd/configure   Tue Oct 23 21:44:09 2007
++++ binutils-2.18/bfd/configure        Tue Oct 23 22:18:44 2007
+@@ -19034,6 +19034,8 @@
+     armpe_little_vec)         tb="$tb pe-arm.lo peigen.lo cofflink.lo " ;;
+     armpei_big_vec)           tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;;
+     armpei_little_vec)                tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;;
++    avrcoff_vec)              tb="$tb coff-avr.lo cofflink.lo " ;;
++    avrextcoff_vec)           tb="$tb coff-ext-avr.lo cofflink.lo " ;;
+     b_out_vec_big_host)               tb="$tb bout.lo aout32.lo" ;;
+     b_out_vec_little_host)    tb="$tb bout.lo aout32.lo" ;;
+     bfd_efi_app_ia32_vec)     tb="$tb efi-app-ia32.lo peigen.lo cofflink.lo" ;;
+--- binutils-2.18.orig/bfd/configure.in        Tue Oct 23 21:44:07 2007
++++ binutils-2.18/bfd/configure.in     Tue Oct 23 22:18:44 2007
+@@ -612,6 +612,8 @@
+     armpe_little_vec)         tb="$tb pe-arm.lo peigen.lo cofflink.lo " ;;
+     armpei_big_vec)           tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;;
+     armpei_little_vec)                tb="$tb pei-arm.lo peigen.lo cofflink.lo " ;;
++    avrcoff_vec)              tb="$tb coff-avr.lo cofflink.lo " ;;
++    avrextcoff_vec)           tb="$tb coff-ext-avr.lo cofflink.lo " ;;
+     b_out_vec_big_host)               tb="$tb bout.lo aout32.lo" ;;
+     b_out_vec_little_host)    tb="$tb bout.lo aout32.lo" ;;
+     bfd_efi_app_ia32_vec)     tb="$tb efi-app-ia32.lo peigen.lo cofflink.lo" ;;
+--- binutils-2.18.orig/bfd/targets.c   Tue Oct 23 21:44:09 2007
++++ binutils-2.18/bfd/targets.c        Tue Oct 23 22:18:44 2007
+@@ -558,6 +558,8 @@
+ extern const bfd_target armpe_little_vec;
+ extern const bfd_target armpei_big_vec;
+ extern const bfd_target armpei_little_vec;
++extern const bfd_target avrcoff_vec;
++extern const bfd_target avrextcoff_vec;
+ extern const bfd_target b_out_vec_big_host;
+ extern const bfd_target b_out_vec_little_host;
+ extern const bfd_target bfd_efi_app_ia32_vec;
+@@ -876,6 +878,8 @@
+       &armpe_little_vec,
+       &armpei_big_vec,
+       &armpei_little_vec,
++      &avrcoff_vec,
++      &avrextcoff_vec,
+       &b_out_vec_big_host,
+       &b_out_vec_little_host,
+       &bfd_efi_app_ia32_vec,
+--- binutils-2.18.orig/include/coff/avr.h      Thu Jan  1 01:00:00 1970
++++ binutils-2.18/include/coff/avr.h   Tue Oct 23 22:18:44 2007
 @@ -0,0 +1,110 @@
 +/* coff information for Atmel AVR.
 +   
@@ -5521,9 +5541,8 @@ diff -uNdr binutils-2.17.50.0.18-old/include/coff/avr.h binutils-2.17.50.0.18/in
 +
 +#define RELOC struct external_reloc
 +#define RELSZ 10
-diff -uNdr binutils-2.17.50.0.18-old/include/coff/internal.h binutils-2.17.50.0.18/include/coff/internal.h
---- binutils-2.17.50.0.18-old/include/coff/internal.h  2007-08-01 15:11:51.000000000 +0200
-+++ binutils-2.17.50.0.18/include/coff/internal.h      2007-10-20 16:45:33.000000000 +0200
+--- binutils-2.18.orig/include/coff/internal.h Tue Oct 23 21:44:43 2007
++++ binutils-2.18/include/coff/internal.h      Tue Oct 23 22:18:44 2007
 @@ -630,6 +630,8 @@
  
  };
This page took 0.7822 seconds and 4 git commands to generate.