diff -ruN avr-binutils.orig/Portfile avr-binutils/Portfile
--- avr-binutils.orig/Portfile	2010-04-05 23:27:54.000000000 -0700
+++ avr-binutils/Portfile	2010-04-06 21:06:45.000000000 -0700
@@ -3,6 +3,7 @@
 PortSystem			1.0
 name				avr-binutils
 version				2.20
+revision			1
 
 # Parameters for this port.
 set crossgcc-target avr
@@ -55,10 +56,15 @@
 
 build.dir       	${workpath}/build
 					
-# We don't want the etc module.
-post-extract {
-	system "rm -rf ${worksrcpath}/etc"
-}
+patchfiles patch-aa \
+	   patch-as-dwarf \
+	   patch-as-dwarf-avrstudio \
+	   patch-avr-size \
+	   patch-coff-avr \
+	   patch-newdevices \
+	   patch-newsections \
+	   patch-xmega
+
 
 post-patch {
 	namespace eval crossgcc {}
diff -ruN avr-binutils.orig/files/patch-aa avr-binutils/files/patch-aa
--- avr-binutils.orig/files/patch-aa	1969-12-31 16:00:00.000000000 -0800
+++ avr-binutils/files/patch-aa	2010-03-04 05:38:29.000000000 -0800
@@ -0,0 +1,50 @@
+--- etc/Makefile.in~	2009-07-31 00:44:48.000000000 +0200
++++ etc/Makefile.in	2010-03-03 17:13:29.000000000 +0100
+@@ -64,7 +64,8 @@
+ HTMLFILES = standards.html configure.html
+ 
+ all: info
+-install: install-info
++#install: install-info
++install:
+ 
+ uninstall:
+ 
+--- libiberty/Makefile.in~	2009-08-23 21:03:58.000000000 +0200
++++ libiberty/Makefile.in	2010-03-03 17:14:00.000000000 +0100
+@@ -321,7 +321,8 @@
+ @MAINT@	echo stamp > stamp-functions
+ 
+ INSTALL_DEST = @INSTALL_DEST@
+-install: install_to_$(INSTALL_DEST) install-subdir
++#install: install_to_$(INSTALL_DEST) install-subdir
++install:
+ 
+ # This is tricky.  Even though CC in the Makefile contains
+ # multilib-specific flags, it's overridden by FLAGS_TO_PASS from the
+--- bfd/Makefile.in~	2009-10-16 13:47:48.000000000 +0200
++++ bfd/Makefile.in	2010-03-03 17:19:17.000000000 +0100
+@@ -1673,8 +1673,9 @@
+ 	for dir in "$(DESTDIR)$(bfdlibdir)" "$(DESTDIR)$(bfdincludedir)"; do \
+ 	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ 	done
+-install: $(BUILT_SOURCES)
+-	$(MAKE) $(AM_MAKEFLAGS) install-recursive
++#install: $(BUILT_SOURCES)
++#	$(MAKE) $(AM_MAKEFLAGS) install-recursive
++install:
+ install-exec: install-exec-recursive
+ install-data: install-data-recursive
+ uninstall: uninstall-recursive
+--- opcodes/Makefile.in~	2009-09-07 14:08:03.000000000 +0200
++++ opcodes/Makefile.in	2010-03-03 17:19:43.000000000 +0100
+@@ -1051,7 +1051,8 @@
+ 	for dir in "$(DESTDIR)$(bfdlibdir)" "$(DESTDIR)$(bfdincludedir)"; do \
+ 	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ 	done
+-install: install-recursive
++#install: install-recursive
++install:
+ install-exec: install-exec-recursive
+ install-data: install-data-recursive
+ uninstall: uninstall-recursive
diff -ruN avr-binutils.orig/files/patch-as-dwarf avr-binutils/files/patch-as-dwarf
--- avr-binutils.orig/files/patch-as-dwarf	1969-12-31 16:00:00.000000000 -0800
+++ avr-binutils/files/patch-as-dwarf	2010-03-04 05:38:29.000000000 -0800
@@ -0,0 +1,10 @@
+diff -ru binutils-2.19.1.orig/gas/config/tc-avr.h binutils-2.19.1/gas/config/tc-avr.h
+--- gas/config/tc-avr.h	Tue Jul  3 14:01:04 2007
++++ gas/config/tc-avr.h	Thu Apr 16 20:46:54 2009
+@@ -147,3 +147,6 @@
+ 
+ /* This target is buggy, and sets fix size too large.  */
+ #define TC_FX_SIZE_SLACK(FIX) 2
++
++/* keep DWARF2_ADDR_SIZE in consistency with C compiler produced information */
++#define DWARF2_ADDR_SIZE(bfd) 4
diff -ruN avr-binutils.orig/files/patch-as-dwarf-avrstudio avr-binutils/files/patch-as-dwarf-avrstudio
--- avr-binutils.orig/files/patch-as-dwarf-avrstudio	1969-12-31 16:00:00.000000000 -0800
+++ avr-binutils/files/patch-as-dwarf-avrstudio	2010-03-04 05:38:29.000000000 -0800
@@ -0,0 +1,27 @@
+--- gas/dwarf2dbg.c.orig	2009-09-14 13:43:26.000000000 +0200
++++ gas/dwarf2dbg.c	2010-03-04 11:13:52.000000000 +0100
+@@ -112,8 +112,11 @@
+    Note: If you want to change this, you'll have to update the
+    "standard_opcode_lengths" table that is emitted below in
+    out_debug_line().  */
++#ifndef TC_AVR
+ #define DWARF2_LINE_OPCODE_BASE		13
+-
++#else
++#define DWARF2_LINE_OPCODE_BASE		10
++#endif
+ #ifndef DWARF2_LINE_BASE
+   /* Minimum line offset in a special line info. opcode.  This value
+      was chosen to give a reasonable range of values.  */
+@@ -1439,9 +1442,11 @@
+   out_byte (0);			/* DW_LNS_set_basic_block */
+   out_byte (0);			/* DW_LNS_const_add_pc */
+   out_byte (1);			/* DW_LNS_fixed_advance_pc */
++#ifndef TC_AVR
+   out_byte (0);			/* DW_LNS_set_prologue_end */
+   out_byte (0);			/* DW_LNS_set_epilogue_begin */
+   out_byte (1);			/* DW_LNS_set_isa */
++#endif
+ 
+   out_file_list ();
+ 
diff -ruN avr-binutils.orig/files/patch-avr-size avr-binutils/files/patch-avr-size
--- avr-binutils.orig/files/patch-avr-size	1969-12-31 16:00:00.000000000 -0800
+++ avr-binutils/files/patch-avr-size	2010-03-04 05:38:29.000000000 -0800
@@ -0,0 +1,513 @@
+AVR specific only
+===========================================================
+--- binutils/size.c	2007-08-06 13:56:14.000000000 -0600
++++ binutils/size.c	2007-09-13 09:13:10.281250000 -0600
+@@ -36,10 +36,31 @@
+ #include "getopt.h"
+ #include "bucomm.h"
+ 
+-#ifndef BSD_DEFAULT
+-#define BSD_DEFAULT 1
++typedef enum
++{
++    format_sysv = 0,
++    format_bsd = 1,
++    format_avr = 2,
++} format_type_t;
++
++
++/* Set the default format. */
++#define FORMAT_DEFAULT_SYSV 0
++#define FORMAT_DEFAULT_BSD 1
++#define FORMAT_DEFAULT_AVR 0
++
++#if FORMAT_DEFAULT_SYSV
++    #define FORMAT_DEFAULT format_sysv
++    #define FORMAT_NAME "sysv"
++#elif FORMAT_DEFAULT_BSD
++    #define FORMAT_DEFAULT format_bsd
++    #define FORMAT_NAME "berkeley"
++#elif FORMAT_DEFAULT_AVR
++    #define FORMAT_DEFAULT format_avr
++    #define FORMAT_NAME "avr"
+ #endif
+ 
++
+ /* Program options.  */
+ 
+ static enum
+@@ -48,9 +69,8 @@ static enum
+   }
+ radix = decimal;
+ 
+-/* 0 means use AT&T-style output.  */
+-static int berkeley_format = BSD_DEFAULT;
+ 
++format_type_t format = FORMAT_DEFAULT;
+ static int show_version = 0;
+ static int show_help = 0;
+ static int show_totals = 0;
+@@ -64,6 +84,238 @@ static bfd_size_type total_textsize;
+ /* Program exit status.  */
+ static int return_code = 0;
+ 
++
++/* AVR Size specific stuff */
++
++#define AVR64 64UL
++#define AVR128 128UL
++#define AVR256 256UL
++#define AVR512 512UL
++#define AVR1K 1024UL
++#define AVR2K 2048UL
++#define AVR4K 4096UL
++#define AVR8K 8192UL
++#define AVR16K 16384UL
++#define AVR20K 20480UL
++#define AVR24K 24576UL
++#define AVR32K 32768UL
++#define AVR36K 36864UL
++#define AVR40K 40960UL
++#define AVR64K 65536UL
++#define AVR68K 69632UL
++#define AVR128K 131072UL
++#define AVR136K 139264UL
++#define AVR200K 204800UL
++#define AVR256K 262144UL
++#define AVR264K 270336UL
++
++typedef struct
++{
++    char *name;
++	long flash;
++	long ram;
++	long eeprom;
++} avr_device_t;
++
++avr_device_t avr[] =
++{
++	{"atxmega256a3",  AVR264K, AVR16K, AVR4K},
++	{"atxmega256a3b", AVR264K, AVR16K, AVR4K},
++	{"atxmega256d3",  AVR264K, AVR16K, AVR4K},
++
++	{"atmega2560",    AVR256K, AVR8K,  AVR4K},
++	{"atmega2561",    AVR256K, AVR8K,  AVR4K},
++
++	{"atxmega192a3",  AVR200K, AVR16K, AVR2K},
++	{"atxmega192d3",  AVR200K, AVR16K, AVR2K},
++
++	{"atxmega128a1",  AVR136K, AVR8K,  AVR2K},
++	{"atxmega128a3",  AVR136K, AVR8K,  AVR2K},
++	{"atxmega128d3",  AVR136K, AVR8K,  AVR2K},
++
++	{"at43usb320",    AVR128K, 608UL,  0UL},
++	{"at90can128",    AVR128K, AVR4K,  AVR4K},
++	{"at90usb1286",   AVR128K, AVR8K,  AVR4K},
++	{"at90usb1287",   AVR128K, AVR8K,  AVR4K},
++	{"atmega128",     AVR128K, AVR4K,  AVR4K},
++	{"atmega1280",    AVR128K, AVR8K,  AVR4K},
++	{"atmega1281",    AVR128K, AVR8K,  AVR4K},
++	{"atmega1284p",   AVR128K, AVR16K, AVR4K},
++	{"atmega128rfa1", AVR128K, AVR16K, AVR4K},
++	{"atmega103",     AVR128K, 4000UL, AVR4K},
++
++	{"atxmega64a1",   AVR68K,  AVR4K,  AVR2K},
++	{"atxmega64a3",   AVR68K,  AVR4K,  AVR2K},
++	{"atxmega64d3",   AVR68K,  AVR4K,  AVR2K},
++
++	{"at90can64",     AVR64K,  AVR4K,  AVR2K},
++	{"at90scr100",    AVR64K,  AVR4K,  AVR2K},
++	{"at90usb646",    AVR64K,  AVR4K,  AVR2K},
++	{"at90usb647",    AVR64K,  AVR4K,  AVR2K},
++	{"atmega64",      AVR64K,  AVR4K,  AVR2K},
++	{"atmega640",     AVR64K,  AVR8K,  AVR4K},
++	{"atmega644",     AVR64K,  AVR4K,  AVR2K},
++	{"atmega644a",    AVR64K,  AVR4K,  AVR2K},
++	{"atmega644p",    AVR64K,  AVR4K,  AVR2K},
++	{"atmega644pa",   AVR64K,  AVR4K,  AVR2K},
++	{"atmega645",     AVR64K,  AVR4K,  AVR2K},
++	{"atmega645a",    AVR64K,  AVR4K,  AVR2K},
++	{"atmega645p",    AVR64K,  AVR4K,  AVR2K},
++	{"atmega6450",    AVR64K,  AVR4K,  AVR2K},
++	{"atmega6450a",   AVR64K,  AVR4K,  AVR2K},
++	{"atmega6450p",   AVR64K,  AVR4K,  AVR2K},
++	{"atmega649",     AVR64K,  AVR4K,  AVR2K},
++	{"atmega649a",    AVR64K,  AVR4K,  AVR2K},
++	{"atmega649p",    AVR64K,  AVR4K,  AVR2K},
++	{"atmega6490",    AVR64K,  AVR4K,  AVR2K},
++	{"atmega6490a",   AVR64K,  AVR4K,  AVR2K},
++	{"atmega6490p",   AVR64K,  AVR4K,  AVR2K},
++	{"atmega64c1",    AVR64K,  AVR4K,  AVR2K},
++	{"atmega64hve",   AVR64K,  AVR4K,  AVR1K},
++	{"atmega64m1",    AVR64K,  AVR4K,  AVR2K},
++
++	{"atmega406",     AVR40K,  AVR2K,  AVR512},
++
++	{"atxmega32a4",   AVR36K,  AVR4K,  AVR1K},
++	{"atxmega32d4",   AVR36K,  AVR4K,  AVR1K},
++
++	{"at90can32",     AVR32K,  AVR2K,  AVR1K},
++	{"at94k",         AVR32K,  AVR4K,  0UL},
++	{"atmega32",      AVR32K,  AVR2K,  AVR1K},
++	{"atmega323",     AVR32K,  AVR2K,  AVR1K},
++	{"atmega324a",    AVR32K,  AVR2K,  AVR1K},
++	{"atmega324p",    AVR32K,  AVR2K,  AVR1K},
++	{"atmega324pa",   AVR32K,  AVR2K,  AVR1K},
++	{"atmega325",     AVR32K,  AVR2K,  AVR1K},
++	{"atmega325p",    AVR32K,  AVR2K,  AVR1K},
++	{"atmega3250",    AVR32K,  AVR2K,  AVR1K},
++	{"atmega3250p",   AVR32K,  AVR2K,  AVR1K},
++	{"atmega328",     AVR32K,  AVR2K,  AVR1K},
++	{"atmega328p",    AVR32K,  AVR2K,  AVR1K},
++	{"atmega329",     AVR32K,  AVR2K,  AVR1K},
++	{"atmega329p",    AVR32K,  AVR2K,  AVR1K},
++	{"atmega329pa",   AVR32K,  AVR2K,  AVR1K},
++	{"atmega3290",    AVR32K,  AVR2K,  AVR1K},
++	{"atmega3290p",   AVR32K,  AVR2K,  AVR1K},
++	{"atmega32hvb",   AVR32K,  AVR2K,  AVR1K},
++	{"atmega32c1",    AVR32K,  AVR2K,  AVR1K},
++   {"atmega32hvb",   AVR32K,  AVR2K,  AVR1K},
++	{"atmega32m1",    AVR32K,  AVR2K,  AVR1K},
++	{"atmega32u2",    AVR32K,  AVR1K,  AVR1K},
++	{"atmega32u4",    AVR32K,  2560UL, AVR1K},
++	{"atmega32u6",    AVR32K,  2560UL, AVR1K},
++
++	{"at43usb355",    AVR24K,  1120UL,   0UL},
++
++	{"atxmega16a4",   AVR20K,  AVR2K,  AVR1K},
++	{"atxmega16d4",   AVR20K,  AVR2K,  AVR1K},
++
++	{"at76c711",      AVR16K,  AVR2K,  0UL},
++	{"at90pwm216",    AVR16K,  AVR1K,  AVR512},
++	{"at90pwm316",    AVR16K,  AVR1K,  AVR512},
++	{"at90usb162",    AVR16K,  AVR512, AVR512},
++	{"atmega16",      AVR16K,  AVR1K,  AVR512},
++	{"atmega16a",     AVR16K,  AVR1K,  AVR512},
++	{"atmega161",     AVR16K,  AVR1K,  AVR512},
++	{"atmega162",     AVR16K,  AVR1K,  AVR512},
++	{"atmega163",     AVR16K,  AVR1K,  AVR512},
++	{"atmega164",     AVR16K,  AVR1K,  AVR512},
++	{"atmega164a",    AVR16K,  AVR1K,  AVR512},
++	{"atmega164p",    AVR16K,  AVR1K,  AVR512},
++	{"atmega165a",    AVR16K,  AVR1K,  AVR512},
++	{"atmega165",     AVR16K,  AVR1K,  AVR512},
++	{"atmega165p",    AVR16K,  AVR1K,  AVR512},
++	{"atmega168",     AVR16K,  AVR1K,  AVR512},
++	{"atmega168a",    AVR16K,  AVR1K,  AVR512},
++	{"atmega168p",    AVR16K,  AVR1K,  AVR512},
++	{"atmega169",     AVR16K,  AVR1K,  AVR512},
++	{"atmega169a",    AVR16K,  AVR1K,  AVR512},
++	{"atmega169p",    AVR16K,  AVR1K,  AVR512},
++	{"atmega169pa",   AVR16K,  AVR1K,  AVR512},
++	{"atmega16hva",   AVR16K,  768UL,  AVR256},
++	{"atmega16hva2",  AVR16K,  AVR1K,  AVR256},
++   {"atmega16hvb",   AVR16K,  AVR1K,  AVR512},
++	{"atmega16m1",    AVR16K,  AVR1K,  AVR512},
++	{"atmega16u2",    AVR16K,  AVR512, AVR512},
++	{"atmega16u4",    AVR16K,  1280UL, AVR512},
++	{"attiny167",     AVR16K,  AVR512, AVR512},
++
++	{"at90c8534",     AVR8K,   352UL,  AVR512},
++	{"at90pwm1",      AVR8K,   AVR512, AVR512},
++	{"at90pwm2",      AVR8K,   AVR512, AVR512},
++	{"at90pwm2b",     AVR8K,   AVR512, AVR512},
++	{"at90pwm3",      AVR8K,   AVR512, AVR512},
++	{"at90pwm3b",     AVR8K,   AVR512, AVR512},
++	{"at90pwm81",     AVR8K,   AVR256, AVR512},
++	{"at90s8515",     AVR8K,   AVR512, AVR512},
++	{"at90s8535",     AVR8K,   AVR512, AVR512},
++	{"at90usb82",     AVR8K,   AVR512, AVR512},
++	{"ata6289",       AVR8K,   AVR512, 320UL},
++	{"atmega8",       AVR8K,   AVR1K,  AVR512},
++	{"atmega8515",    AVR8K,   AVR512, AVR512},
++	{"atmega8535",    AVR8K,   AVR512, AVR512},
++	{"atmega88",      AVR8K,   AVR1K,  AVR512},
++	{"atmega88a",     AVR8K,   AVR1K,  AVR512},
++	{"atmega88p",     AVR8K,   AVR1K,  AVR512},
++	{"atmega88pa",    AVR8K,   AVR1K,  AVR512},
++	{"atmega8hva",    AVR8K,   768UL,  AVR256},
++	{"atmega8u2",     AVR8K,   AVR512, AVR512},
++	{"attiny84",      AVR8K,   AVR512, AVR512},
++	{"attiny85",      AVR8K,   AVR512, AVR512},
++	{"attiny861",     AVR8K,   AVR512, AVR512},
++	{"attiny861a",    AVR8K,   AVR512, AVR512},
++	{"attiny87",      AVR8K,   AVR512, AVR512},
++	{"attiny88",      AVR8K,   AVR512, AVR64},
++
++	{"at90s4414",     AVR4K,   352UL,  AVR256},
++	{"at90s4433",     AVR4K,   AVR128, AVR256},
++	{"at90s4434",     AVR4K,   352UL,  AVR256},
++	{"atmega48",      AVR4K,   AVR512, AVR256},
++	{"atmega48a",     AVR4K,   AVR512, AVR256},
++	{"atmega48p",     AVR4K,   AVR512, AVR256},
++	{"attiny4313",    AVR4K,   AVR256, AVR256},
++	{"attiny43u",     AVR4K,   AVR256, AVR64},
++	{"attiny44",      AVR4K,   AVR256, AVR256},
++	{"attiny44a",     AVR4K,   AVR256, AVR256},
++	{"attiny45",      AVR4K,   AVR256, AVR256},
++	{"attiny461",     AVR4K,   AVR256, AVR256},
++	{"attiny461a",    AVR4K,   AVR256, AVR256},
++	{"attiny48",      AVR4K,   AVR256, AVR64},
++
++	{"at86rf401",     AVR2K,   224UL,  AVR128},
++	{"at90s2313",     AVR2K,   AVR128, AVR128},
++	{"at90s2323",     AVR2K,   AVR128, AVR128},
++	{"at90s2333",     AVR2K,   224UL,  AVR128},
++	{"at90s2343",     AVR2K,   AVR128, AVR128},
++   {"attiny20",      AVR2K,   AVR128, 0UL},
++	{"attiny22",      AVR2K,   224UL,  AVR128},
++	{"attiny2313",    AVR2K,   AVR128, AVR128},
++	{"attiny2313a",   AVR2K,   AVR128, AVR128},
++	{"attiny24",      AVR2K,   AVR128, AVR128},
++	{"attiny24a",     AVR2K,   AVR128, AVR128},
++	{"attiny25",      AVR2K,   AVR128, AVR128},
++	{"attiny26",      AVR2K,   AVR128, AVR128},
++	{"attiny261",     AVR2K,   AVR128, AVR128},
++	{"attiny261a",    AVR2K,   AVR128, AVR128},
++	{"attiny28",      AVR2K,   0UL,    0UL},
++   {"attiny40",      AVR2K,   AVR256, 0UL},
++
++	{"at90s1200",     AVR1K,   0UL,    AVR64},
++   {"attiny9",       AVR1K,   32UL,   0UL},
++   {"attiny10",      AVR1K,   32UL,   0UL},
++	{"attiny11",      AVR1K,   0UL,    AVR64},
++	{"attiny12",      AVR1K,   0UL,    AVR64},
++	{"attiny13",      AVR1K,   AVR64,  AVR64},
++	{"attiny13a",     AVR1K,   AVR64,  AVR64},
++	{"attiny15",      AVR1K,   0UL,    AVR64},
++
++   {"attiny4",       AVR512,  32UL,   0UL},
++   {"attiny5",       AVR512,  32UL,   0UL},
++};
++
++static char *avrmcu = NULL;
++
++
+ static char *target = NULL;
+ 
+ /* Forward declarations.  */
+@@ -79,7 +329,8 @@ usage (FILE *stream, int status)
+   fprintf (stream, _(" Displays the sizes of sections inside binary files\n"));
+   fprintf (stream, _(" If no input file(s) are specified, a.out is assumed\n"));
+   fprintf (stream, _(" The options are:\n\
+-  -A|-B     --format={sysv|berkeley}  Select output style (default is %s)\n\
++  -A|-B|-C  --format={sysv|berkeley|avr}  Select output style (default is %s)\n\
++            --mcu=<avrmcu>            MCU name for AVR format only\n\
+   -o|-d|-x  --radix={8|10|16}         Display numbers in octal, decimal or hex\n\
+   -t        --totals                  Display the total sizes (Berkeley only)\n\
+             --common                  Display total size for *COM* syms\n\
+@@ -88,11 +329,7 @@ usage (FILE *stream, int status)
+   -h        --help                    Display this information\n\
+   -v        --version                 Display the program's version\n\
+ \n"),
+-#if BSD_DEFAULT
+-  "berkeley"
+-#else
+-  "sysv"
+-#endif
++FORMAT_NAME
+ );
+   list_supported_targets (program_name, stream);
+   if (REPORT_BUGS_TO[0] && status == 0)
+@@ -103,6 +351,7 @@ usage (FILE *stream, int status)
+ #define OPTION_FORMAT (200)
+ #define OPTION_RADIX (OPTION_FORMAT + 1)
+ #define OPTION_TARGET (OPTION_RADIX + 1)
++#define OPTION_MCU (OPTION_TARGET + 1) 
+ 
+ static struct option long_options[] =
+ {
+@@ -110,6 +360,7 @@ static struct option long_options[] =
+   {"format", required_argument, 0, OPTION_FORMAT},
+   {"radix", required_argument, 0, OPTION_RADIX},
+   {"target", required_argument, 0, OPTION_TARGET},
++  {"mcu", required_argument, 0, 203},
+   {"totals", no_argument, &show_totals, 1},
+   {"version", no_argument, &show_version, 1},
+   {"help", no_argument, &show_help, 1},
+@@ -141,7 +391,7 @@ main (int argc, char **argv)
+   bfd_init ();
+   set_default_bfd_target ();
+ 
+-  while ((c = getopt_long (argc, argv, "ABHhVvdfotx", long_options,
++  while ((c = getopt_long (argc, argv, "ABCHhVvdfotx", long_options,
+ 			   (int *) 0)) != EOF)
+     switch (c)
+       {
+@@ -150,11 +401,15 @@ main (int argc, char **argv)
+ 	  {
+ 	  case 'B':
+ 	  case 'b':
+-	    berkeley_format = 1;
++	    format = format_bsd;
+ 	    break;
+ 	  case 'S':
+ 	  case 's':
+-	    berkeley_format = 0;
++	    format = format_sysv;
++	    break;
++	  case 'A':
++	  case 'a':
++	    format = format_avr;
+ 	    break;
+ 	  default:
+ 	    non_fatal (_("invalid argument to --format: %s"), optarg);
+@@ -162,6 +416,10 @@ main (int argc, char **argv)
+ 	  }
+ 	break;
+ 
++      case OPTION_MCU:
++	avrmcu = optarg;
++	break;
++
+       case OPTION_TARGET:
+ 	target = optarg;
+ 	break;
+@@ -190,11 +449,14 @@ main (int argc, char **argv)
+ 	break;
+ 
+       case 'A':
+-	berkeley_format = 0;
++	format = format_sysv;
+ 	break;
+       case 'B':
+-	berkeley_format = 1;
++	format = format_bsd;
+ 	break;
++      case 'C':
++    format = format_avr;
++    break;
+       case 'v':
+       case 'V':
+ 	show_version = 1;
+@@ -240,7 +501,7 @@ main (int argc, char **argv)
+     for (; optind < argc;)
+       display_file (argv[optind++]);
+ 
+-  if (show_totals && berkeley_format)
++  if (show_totals && format == format_bsd)
+     {
+       bfd_size_type total = total_textsize + total_datasize + total_bsssize;
+ 
+@@ -599,13 +861,117 @@ print_sysv_format (bfd *file)
+   printf ("\n\n");
+ }
+ 
++
++static avr_device_t *
++avr_find_device (void)
++{
++  unsigned int i;
++  if (avrmcu != NULL)
++  {
++    for (i = 0; i < sizeof(avr) / sizeof(avr[0]); i++)
++    {
++      if (strcmp(avr[i].name, avrmcu) == 0)
++      {
++        /* Match found */
++        return (&avr[i]);
++      }
++    }
++  }
++  return (NULL);
++}
++
++
++
++static void
++print_avr_format (bfd *file)
++{
++  char *avr_name = "Unknown";
++  int flashmax = 0;
++  int rammax = 0;
++  int eeprommax = 0;
++  asection *section; 
++  bfd_size_type datasize = 0;
++  bfd_size_type textsize = 0;
++  bfd_size_type bsssize = 0;
++  bfd_size_type bootloadersize = 0;
++  bfd_size_type noinitsize = 0;
++  bfd_size_type eepromsize = 0;
++
++  avr_device_t *avrdevice = avr_find_device();
++  if (avrdevice != NULL)
++  {
++    avr_name = avrdevice->name;
++    flashmax = avrdevice->flash;
++    rammax = avrdevice->ram;
++    eeprommax = avrdevice->eeprom;
++  }
++
++  if ((section = bfd_get_section_by_name (file, ".data")) != NULL)
++    datasize = bfd_section_size (file, section);
++  if ((section = bfd_get_section_by_name (file, ".text")) != NULL)
++    textsize = bfd_section_size (file, section);
++  if ((section = bfd_get_section_by_name (file, ".bss")) != NULL)
++    bsssize = bfd_section_size (file, section);
++  if ((section = bfd_get_section_by_name (file, ".bootloader")) != NULL)
++    bootloadersize = bfd_section_size (file, section);
++  if ((section = bfd_get_section_by_name (file, ".noinit")) != NULL)
++    noinitsize = bfd_section_size (file, section);
++  if ((section = bfd_get_section_by_name (file, ".eeprom")) != NULL)
++    eepromsize = bfd_section_size (file, section);
++  
++  bfd_size_type text = textsize + datasize + bootloadersize;
++  bfd_size_type data = datasize + bsssize + noinitsize;
++  bfd_size_type eeprom = eepromsize;
++  
++  printf ("AVR Memory Usage\n"
++          "----------------\n"
++          "Device: %s\n\n", avr_name);
++  
++  /* Text size */
++  printf ("Program:%8ld bytes", text);
++  if (flashmax > 0)
++  {
++    printf (" (%2.1f%% Full)", ((float)text / flashmax) * 100);
++  }
++  printf ("\n(.text + .data + .bootloader)\n\n");
++  
++  /* Data size */
++  printf ("Data:   %8ld bytes", data);
++  if (rammax > 0)
++  {
++    printf (" (%2.1f%% Full)", ((float)data / rammax) * 100);
++  }
++  printf ("\n(.data + .bss + .noinit)\n\n");
++  
++  /* EEPROM size */
++  if (eeprom > 0) 
++  { 
++    printf ("EEPROM: %8ld bytes", eeprom);
++    if (eeprommax > 0)
++    {
++      printf (" (%2.1f%% Full)", ((float)eeprom / eeprommax) * 100);
++    }
++    printf ("\n(.eeprom)\n\n");
++  }
++}
++
++
+ static void
+ print_sizes (bfd *file)
+ {
+   if (show_common)
+     calculate_common_size (file);
+-  if (berkeley_format)
+-    print_berkeley_format (file);
+-  else
+-    print_sysv_format (file);
++  switch (format)
++  {
++    case format_sysv:
++      print_sysv_format (file);
++      break;
++    case format_bsd:
++      print_berkeley_format (file);
++      break;
++    case format_avr:
++    default:
++      print_avr_format (file);
++      break;
++  }
+ }
diff -ruN avr-binutils.orig/files/patch-coff-avr avr-binutils/files/patch-coff-avr
--- avr-binutils.orig/files/patch-coff-avr	1969-12-31 16:00:00.000000000 -0800
+++ avr-binutils/files/patch-coff-avr	2010-03-04 05:38:29.000000000 -0800
@@ -0,0 +1,5505 @@
+diff -Nruw bfd/Makefile.am bfd/Makefile.am
+--- bfd/Makefile.am	2009-10-16 17:17:44.000000000 +0530
++++ bfd/Makefile.am	2010-02-11 10:59:11.320193800 +0530
+@@ -228,6 +228,8 @@
+ 	coff-apollo.lo \
+ 	coff-arm.lo \
+ 	coff-aux.lo \
++        coff-avr.lo \
++        coff-ext-avr.lo \
+ 	coff-go32.lo \
+ 	coff-h8300.lo \
+ 	coff-h8500.lo \
+@@ -411,6 +413,8 @@
+ 	coff-apollo.c \
+ 	coff-arm.c \
+ 	coff-aux.c \
++	coff-avr.c \
++	coff-ext-avr.c \
+ 	coff-go32.c \
+ 	coff-h8300.c \
+ 	coff-h8500.c \
+diff -Nruw bfd/Makefile.in bfd/Makefile.in
+--- bfd/Makefile.in	2009-10-16 17:17:48.000000000 +0530
++++ bfd/Makefile.in	2010-02-11 11:13:52.698455300 +0530
+@@ -524,6 +524,8 @@
+ 	coff-apollo.lo \
+ 	coff-arm.lo \
+ 	coff-aux.lo \
++	coff-avr.lo \
++        coff-ext-avr.lo \
+ 	coff-go32.lo \
+ 	coff-h8300.lo \
+ 	coff-h8500.lo \
+@@ -707,6 +709,8 @@
+ 	coff-apollo.c \
+ 	coff-arm.c \
+ 	coff-aux.c \
++	coff-avr.c \
++	coff-ext-avr.c \
+ 	coff-go32.c \
+ 	coff-h8300.c \
+ 	coff-h8500.c \
+diff -Nruw bfd/coff-avr.c bfd/coff-avr.c
+--- bfd/coff-avr.c	1970-01-01 05:30:00.000000000 +0530
++++ bfd/coff-avr.c	2010-02-10 17:35:58.222099600 +0530
+@@ -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
++
++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"
++
++#include "coff/avr.h"
++
++#include "coff/internal.h"
++
++#include "libcoff.h"
++
++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.  */
++
++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 (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
++    {
++      /* 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 1:
++	    {
++	      short x = bfd_get_16 (abfd, addr);
++	      DOIT (x);
++	      bfd_put_16 (abfd, (bfd_vma) x, addr);
++	    }
++	    break;
++
++	  case 2:
++	    {
++	      long x = bfd_get_32 (abfd, addr);
++	      DOIT (x);
++	      bfd_put_32 (abfd, (bfd_vma) x, addr);
++	    }
++	    break;
++
++	  default:
++	    abort ();
++	  }
++      }
++
++  /* Now let bfd_perform_relocation finish everything up.  */
++  return bfd_reloc_continue;
++}
++
++#ifndef PCRELOFFSET
++#define PCRELOFFSET FALSE
++#endif
++
++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
++
++#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;
++{
++  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 -Nruw bfd/coff-ext-avr.c bfd/coff-ext-avr.c
+--- bfd/coff-ext-avr.c	1970-01-01 05:30:00.000000000 +0530
++++ bfd/coff-ext-avr.c	2010-02-10 17:35:58.222099600 +0530
+@@ -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.
++
++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)
++     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 (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
++    {
++      /* 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 1:
++	    {
++	      short x = bfd_get_16 (abfd, addr);
++	      DOIT (x);
++	      bfd_put_16 (abfd, (bfd_vma) x, addr);
++	    }
++	    break;
++
++	  case 2:
++	    {
++	      long x = bfd_get_32 (abfd, addr);
++	      DOIT (x);
++	      bfd_put_32 (abfd, (bfd_vma) x, addr);
++	    }
++	    break;
++
++	  default:
++	    abort ();
++	  }
++      }
++
++  /* Now let bfd_perform_relocation finish everything up.  */
++  return bfd_reloc_continue;
++}
++
++#ifndef PCRELOFFSET
++#define PCRELOFFSET FALSE
++#endif
++
++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 */
++};
++
++/* 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_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;
++{
++
++  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_ext_avr_rtype_to_howto
++
++#ifndef bfd_pe_print_pdata
++#define bfd_pe_print_pdata	NULL
++#endif
++
++#include "coffcode.h"
++
++static const bfd_target *
++coff_ext_avr_object_p(a)
++     bfd *a;
++{
++  return coff_object_p (a);
++}
++
++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 */
++
++  (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_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},
++
++     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 -Nruw bfd/coffcode.h bfd/coffcode.h
+--- bfd/coffcode.h	2009-09-10 17:17:12.000000000 +0530
++++ bfd/coffcode.h	2010-02-10 17:35:58.253349600 +0530
+@@ -1,3 +1,4 @@
++
+ /* 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, 2008, 2009
+@@ -1910,6 +1911,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);
++
+ /*  make_abs_section(abfd);*/
+ 
+   return TRUE;
+@@ -1934,17 +1946,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) =
+@@ -2076,6 +2077,11 @@
+ 	}
+       break;
+ #endif
++#ifdef AVRMAGIC
++    case AVRMAGIC:
++      arch = bfd_arch_avr;
++      break;
++#endif
+ #ifdef MC68MAGIC
+     case MC68MAGIC:
+     case M68MAGIC:
+@@ -2871,6 +2877,13 @@
+       return TRUE;
+ #endif
+ 
++#ifdef AVRMAGIC
++    case bfd_arch_avr:
++      *magicp = AVRMAGIC;
++      return TRUE;
++      break;
++#endif
++
+ #ifdef PPCMAGIC
+     case bfd_arch_powerpc:
+       *magicp = PPCMAGIC;
+@@ -3698,6 +3711,11 @@
+       section.s_page = 0;
+ #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
+@@ -4042,6 +4060,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;
+@@ -4109,8 +4138,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;
+@@ -4668,6 +4705,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:
+@@ -4891,7 +4932,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 -Nruw bfd/coffgen.c bfd/coffgen.c
+--- bfd/coffgen.c	2009-09-10 17:17:12.000000000 +0530
++++ bfd/coffgen.c	2010-02-11 11:20:28.795092600 +0530
+@@ -699,6 +699,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;
++
++		  s->u.syment.n_numaux = n > NAUXENTS? NAUXENTS: n;
++		}
+ 	    }
+ 	  else
+ 	    /* Modify the symbol values according to their section and
+@@ -827,6 +841,20 @@
+ 	{
+ 	  if (name_length <= filnmlen)
+ 	    strncpy (auxent->x_file.x_fname, name, filnmlen);
++	  else if (bfd_get_arch (abfd) == bfd_arch_avr)
++	    {
++	      /* AVR COFF records long filenames in successive aux records. */
++	      int i = 1;
++	      while (name_length > filnmlen && i < NAUXENTS)
++		{
++		  strncpy (auxent->x_file.x_fname, name, filnmlen);
++		  name += filnmlen;
++		  name_length -= filnmlen;
++		  i++;
++		  auxent = &(native + i)->u.auxent;
++		}
++	      strncpy (auxent->x_file.x_fname, name, filnmlen);
++	    }
+ 	  else
+ 	    {
+ 	      auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE;
+@@ -1272,6 +1300,10 @@
+ 		  if (bfd_bwrite (".file", (bfd_size_type) 6, abfd) != 6)
+ 		    return FALSE;
+ 		}
++	      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
+@@ -1710,14 +1742,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)
+@@ -1823,9 +1868,9 @@
+ 
+   if (new_symbol == NULL)
+     return NULL;
+-  /* @@ The 10 is a guess at a plausible maximum number of aux entries
++  /* @@ The NAUXENTS is a guess at a plausible maximum number of aux entries
+      (but shouldn't be a constant).  */
+-  amt = sizeof (combined_entry_type) * 10;
++  amt = sizeof (combined_entry_type) * (NAUXENTS + 1);
+   new_symbol->native = (combined_entry_type *) bfd_zalloc (abfd, amt);
+   if (!new_symbol->native)
+     return NULL;
+diff -Nruw bfd/coffswap.h bfd/coffswap.h
+--- bfd/coffswap.h	2009-09-07 13:45:15.000000000 +0530
++++ bfd/coffswap.h	2010-02-11 11:24:25.908936000 +0530
+@@ -383,7 +383,11 @@
+ 		  void * ext1,
+ 		  int type,
+ 		  int in_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 -Nruw bfd/config.bfd bfd/config.bfd
+--- bfd/config.bfd	2009-08-06 23:08:00.000000000 +0530
++++ bfd/config.bfd	2010-02-10 17:35:58.300224600 +0530
+@@ -339,6 +339,7 @@
+ 
+   avr-*-*)
+     targ_defvec=bfd_elf32_avr_vec
++    targ_selvecs="bfd_elf32_avr_vec avrcoff_vec avrextcoff_vec"
+     ;;
+ 
+   bfin-*-*)
+diff -Nruw bfd/configure bfd/configure
+--- bfd/configure	2009-10-16 17:17:47.000000000 +0530
++++ bfd/configure	2010-02-10 17:35:58.331474600 +0530
+@@ -14782,6 +14782,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_pei_ia64_vec)		tb="$tb pei-ia64.lo pepigen.lo cofflink.lo"; target_size=64 ;;
+diff -Nruw bfd/configure.in bfd/configure.in
+--- bfd/configure.in	2009-10-16 17:17:44.000000000 +0530
++++ bfd/configure.in	2010-02-10 17:35:58.331474600 +0530
+@@ -670,6 +670,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_pei_ia64_vec)		tb="$tb pei-ia64.lo pepigen.lo cofflink.lo"; target_size=64 ;;
+diff -Nruw bfd/targets.c bfd/targets.c
+--- bfd/targets.c	2009-09-10 17:17:13.000000000 +0530
++++ bfd/targets.c	2010-02-10 17:35:58.347099600 +0530
+@@ -564,6 +564,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_pei_ia64_vec;
+@@ -890,6 +892,8 @@
+ 	&armpe_little_vec,
+ 	&armpei_big_vec,
+ 	&armpei_little_vec,
++	&avrcoff_vec,
++	&avrextcoff_vec,
+ 	&b_out_vec_big_host,
+ 	&b_out_vec_little_host,
+ #ifdef BFD64
+diff -Nruw binutils/Makefile.am binutils/Makefile.am
+--- binutils/Makefile.am	2009-09-09 13:43:23.000000000 +0530
++++ binutils/Makefile.am	2010-02-10 17:35:57.972099600 +0530
+@@ -101,7 +101,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 = \
+@@ -109,7 +109,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 -Nruw binutils/Makefile.in binutils/Makefile.in
+--- binutils/Makefile.in	2009-09-09 13:43:23.000000000 +0530
++++ binutils/Makefile.in	2010-02-10 17:35:57.987724600 +0530
+@@ -126,7 +126,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)
+@@ -439,7 +439,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 = \
+@@ -447,7 +447,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 -Nruw binutils/bucomm.c binutils/bucomm.c
+--- binutils/bucomm.c	2009-09-14 17:13:26.000000000 +0530
++++ binutils/bucomm.c	2010-02-10 17:35:58.034599600 +0530
+@@ -550,6 +550,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, '/');
++
++#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;
++}
++
+ /* 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 -Nruw binutils/bucomm.h binutils/bucomm.h
+--- binutils/bucomm.h	2009-09-02 12:52:31.000000000 +0530
++++ binutils/bucomm.h	2010-02-10 17:35:58.050224600 +0530
+@@ -58,6 +58,8 @@
+ 
+ off_t get_file_size (const char *);
+ 
++const char *bu_basename PARAMS ((const char *));
++
+ extern char *program_name;
+ 
+ /* filemode.c */
+diff -Nruw binutils/budbg.h binutils/budbg.h
+--- binutils/budbg.h	2009-09-02 12:52:31.000000000 +0530
++++ binutils/budbg.h	2010-02-10 17:35:58.050224600 +0530
+@@ -52,8 +52,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 ***);
++
+ #endif
+diff -Nruw binutils/debug.c binutils/debug.c
+--- binutils/debug.c	2009-09-14 17:13:26.000000000 +0530
++++ binutils/debug.c	2010-02-11 10:50:38.043866600 +0530
+@@ -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_s *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;
++};
++
+ /* Local functions.  */
+ 
+ static void debug_error (const char *);
+@@ -588,6 +602,11 @@
+   (struct debug_handle *, struct debug_type_s *, struct debug_type_s *);
+ static bfd_boolean debug_class_type_samep
+   (struct debug_handle *, struct debug_type_s *, struct debug_type_s *);
++static const char *debug_xlat_pathname (const char *);
++
++/* List of pathname translations. */
++static struct xlat_list *xlat, *xltail;
++static bfd_boolean xlat_basename;
+ 
+ /* 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;
+ }
++
++/* Register a pathname translation. */
++void
++debug_register_pathname_xlat (oname, nname)
++     const char *oname;
++     const char *nname;
++{
++  struct xlat_list *xlp;
++
++  /* 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;
++    }
++
++  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);
++}
++
++/* Try to translate a pathname. */
++static const char *
++debug_xlat_pathname (oname)
++     const char *oname;
++{
++  struct xlat_list *xlp;
++  char *cp;
++  size_t olen;
++
++  if (xlat_basename)
++    return bu_basename (oname);  
++
++  olen = strlen (oname);
++  for (xlp = xlat; xlp; xlp = xlp->next)
++    {
++      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;
++	}
++    }
++
++  /* Not found, pass the original name on. */
++  return oname;
++}
+diff -Nruw binutils/debug.h binutils/debug.h
+--- binutils/debug.h	2009-09-14 17:13:26.000000000 +0530
++++ binutils/debug.h	2010-02-10 17:35:58.097099600 +0530
+@@ -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 *));
++
+ /* 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 -Nruw binutils/doc/objcopy.1 binutils/doc/objcopy.1
+--- binutils/doc/objcopy.1	2009-10-16 17:22:19.000000000 +0530
++++ binutils/doc/objcopy.1	2010-02-11 10:22:09.312500000 +0530
+@@ -202,6 +202,8 @@
+         [\fB\-\-readonly\-text\fR]
+         [\fB\-\-pure\fR]
+         [\fB\-\-impure\fR]
++ 	[\fB\-\-change\-pathname\fR \fIold\fR=\fInew\fR]
++ 	[\fB\-\-basename\fR]
+         [\fB\-\-file\-alignment=\fR\fInum\fR]
+         [\fB\-\-heap=\fR\fIsize\fR]
+         [\fB\-\-image\-base=\fR\fIaddress\fR]
+@@ -885,6 +887,23 @@
+ It can also be a useful way of reducing the size of a \fB\-\-just\-symbols\fR
+ linker input file.
+ .RE
++.IP "\fB\-\-change\-pathname\fR \fIold\fR=\fInew\fR" 4
++.IX Item "--change-pathname old=new"
++When converting debugging information using \fB\-\-debugging\fR, for
++every pathname that starts with \fIold\fR, replace the matching part
++by \fInew\fR.  This is intented to map pathnames between different
++debugging tools, or when parts of the object file(s) had their
++pathnames recorded in a different build environment.  Note that only
++leading directory name components might be changed that way, since the
++trailing filename could be recorded elsewhere as well (depending on the
++debugging format of the input file).
++.IP "\fB\-\-basename\fR"
++.IX Item "--basename"
++When converting debugging information using \fB\-\-debugging\fR, for
++every pathname, strip all leading directory information.  This option
++takes precedence over any \fB\-\-change\-pathname\fR option.  For some
++debugging formats that cannot handle long filenames, this options is
++implied (notably, some COFF debugging formats).
+ .IP "\fB\-V\fR" 4
+ .IX Item "-V"
+ .PD 0
+diff -Nruw binutils/objcopy.c binutils/objcopy.c
+--- binutils/objcopy.c	2009-09-14 17:13:26.000000000 +0530
++++ binutils/objcopy.c	2010-02-11 10:56:56.890302300 +0530
+@@ -32,6 +32,7 @@
+ #include "elf-bfd.h"
+ #include <sys/stat.h>
+ #include "libbfd.h"
++#include "debug.h"
+ #include "coff/internal.h"
+ #include "libcoff.h"
+ 
+@@ -297,6 +298,8 @@
+     OPTION_IMPURE,
+     OPTION_EXTRACT_SYMBOL,
+     OPTION_REVERSE_BYTES,
++    OPTION_CHANGE_PATHNAME,
++    OPTION_BASENAME,
+     OPTION_FILE_ALIGNMENT,
+     OPTION_HEAP,
+     OPTION_IMAGE_BASE,
+@@ -346,10 +349,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},
+@@ -543,6 +548,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\
+      --file-alignment <num>        Set PE file alignment to <num>\n\
+      --heap <reserve>[,<commit>]   Set PE reserve/commit heap to <reserve>/\n\
+                                    <commit>\n\
+@@ -999,6 +1006,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++)
+     {
+@@ -1099,7 +1108,8 @@
+ 	       || 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
++	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)))
+@@ -2817,6 +2827,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);
++
++  if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
+       || bfd_get_flavour (obfd) == bfd_target_elf_flavour)
+     {
+       bfd_byte *syms, *strings;
+@@ -3641,6 +3655,30 @@
+ 	  prefix_alloc_sections_string = optarg;
+ 	  break;
+ 
++	case OPTION_CHANGE_PATHNAME:
++	  {
++	    const char *s;
++	    int len;
++	    char *name;
++
++	    s = strchr (optarg, '=');
++	    if (s == NULL)
++	      fatal (_("bad format for %s"), "--change-pathname");
++
++	    len = s - optarg;
++	    name = (char *) xmalloc (len + 1);
++	    strncpy (name, optarg, len);
++	    name[len] = '\0';
++
++	    debug_register_pathname_xlat (name, s + 1);
++	  }
++	  break;
++
++	case OPTION_BASENAME:
++	  /* very special case of pathname translation */
++	  debug_register_pathname_xlat (NULL, NULL);
++	  break;
++
+ 	case OPTION_READONLY_TEXT:
+ 	  bfd_flags_to_set |= WP_TEXT;
+ 	  bfd_flags_to_clear &= ~WP_TEXT;
+diff -Nruw binutils/rdcoff.c binutils/rdcoff.c
+--- binutils/rdcoff.c	2009-09-02 12:52:32.000000000 +0530
++++ binutils/rdcoff.c	2010-02-10 17:35:58.128349600 +0530
+@@ -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);
+ 
+ /* 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;
++{
++
++  switch (bfd_get_arch (abfd))
++    {
++    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;
++
++    default:
++      return val;
++    }
++}
++
+ /* 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:
++      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;
+diff -Nruw binutils/wrcoff.c binutils/wrcoff.c
+--- binutils/wrcoff.c	1970-01-01 05:30:00.000000000 +0530
++++ binutils/wrcoff.c	2010-02-10 17:35:58.159599600 +0530
+@@ -0,0 +1,3410 @@
++/* wrcoff.c -- Generate (AVR) COFF debugging information
++   Copyright 2003 Free Software Foundation, Inc.
++
++   Written by Joerg Wunsch.
++
++   This file is part of GNU Binutils.
++
++   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.  */
++
++/* 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. */
++
++#include <stdio.h>
++#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"
++
++/* Enabling COFF_DEBUG will trace the internal callback functions and
++   their parameters as debug_write() calls them. */
++//#define COFF_DEBUG 1
++
++#include "libcoff.h"
++
++#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;
++};
++
++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
++};
++
++/* Structure defining the pre-defined types. */
++struct coff_predef_type
++{
++  enum ts_kind kind;
++  unsigned int size;		/* in bytes */
++  bfd_boolean isunsigned;
++  int slot;
++};
++
++struct coff_type_stack;
++struct coff_hash_entry;
++
++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
++    {
++      unsigned int size;
++      bfd_boolean isunsigned;
++    }
++    ts_int;
++
++    /* TS_FLOAT */
++    struct
++    {
++      unsigned int size;
++    }
++    ts_float;
++
++    /* 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;
++
++    /* TS_FUNC */
++    struct
++    {
++      struct coff_type_stack *savedts;
++    }
++    ts_func;
++
++    /* TS_ARRAY */
++    struct
++    {
++      bfd_signed_vma low;
++      bfd_signed_vma high;
++    }
++    ts_array;
++
++    /* 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;
++};
++
++struct coff_name_type_hash_table
++{
++  struct bfd_hash_table root;
++};
++
++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
++{
++  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;
++};
++
++/* 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 */
++};
++
++/* Stack of tags that need endndx fixing. */
++struct coff_fix_stack
++{
++  struct coff_fix_stack *next;
++  combined_entry_type *native;
++};
++
++/* This is the handle passed through debug_write.  */
++
++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;
++};
++
++/* 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 */
++};
++
++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));
++
++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));
++
++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
++};
++
++/*
++ * 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;
++
++  up = NULL;
++
++  for (i = 0; i < count; i++)
++    {
++      osym = sympp[i];
++
++      /* 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 (osym->flags & BSF_FILE)
++	{
++	  /* New file name. */
++	  long l;
++
++	  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)
++	    {
++	      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)
++		{
++		  /* 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);
++		}
++
++	      /* 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
++	    {
++	      /* 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;
++}
++
++/* 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;
++
++  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;
++    }
++
++  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;
++{
++  struct coff_private_symdata *priv;
++
++  info->syms = (asymbol **) xrealloc (info->syms,
++				      ++info->nsyms * sizeof (asymbol *));
++  info->syms[info->nsyms - 1] = (asymbol *)csymp;
++
++  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;
++
++  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 coff_name_type_hash_entry *ret =
++    (struct coff_name_type_hash_entry *) entry;
++
++  /* 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)
++    {
++      /* Set local fields.  */
++      ret->types = NULL;
++      ret->emitted = FALSE;
++    }
++
++  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)
++    {
++      /* Set local fields.  */
++      ret->types = NULL;
++      ret->emitted = FALSE;
++      ret->fixidxs = NULL;
++      ret->nfixidxs = 0;
++      ret->native = NULL;
++    }
++
++  return (struct bfd_hash_entry *) ret;
++}
++
++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;
++
++  /* 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;
++
++  /* 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;
++    }
++
++  return (struct bfd_hash_entry *) ret;
++}
++
++/* Look up an entry in the hash tables.  */
++
++#define coff_name_type_hash_lookup(table, string, create, copy) \
++  ((struct coff_name_type_hash_entry *) \
++   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
++
++/* 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)))
++
++#define coff_enum_hash_lookup(table, string, create, copy) \
++  ((struct coff_enum_hash_entry *) \
++   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
++
++/* Traverse the hash table.  */
++
++#define coff_enum_hash_traverse(table, func, info)			\
++  (bfd_hash_traverse							\
++   (&(table)->root,							\
++    (bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func),	\
++    (info)))
++
++#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
++
++#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;
++
++  for (tst = h->types; tst != NULL;)
++    {
++      otst = tst;
++      tst = tst->next;
++      free (otst);
++    }
++  return TRUE;
++}
++
++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;
++}
++
++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;)
++    {
++      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;
++{
++  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);
++    }
++
++  return T_NULL;
++}
++
++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;
++
++  /* 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);
++
++  type = arydim = size = nderived = 0;
++
++  aux = &(((*csympp)->native + 1)->u.auxent);
++
++  /* 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;
++
++      /* If we have been advised to not pop the entire stack, stop
++	 here. */
++      if (info->tstack->tsk == stopat && info->tstack->next == NULL)
++	break;
++
++      coff_pop_type ();
++
++      switch (tst->tsk)
++	{
++	case TS_NONE:
++	  /* cannot happen */
++	  break;
++
++	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;
++
++	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;
++
++	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;
++
++	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;
++
++	case TS_POINTER:
++	  nderived++;
++	  type = ((type & ~N_BTMASK) << N_TSHIFT) | (DT_PTR << N_BTSHFT);
++	  size = info->pointersize;
++	  break;
++
++	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;
++
++	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;
++
++	  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;
++
++		  for (i = 0; i < ehash->nfixidxs; i++)
++		    {
++		      combined_entry_type *np;
++
++		      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;
++
++		      if (oldavrcoff)
++			continue;
++
++		      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;
++		    }
++
++		  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;
++
++	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;
++
++	  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;
++
++		  for (i = 0; i < shash->nfixidxs; i++)
++		    {
++		      combined_entry_type *np;
++
++		      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 (oldavrcoff)
++			continue;
++
++		      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;
++		    }
++
++		  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);
++    }
++
++  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;
++    }
++
++  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;
++    }
++
++  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;
++
++  priv->size = size;
++  (*csympp)->symbol.udata.p = priv;
++  (*csympp)->native->u.syment.n_type = type;
++  (*csympp)->native->u.syment.n_numaux = numaux;
++
++  /* 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;
++     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;
++
++  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);
++
++  savedtst = info->tstack;
++
++  if (isstruct)
++    {
++      /* 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;
++	  }
++    }
++
++  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_record_symbol (info, csymp);
++
++      fp->types = NULL;
++    }
++
++  info->tstack = savedtst;
++
++  /* 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;
++}
++
++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;
++}
++
++/* 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;
++     asymbol *osymp;
++     bfd_boolean localp;
++{
++  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;
++
++  coff_record_symbol (info, csymp);
++
++  return TRUE;
++}
++
++/* 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;
++{
++  struct coff_write_handle info;
++  long i, l;
++  asymbol *symp;
++  struct coff_compilation_unit *up;
++  coff_symbol_type *csymp;
++
++  memset ((void *)&info, 0, sizeof info);
++
++  info.abfd = abfd;
++
++  info.pointersize = info.enumsize = 4;
++
++  switch (bfd_get_arch (abfd))
++    {
++    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;
++
++    default:
++      ;
++    }
++
++  coff_copy_symbols(&info, *symcountp, *symppp);
++
++  if (info.textsect == NULL)
++    {
++      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;
++    }
++
++  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;
++
++  /* 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;
++
++	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.
++
++     Finally, put out all remaining global non-debugging symbols. */
++  for (l = 0; l < info.nunits; l++)
++    {
++      const char *bn;
++
++      up = info.units + l;
++      if (up->totsyms == 0)
++	continue;
++
++      /* 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;
++
++      bn = bu_basename (up->fname);
++
++      if (bfd_coff_long_filenames (info.abfd))
++	csymp->symbol.name = up->fname;
++      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 (i = 0; i < up->nsyms; i++)
++	{
++	  symp = up->syms[i];
++	  if (symp == NULL)
++	    continue;
++
++	  coff_emit_ndebug_sym (&info, symp, TRUE);
++	}
++    }
++
++  for (i = 0; i < info.nglobals; i++)
++    {
++      symp = info.globals[i];
++      if (symp == NULL)
++	continue;
++
++      coff_emit_ndebug_sym (&info, symp, FALSE);
++    }
++
++  /* 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;
++
++      csymp = info.secsyms[i];
++
++      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);
++
++  coff_name_type_hash_traverse (&info.types, coff_free_type_info, NULL);
++  bfd_hash_table_free (&info.types.root);
++
++  coff_struct_hash_traverse (&info.structs, coff_free_struct_info, NULL);
++  bfd_hash_table_free (&info.structs.root);
++
++  coff_enum_hash_traverse (&info.enums, coff_free_enum_info, NULL);
++  bfd_hash_table_free (&info.enums.root);
++
++  /* FIXME: free all the other stuff remembered in "info". */
++
++  free (*symppp);
++
++  *symcountp = info.nsyms;
++  *symppp = (asymbol **)info.syms;
++
++  return TRUE;
++}
++
++/* Start writing out information for a compilation unit.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_start_compilation_unit(%s)\n", filename);
++#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;
++
++	if (up->syms[i] != NULL)
++	  {
++	    coff_emit_ndebug_sym (info, up->syms[i], TRUE);
++	    up->syms[i] = NULL;
++	    up->totsyms--;
++	  }
++      }
++
++  /* symtab (and thus COFF debugging) symbols can only transfer the
++     basename of the file, so strip the dirname */
++  bn = bu_basename (filename);
++
++  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;
++    }
++
++  /* 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);
++
++  return TRUE;
++}
++
++/* Start writing out information for a particular source file.  */
++
++static bfd_boolean
++coff_start_source (p, filename)
++     PTR p ATTRIBUTE_UNUSED;
++     const char *filename ATTRIBUTE_UNUSED;
++{
++
++#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_empty_type (p)
++     PTR p;
++{
++  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);
++
++  return TRUE;
++}
++
++/* Push a void type.  */
++
++static bfd_boolean
++coff_void_type (p)
++     PTR p;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst;
++
++#if COFF_DEBUG
++  printf ("coff_void_type()\n");
++#endif
++
++  coff_push_type (TS_VOID);
++
++  return TRUE;
++}
++
++/* Push an integer type.  */
++
++static bfd_boolean
++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;
++
++#if COFF_DEBUG
++  printf ("coff_int_type(%d, %d)\n", size, unsignedp);
++#endif
++
++  coff_push_type (TS_INT);
++  tst->u.ts_int.size = size;
++  tst->u.ts_int.isunsigned = unsignedp;
++
++  return TRUE;
++}
++
++/* Push a floating point type.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_float_type(%d)\n", size);
++#endif
++
++  coff_push_type (TS_FLOAT);
++  tst->u.ts_float.size = size;
++
++  return TRUE;
++}
++
++/* Push a complex type.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_complex_type(%d)\n", size);
++#endif
++
++  coff_push_type (TS_COMPLEX);
++
++  return TRUE;
++}
++
++/* Push a bfd_boolean type. */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_bool_type(%d)\n", size);
++#endif
++
++  coff_push_type (TS_INT);
++  tst->u.ts_int.size = size;
++  tst->u.ts_int.isunsigned = TRUE;
++
++  return TRUE;
++}
++
++/* Push an enum type.  */
++
++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 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
++
++  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;
++
++  return TRUE;
++}
++
++/* Push a pointer type.  */
++
++static bfd_boolean
++coff_pointer_type (p)
++     PTR p;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst;
++
++#if COFF_DEBUG
++  printf ("coff_pointer_type()\n");
++#endif
++
++  coff_push_type (TS_POINTER);
++
++  return TRUE;
++}
++
++/* Push a function type.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_function_type(%d, %d)\n", argcount, varargs);
++#endif
++
++  coff_push_type (TS_FUNC);
++
++  /* FIXME should properly discard function arguments */
++  if (argcount > -1)
++    {
++      fprintf (stderr,
++	       _("coff_function_type() called with positive argcount\n"));
++      return FALSE;
++    }
++
++  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;
++
++#if COFF_DEBUG
++  printf ("coff_reference_type()\n");
++#endif
++
++  coff_complain_unsupp (_("reference"));
++
++  return TRUE;
++}
++
++/* Push a range type.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_range_type([%d..%d)\n", (int)low, (int)high);
++#endif
++
++  coff_complain_unsupp (_("range"));
++
++  return TRUE;
++}
++
++/* Push an array type.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_array_type([%d..%d], %d)\n",
++	  (int)low, (int)high, stringp);
++#endif
++
++  /* Pop the range type, but ignore it.  COFF doesn't use it. */
++  coff_pop_type ();
++
++  /* FIXME  What to do here? */
++  if (stringp)
++    {
++      fprintf(stderr, _("coff_array_type(): stringp == TRUE\n"));
++      return FALSE;
++    }
++
++  coff_push_type (TS_ARRAY);
++  tst->u.ts_array.low = low;
++  tst->u.ts_array.high = high;
++
++  return TRUE;
++}
++
++/* Push a set type.  */
++
++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 COFF_DEBUG
++  printf ("coff_set_type(%d)\n", bitstringp);
++#endif
++
++  coff_complain_unsupp (_("set"));
++
++  return TRUE;
++}
++
++/* Push an offset type.  */
++
++static bfd_boolean
++coff_offset_type (p)
++     PTR p;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++
++#if COFF_DEBUG
++  printf ("coff_offset_type()\n");
++#endif
++
++  coff_complain_unsupp (_("offset"));
++
++  return TRUE;
++}
++
++/* Push a method type.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_method_type(%d, %d, %d)\n",
++	  domainp, argcount, varargs);
++#endif
++
++  coff_complain_unsupp (_("method"));
++
++  return TRUE;
++}
++
++/* Push a const version of a type.  */
++
++static bfd_boolean
++coff_const_type (p)
++     PTR p ATTRIBUTE_UNUSED;
++{
++
++#if COFF_DEBUG
++  printf ("coff_const_type()\n");
++#endif
++
++  /* const modifier is ignored by COFF */
++
++  return TRUE;
++}
++
++/* Push a volatile version of a type.  */
++
++static bfd_boolean
++coff_volatile_type (p)
++     PTR p ATTRIBUTE_UNUSED;
++{
++
++#if COFF_DEBUG
++  printf ("coff_volatile_type()\n");
++#endif
++
++  /* volatile modifier is ignored by COFF */
++
++  return TRUE;
++}
++
++/* 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 = (struct coff_write_handle *) p;
++  struct coff_type_stack *tst, *savedts;
++  struct coff_struct_hash_entry *shash;
++  char buf[20];
++  const char *name;
++
++#if COFF_DEBUG
++  printf ("coff_start_struct_type(%s, %d, %d, %d)\n",
++	  tag, id, structp, size);
++#endif
++
++  savedts = info->tstack;
++  info->tstack = NULL;
++
++  coff_push_type (TS_STRUCT);
++
++  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;
++
++  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);
++
++  return TRUE;
++}
++
++/* 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;)
++    {
++      otst = tst;
++      tst = tst->next;
++    }
++  if (otst != NULL)
++    otst->next = NULL;
++
++  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);
++	}
++    }
++
++  info->tstack = tst;
++
++  return TRUE;
++}
++
++/* Finish up a struct.  */
++
++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;
++
++#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)
++    {
++      fprintf (stderr, "coff_struct_field() not within structure definition\n");
++      return FALSE;
++    }
++
++  /* 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.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_start_class_type(%s, %d, %d, %d, %d, %d)\n",
++	  tag, id, structp, size, vptr, ownvptr);
++#endif
++
++  coff_complain_unsupp (_("class"));
++
++  return TRUE;
++}
++
++/* Add a static member to the class on the type stack.  */
++
++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;
++{
++
++#if COFF_DEBUG
++  printf ("coff_class_static_member(%s, %s, %d)\n",
++	  name, physname, (int)visibility);
++#endif
++
++  return TRUE;
++}
++
++/* Add a base class to the class on the type stack.  */
++
++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;
++{
++
++#if COFF_DEBUG
++  printf ("coff_class_baseclass(%d, %d, %d)\n",
++	  (int)bitpos, virtual, (int)visibility);
++#endif
++
++  return TRUE;
++}
++
++/* Start adding a method to the class on the type stack.  */
++
++static bfd_boolean
++coff_class_start_method (p, name)
++     PTR p ATTRIBUTE_UNUSED;
++     const char *name ATTRIBUTE_UNUSED;
++{
++
++#if COFF_DEBUG
++  printf ("coff_class_start_method(%s)\n", name);
++#endif
++
++  return TRUE;
++}
++
++/* Add a variant to the current method.  */
++
++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;
++{
++
++#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;
++}
++
++/* Add a static variant to the current method.  */
++
++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;
++{
++
++#if COFF_DEBUG
++  printf ("coff_class_static_method_variant(%s, %d, %d, %d)\n",
++	  physname, (int)visibility, constp, volatilep);
++#endif
++
++  return TRUE;
++}
++
++/* 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;
++}
++
++/* 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");
++#endif
++
++  return TRUE;
++}
++
++/* Push a typedef which was previously defined.  */
++
++static bfd_boolean
++coff_typedef_type (p, name)
++     PTR p;
++     const char *name;
++{
++  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
++
++  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 struct, union or class tag.  */
++
++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;
++{
++  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;
++
++    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;
++}
++
++/* Define a typedef.  */
++
++static bfd_boolean
++coff_typdef (p, name)
++     PTR p;
++     const char *name;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  struct coff_name_type_hash_entry *nthash;
++
++#if COFF_DEBUG
++  printf ("coff_typdef(%s)\n", name);
++#endif
++
++  /* 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;
++}
++
++/* Define a tag.  */
++
++static bfd_boolean
++coff_tag (p, tag)
++     PTR p;
++     const char *tag;
++{
++  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;
++
++
++#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 ("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;
++
++    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;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++
++#if COFF_DEBUG
++  printf ("coff_int_constant(%s, %d)\n", name, (int)val);
++#endif
++
++  coff_complain_unsupp (_("int constant"));
++
++  return TRUE;
++}
++
++/* Define a floating point constant.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_float_constant(%s, %g)\n", name, val);
++#endif
++
++  coff_complain_unsupp (_("float constant"));
++
++  return TRUE;
++}
++
++/* Define a typed constant.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_typed_constant(%s, %d)\n", name, (int)val);
++#endif
++
++  coff_complain_unsupp (_("typed constant"));
++
++  return TRUE;
++}
++
++/* Record a variable.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_variable(%s, %d, %d)\n",
++	  name, (int)kind, (int)val);
++#endif
++
++  switch (kind)
++    {
++    default:
++      abort ();
++
++    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;
++
++    case DEBUG_STATIC:
++    case DEBUG_LOCAL_STATIC:
++      class = C_STAT;
++      break;
++
++    case DEBUG_LOCAL:
++      class = C_AUTO;
++      break;
++
++    case DEBUG_REGISTER:
++      class = C_REG;
++      break;
++    }
++
++  if (!coff_make_typed_symbol (info, &csymp, TS_NONE))
++    return FALSE;
++
++  if (class == C_REG && (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);
++    }
++
++  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)
++    {
++      symp = coff_find_symbol (info, name, FALSE, global);
++      if (symp)
++	{
++	  csymp->symbol.section = symp->section;
++	  vmadiff = symp->section->vma;
++	}
++    }
++
++  /* 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.  */
++
++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 COFF_DEBUG
++  printf ("coff_start_function(%s, %d)\n",
++	  name, globalp);
++#endif
++
++  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;
++}
++
++/* 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);
++#endif
++
++  switch (kind)
++    {
++    default:
++      abort ();
++
++    case DEBUG_PARM_STACK:
++      class = C_ARG;
++      break;
++
++    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;
++    }
++
++  if (!coff_make_typed_symbol (info, &csymp, TS_FUNC))
++    return FALSE;
++
++  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);
++    }
++
++  csymp->symbol.name = name;
++  csymp->symbol.value = val;
++  csymp->symbol.flags |= BSF_LOCAL;
++  csymp->native->u.syment.n_sclass = class;
++
++  /* 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;
++}
++
++/* Start a block.  */
++
++static bfd_boolean
++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_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;
++
++  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);
++
++  info->flags |= COFF_FL_FIX_BB;
++
++  /* 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;
++}
++
++/* 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;
++
++#if COFF_DEBUG
++  printf ("coff_end_block(%#x)\n", (int)addr);
++#endif
++
++  if (info->funname == NULL)
++    return TRUE;
++
++  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (csymp == NULL)
++    return FALSE;
++
++  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;
++}
++
++/* End a function.  */
++
++static bfd_boolean
++coff_end_function (p)
++     PTR p;
++{
++  struct coff_write_handle *info = (struct coff_write_handle *) p;
++  coff_symbol_type *csymp;
++  union internal_auxent *aux;
++
++#if COFF_DEBUG
++  printf ("coff_end_function()\n");
++#endif
++
++  if (info->funname == NULL)
++    return TRUE;
++
++  csymp = (coff_symbol_type *) coff_bfd_make_debug_symbol (info->abfd, 0, 0);
++  if (csymp == NULL)
++    return FALSE;
++
++  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;
++}
++
++/* Output a line number.  */
++
++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;
++
++#if COFF_DEBUG
++  printf ("coff_lineno(%s, %ld, %d)\n",
++	  file, lineno, (int)addr);
++#endif
++
++  /* 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)
++	    {
++	      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;
++	    }
++	}
++    }
++
++  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 -Nruw include/coff/avr.h include/coff/avr.h
+--- include/coff/avr.h	1970-01-01 05:30:00.000000000 +0530
++++ include/coff/avr.h	2010-02-10 17:35:58.362724600 +0530
+@@ -0,0 +1,110 @@
++/* coff information for Atmel AVR.
++   
++   Copyright 2001 Free Software Foundation, Inc.
++
++   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.  */
++
++/* This file was hacked from i860.h */
++
++#define L_LNNO_SIZE 2
++#include "coff/external.h"
++
++/* Bits for f_flags:
++ 	F_RELFLG	relocation info stripped from file
++ 	F_EXEC		file is executable (no unresolved external references)
++ 	F_LNNO		line numbers stripped from file
++ 	F_LSYMS		local symbols stripped from file  */
++
++#define F_RELFLG	(0x0001)
++#define F_EXEC		(0x0002)
++#define F_LNNO		(0x0004)
++#define F_LSYMS		(0x0008)
++/* Upper nibble of flags always needs to be set.  This used to be
++ * undocumented, recent information from Atmel says that bit 7 used to
++ * differentiate between an old vendor-specific deviation of the
++ * format and the current format. */
++#define F_JUNK		(0x00f0)
++#define F_UNUSED	(0xff00)
++
++#define	AVRMAGIC	0xa12
++
++#undef AOUTSZ
++#ifdef AVR_EXT_COFF
++
++/* AVR "extended" COFF format.  This uses the optional header ("a.out"
++   header) to inform the consumer about some additional features that
++   are supported. */
++#define COFF_LONG_FILENAMES yes	/* long filenames supported in consecutive aux entries */
++#define AOUTSZ		28	/* size of optional header in "extended" COFF */
++
++/* Flags in the optional header; they are stored in the vstamp field. */
++#define F_FULLPATHS	0x0001	/* long filenames supported */
++#define F_STRUCTINFO	0x0002	/* structure information contained */
++#define F_PTRINFO	0x0004	/* inter-segment pointers supported */
++
++#else /* old AVR COFF */
++
++#define AOUTSZ		0	/* no a.out for AVR */
++#endif
++
++/* #define AVRAOUTMAGIC	0x406 */ /* "general" magic number of optional header */
++/*
++ * The following magic number causes AVR Studio 4.x to recognize
++ * avr-gcc/GNU binutils produced AVR extended COFF files.  By now,
++ * the only special treatment for them is that the contents of .data
++ * will be appended after .text in the simulator flash.
++ *
++ * 0x9cc has been chosen since it resembles "gcc". ;-)
++ */
++#define AVRAOUTMAGIC	0x9cc	/* "gcc" magic number */
++
++/* By matching not only the magic number, but also the size of the
++   optional a.out header, we can differentiate between both
++   formats. */
++#define AVRBADMAG(x)   ((x).f_magic != AVRMAGIC || (x).f_opthdr != AOUTSZ)
++
++/* AVR COFF has several anomalities in the way the handle the derived
++   type information, and AUX entries, mainly because they apparently
++   didn't bother to learn how COFF is supposed to work before they
++   started.  We fix many of them at the export/import boundary, so all
++   the internal generic COFF handling will work mostly as designed. */
++
++/* NB: these functions are only defined in bfd/coff-avr.c, but also
++   used in coff-ext-avr.c, so the latter can only be configured if the
++   former is also present.  This is certainly always the case
++   anyway. */
++extern void avr_coff_adjust_sym_in_post
++  PARAMS((bfd *, PTR, PTR));
++
++extern void avr_coff_adjust_sym_out_post
++  PARAMS((bfd *, PTR, PTR));
++
++#define COFF_ADJUST_SYM_IN_POST(ABFD, EXT, INT) \
++	avr_coff_adjust_sym_in_post (ABFD, EXT, INT)
++
++#define COFF_ADJUST_SYM_OUT_POST(ABFD, INT, EXT) \
++	avr_coff_adjust_sym_out_post (ABFD, INT, EXT)
++
++/********************** RELOCATION DIRECTIVES **********************/
++
++struct external_reloc
++{
++  char r_vaddr[4];
++  char r_symndx[4];
++  char r_type[2];
++};
++
++#define RELOC struct external_reloc
++#define RELSZ 10
+diff -Nruw include/coff/internal.h include/coff/internal.h
+--- include/coff/internal.h	2009-09-02 12:51:39.000000000 +0530
++++ include/coff/internal.h	2010-02-10 17:35:58.378349600 +0530
+@@ -646,6 +646,8 @@
+ 
+ };
+ 
++#define NAUXENTS 10		/* number of pre-allocated aux entries */
++
+ /********************** RELOCATION DIRECTIVES **********************/
+ 
+ struct internal_reloc
diff -ruN avr-binutils.orig/files/patch-newdevices avr-binutils/files/patch-newdevices
--- avr-binutils.orig/files/patch-newdevices	1969-12-31 16:00:00.000000000 -0800
+++ avr-binutils/files/patch-newdevices	2010-03-04 05:38:30.000000000 -0800
@@ -0,0 +1,135 @@
+diff -ruw ggas/config/tc-avr.c gas/config/tc-avr.c
+--- ggas/config/tc-avr.c	2009-09-09 13:43:29.000000000 +0530
++++ gas/config/tc-avr.c	2010-02-12 20:42:30.742688700 +0530
+@@ -133,9 +133,12 @@
+   {"atmega32u2", AVR_ISA_AVR35,   bfd_mach_avr35},
+   {"atmega8",    AVR_ISA_M8,      bfd_mach_avr4},
+   {"atmega48",   AVR_ISA_AVR4,    bfd_mach_avr4},
++  {"atmega48a",  AVR_ISA_AVR4,    bfd_mach_avr4},
+   {"atmega48p",  AVR_ISA_AVR4,    bfd_mach_avr4},
+   {"atmega88",   AVR_ISA_AVR4,    bfd_mach_avr4},
++  {"atmega88a",  AVR_ISA_AVR4,    bfd_mach_avr4},
+   {"atmega88p",  AVR_ISA_AVR4,    bfd_mach_avr4},
++  {"atmega88pa", AVR_ISA_AVR4,    bfd_mach_avr4},
+   {"atmega8515", AVR_ISA_M8,      bfd_mach_avr4},
+   {"atmega8535", AVR_ISA_M8,      bfd_mach_avr4},
+   {"atmega8hva", AVR_ISA_AVR4,    bfd_mach_avr4},
+@@ -150,40 +153,63 @@
+   {"at90pwm3b",  AVR_ISA_AVR4,    bfd_mach_avr4},
+   {"at90pwm81",  AVR_ISA_AVR4,    bfd_mach_avr4},
+   {"atmega16",   AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega16a",  AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega161",  AVR_ISA_M161,    bfd_mach_avr5},
+   {"atmega162",  AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega163",  AVR_ISA_M161,    bfd_mach_avr5},
++  {"atmega164a", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega164p", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega165",  AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega165p", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega168",  AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega168a", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega168p", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega169",  AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega169a", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega169p", AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega169pa",AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega16hva",AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega16hvb",AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega16c1", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega32",   AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega323",  AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega324a", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega324p", AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega324pa",AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega325",  AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega325p", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega3250", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega3250p",AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega328",  AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega328p", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega329",  AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega329p", AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega329pa",AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega3290", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega3290p",AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega32hvb",AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega406",  AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega64",   AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega640",  AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega644",  AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega644a", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega644p", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega644pa",AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega645",  AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega645a", AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega645p", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega649",  AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega649p", AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega649a", AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega6450", AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega6450a",AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega6450p",AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega6490", AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega6490a",AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega6490p",AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega64hve",AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega16hva",AVR_ISA_AVR5,    bfd_mach_avr5},
++  {"atmega16hva2",AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega16hvb",AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"atmega32hvb",AVR_ISA_AVR5,    bfd_mach_avr5},
+   {"at90can32" , AVR_ISA_AVR5,    bfd_mach_avr5},
+diff -ruw ggas/doc/c-avr.texi gas/doc/c-avr.texi
+--- ggas/doc/c-avr.texi	2009-09-02 12:54:21.000000000 +0530
++++ gas/doc/c-avr.texi	2010-02-12 21:31:02.132717100 +0530
+@@ -43,9 +43,10 @@
+ 
+ Instruction set avr25 is for the classic AVR core with up to 8K program memory
+ space plus the MOVW instruction (MCU types: attiny13, attiny13a, attiny2313,
+-attiny2313a, attiny24, attiny24a, attiny4313, attiny44, attiny44a, attiny84,
+-attiny25, attiny45, attiny85, attiny261, attiny261a, attiny461, attiny861,
+-attiny861a, attiny87, attiny43u, attiny48, attiny88, at86rf401, ata6289).
++attiny2313a, attiny24, attiny24a, attiny4313, attiny43u, attiny44, attiny44a, 
++attiny84, attiny25, attiny45, attiny85, attiny261, attiny261a, attiny461, 
++attiny461a, attiny861, attiny861a, attiny87, attiny43u, attiny48, attiny88, 
++at86rf401, ata6289).
+ 
+ Instruction set avr3 is for the classic AVR core with up to 128K program
+ memory space (MCU types: at43usb355, at76c711).
+@@ -58,20 +59,25 @@
+ atmega16u2, atmega32u2).
+ 
+ Instruction set avr4 is for the enhanced AVR core with up to 8K program
+-memory space (MCU types: atmega48, atmega48p,atmega8, atmega88, atmega88p,
+-atmega8515, atmega8535, atmega8hva, atmega4hvd, atmega8hvd, at90pwm1,
+-at90pwm2, at90pwm2b, at90pwm3, at90pwm3b, at90pwm81, atmega8m1, atmega8c1).
++memory space (MCU types: atmega48, atmega48a, atmega48p,atmega8, atmega88, 
++atmega88a, atmega88p, atmega88pa, atmega8515, atmega8535, atmega8hva, 
++atmega4hvd, atmega8hvd, at90pwm1,at90pwm2, at90pwm2b, at90pwm3, at90pwm3b,
++at90pwm81, atmega8m1, atmega8c1).
+ 
+ Instruction set avr5 is for the enhanced AVR core with up to 128K program
+-memory space (MCU types: atmega16, atmega161, atmega162, atmega163, atmega164p,
+-atmega165, atmega165p, atmega168, atmega168p, atmega169, atmega169p, atmega16c1,
+-atmega32, atmega323, atmega324p, atmega325, atmega325p, atmega3250, atmega3250p,
+-atmega328p, atmega329, atmega329p, atmega3290, atmega3290p, atmega406, atmega64,
+-atmega640, atmega644, atmega644p, atmega644pa, atmega645, atmega6450, atmega649,
+-atmega6490, atmega16hva, atmega16hvb, atmega32hvb, at90can32, at90can64,
+-at90pwm216, at90pwm316, atmega32c1, atmega64c1, atmega16m1, atmega32m1,
+-atmega64m1, atmega16u4, atmega32u4, atmega32u6, at90usb646, at90usb647, at94k,
+-at90scr100).
++memory space (MCU types: atmega16, atmega16a, atmega161, atmega162, atmega163,
++atmega164a, atmega164p, atmega165, atmega165a, atmega165p, atmega168, 
++atmega168a, atmega168p, atmega169, atmega169p, atmega169pa, atmega16c1,
++atmega32, atmega323, atmega324a, atmega324p, atmega324pa, atmega325, 
++atmega325p, atmega3250, atmega3250p, atmega328, atmega328p, atmega329,
++atmega329p, atmega329pa, atmega3290, atmega3290p, atmega406, atmega64,
++atmega640, atmega644, atmega644a, atmega644p, atmega644pa, atmega645, 
++atmega645a, atmega645p, atmega6450, atmega6450a, atmega6450p, atmega649,
++atmega649a, atmega649p, atmega6490, atmega6490a, atmega6490p, atmega64hve,
++atmega16hva, atmega16hva2, atmega16hvb, atmega32hvb, at90can32, at90can64,
++at90pwm216, at90pwm316, atmega16u4, atmega32c1, atmega64c1, atmega64m1,
++atmega16m1, atmega32m1, atmega64m1, atmega16u4, atmega32u4, atmega32u6,
++at90usb646, at90usb647, at94k, at90scr100).
+ 
+ Instruction set avr51 is for the enhanced AVR core with exactly 128K program
+ memory space (MCU types: atmega128, atmega1280, atmega1281, atmega1284p,
diff -ruN avr-binutils.orig/files/patch-newsections avr-binutils/files/patch-newsections
--- avr-binutils.orig/files/patch-newsections	1969-12-31 16:00:00.000000000 -0800
+++ avr-binutils/files/patch-newsections	2010-03-04 05:38:30.000000000 -0800
@@ -0,0 +1,38 @@
+diff -ruw ld/scripttempl/avr.sc ld/scripttempl/avr.sc
+--- ld/scripttempl/avr.sc	2009-10-09 18:42:35.000000000 +0530
++++ ld/scripttempl/avr.sc	2010-02-12 20:09:24.070812400 +0530
+@@ -7,6 +7,9 @@
+   text   (rx)   : ORIGIN = 0, LENGTH = $TEXT_LENGTH
+   data   (rw!x) : ORIGIN = $DATA_ORIGIN, LENGTH = $DATA_LENGTH
+   eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
++  fuse      (rw!x) : ORIGIN = 0x820000, LENGTH = 1K
++  lock      (rw!x) : ORIGIN = 0x830000, LENGTH = 1K
++  signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K
+ }
+ 
+ SECTIONS
+@@ -196,6 +199,24 @@
+     ${RELOCATING+ __eeprom_end = . ; }
+   } ${RELOCATING+ > eeprom}
+ 
++  .fuse ${RELOCATING-0}:
++  {
++    KEEP(*(.fuse))
++    KEEP(*(.lfuse))
++    KEEP(*(.hfuse))
++    KEEP(*(.efuse))
++  } ${RELOCATING+ > fuse}
++
++  .lock ${RELOCATING-0}:
++  {
++    KEEP(*(.lock*))
++  } ${RELOCATING+ > lock}
++
++  .signature ${RELOCATING-0}:
++  {
++    KEEP(*(.signature*))
++  } ${RELOCATING+ > signature}
++
+   /* Stabs debugging sections.  */
+   .stab 0 : { *(.stab) }
+   .stabstr 0 : { *(.stabstr) }
diff -ruN avr-binutils.orig/files/patch-xmega avr-binutils/files/patch-xmega
--- avr-binutils.orig/files/patch-xmega	1969-12-31 16:00:00.000000000 -0800
+++ avr-binutils/files/patch-xmega	2010-03-04 05:38:30.000000000 -0800
@@ -0,0 +1,663 @@
+diff -Nur ../binutils-2.20.orig/bfd/archures.c ./bfd/archures.c
+--- ../binutils-2.20.orig/bfd/archures.c	2009-09-10 13:47:11.000000000 +0200
++++ ./bfd/archures.c	2010-03-04 11:34:08.000000000 +0100
+@@ -368,6 +368,13 @@
+ .#define bfd_mach_avr5		5
+ .#define bfd_mach_avr51		51
+ .#define bfd_mach_avr6		6
++.#define bfd_mach_avrxmega1 101
++.#define bfd_mach_avrxmega2 102
++.#define bfd_mach_avrxmega3 103
++.#define bfd_mach_avrxmega4 104
++.#define bfd_mach_avrxmega5 105
++.#define bfd_mach_avrxmega6 106
++.#define bfd_mach_avrxmega7 107
+ .  bfd_arch_bfin,        {* ADI Blackfin *}
+ .#define bfd_mach_bfin          1
+ .  bfd_arch_cr16,       {* National Semiconductor CompactRISC (ie CR16). *}
+diff -Nur ../binutils-2.20.orig/bfd/bfd-in2.h ./bfd/bfd-in2.h
+--- ../binutils-2.20.orig/bfd/bfd-in2.h	2009-09-10 13:47:11.000000000 +0200
++++ ./bfd/bfd-in2.h	2010-03-04 11:34:08.000000000 +0100
+@@ -2035,6 +2035,13 @@
+ #define bfd_mach_avr5          5
+ #define bfd_mach_avr51         51
+ #define bfd_mach_avr6          6
++#define bfd_mach_avrxmega1 101
++#define bfd_mach_avrxmega2 102
++#define bfd_mach_avrxmega3 103
++#define bfd_mach_avrxmega4 104
++#define bfd_mach_avrxmega5 105
++#define bfd_mach_avrxmega6 106
++#define bfd_mach_avrxmega7 107
+   bfd_arch_bfin,        /* ADI Blackfin */
+ #define bfd_mach_bfin          1
+   bfd_arch_cr16,       /* National Semiconductor CompactRISC (ie CR16). */
+diff -Nur ../binutils-2.20.orig/bfd/cpu-avr.c ./bfd/cpu-avr.c
+--- ../binutils-2.20.orig/bfd/cpu-avr.c	2009-09-02 09:18:36.000000000 +0200
++++ ./bfd/cpu-avr.c	2010-03-04 11:34:08.000000000 +0100
+@@ -133,7 +133,29 @@
+   N (22, bfd_mach_avr51, "avr:51", FALSE, & arch_info_struct[9]),
+ 
+   /* 3-Byte PC.  */
+-  N (22, bfd_mach_avr6, "avr:6", FALSE, NULL)
++  N (22, bfd_mach_avr6, "avr:6", FALSE, & arch_info_struct[10]),
++  
++  /* Xmega 1 */
++  N (24, bfd_mach_avrxmega1, "avr:101", FALSE, & arch_info_struct[11]),
++
++  /* Xmega 2 */
++  N (24, bfd_mach_avrxmega2, "avr:102", FALSE, & arch_info_struct[12]),
++  
++  /* Xmega 3 */
++  N (24, bfd_mach_avrxmega3, "avr:103", FALSE, & arch_info_struct[13]),
++  
++  /* Xmega 4 */
++  N (24, bfd_mach_avrxmega4, "avr:104", FALSE, & arch_info_struct[14]),
++  
++  /* Xmega 5 */
++  N (24, bfd_mach_avrxmega5, "avr:105", FALSE, & arch_info_struct[15]),
++  
++  /* Xmega 6 */
++  N (24, bfd_mach_avrxmega6, "avr:106", FALSE, & arch_info_struct[16]),
++  
++  /* Xmega 7 */
++  N (24, bfd_mach_avrxmega7, "avr:107", FALSE, NULL)
++  
+ };
+ 
+ const bfd_arch_info_type bfd_avr_arch =
+diff -Nur ../binutils-2.20.orig/bfd/elf32-avr.c ./bfd/elf32-avr.c
+--- ../binutils-2.20.orig/bfd/elf32-avr.c	2009-09-02 09:18:36.000000000 +0200
++++ ./bfd/elf32-avr.c	2010-03-04 11:34:08.000000000 +0100
+@@ -1328,6 +1328,34 @@
+     case bfd_mach_avr6:
+       val = E_AVR_MACH_AVR6;
+       break;
++
++    case bfd_mach_avrxmega1:
++      val = E_AVR_MACH_XMEGA1;
++      break;
++
++    case bfd_mach_avrxmega2:
++      val = E_AVR_MACH_XMEGA2;
++      break;
++
++    case bfd_mach_avrxmega3:
++      val = E_AVR_MACH_XMEGA3;
++      break;
++
++    case bfd_mach_avrxmega4:
++      val = E_AVR_MACH_XMEGA4;
++      break;
++
++    case bfd_mach_avrxmega5:
++      val = E_AVR_MACH_XMEGA5;
++      break;
++
++    case bfd_mach_avrxmega6:
++      val = E_AVR_MACH_XMEGA6;
++      break;
++
++    case bfd_mach_avrxmega7:
++      val = E_AVR_MACH_XMEGA7;
++      break;
+     }
+ 
+   elf_elfheader (abfd)->e_machine = EM_AVR;
+@@ -1390,6 +1418,34 @@
+ 	case E_AVR_MACH_AVR6:
+ 	  e_set = bfd_mach_avr6;
+ 	  break;
++
++	case E_AVR_MACH_XMEGA1:
++	  e_set = bfd_mach_avrxmega1;
++	  break;
++
++	case E_AVR_MACH_XMEGA2:
++	  e_set = bfd_mach_avrxmega2;
++	  break;
++
++	case E_AVR_MACH_XMEGA3:
++	  e_set = bfd_mach_avrxmega3;
++	  break;
++
++	case E_AVR_MACH_XMEGA4:
++	  e_set = bfd_mach_avrxmega4;
++	  break;
++
++	case E_AVR_MACH_XMEGA5:
++	  e_set = bfd_mach_avrxmega5;
++	  break;
++
++	case E_AVR_MACH_XMEGA6:
++	  e_set = bfd_mach_avrxmega6;
++	  break;
++
++	case E_AVR_MACH_XMEGA7:
++	  e_set = bfd_mach_avrxmega7;
++	  break;
+ 	}
+     }
+   return bfd_default_set_arch_mach (abfd, bfd_arch_avr,
+diff -Nur ../binutils-2.20.orig/gas/config/tc-avr.c ./gas/config/tc-avr.c
+--- ../binutils-2.20.orig/gas/config/tc-avr.c	2010-03-04 11:19:26.000000000 +0100
++++ ./gas/config/tc-avr.c	2010-03-04 11:34:09.000000000 +0100
+@@ -27,20 +27,21 @@
+ 
+ struct avr_opcodes_s
+ {
+-  char *        name;
+-  char *        constraints;
+-  int           insn_size;		/* In words.  */
+-  int           isa;
++  char *name;
++  char *constraints;
++  char *opcode;
++  int insn_size;		/* In words.  */
++  int isa;
+   unsigned int  bin_opcode;
+ };
+ 
+ #define AVR_INSN(NAME, CONSTR, OPCODE, SIZE, ISA, BIN) \
+-{#NAME, CONSTR, SIZE, ISA, BIN},
++{#NAME, CONSTR, OPCODE, SIZE, ISA, BIN},
+ 
+ struct avr_opcodes_s avr_opcodes[] =
+ {
+   #include "opcode/avr.h"
+-  {NULL, NULL, 0, 0, 0}
++  {NULL, NULL, NULL, 0, 0, 0}
+ };
+ 
+ const char comment_chars[] = ";";
+@@ -79,6 +80,13 @@
+   {"avr5",       AVR_ISA_AVR51,   bfd_mach_avr5},
+   {"avr51",      AVR_ISA_AVR51,   bfd_mach_avr51},
+   {"avr6",       AVR_ISA_AVR6,    bfd_mach_avr6},
++  {"avrxmega1",  AVR_ISA_XMEGA,   bfd_mach_avrxmega1},
++  {"avrxmega2",  AVR_ISA_XMEGA,   bfd_mach_avrxmega2},
++  {"avrxmega3",  AVR_ISA_XMEGA,   bfd_mach_avrxmega3},
++  {"avrxmega4",  AVR_ISA_XMEGA,   bfd_mach_avrxmega4},
++  {"avrxmega5",  AVR_ISA_XMEGA,   bfd_mach_avrxmega5},
++  {"avrxmega6",  AVR_ISA_XMEGA,   bfd_mach_avrxmega6},
++  {"avrxmega7",  AVR_ISA_XMEGA,   bfd_mach_avrxmega7},
+   {"at90s1200",  AVR_ISA_1200,    bfd_mach_avr1},
+   {"attiny11",   AVR_ISA_AVR1,    bfd_mach_avr1},
+   {"attiny12",   AVR_ISA_AVR1,    bfd_mach_avr1},
+@@ -241,6 +249,21 @@
+   {"m3001b",     AVR_ISA_AVR51,   bfd_mach_avr51},
+   {"atmega2560", AVR_ISA_AVR6,    bfd_mach_avr6},
+   {"atmega2561", AVR_ISA_AVR6,    bfd_mach_avr6},
++  {"atxmega16a4", AVR_ISA_XMEGA,  bfd_mach_avrxmega2},
++  {"atxmega16d4", AVR_ISA_XMEGA,  bfd_mach_avrxmega2},
++  {"atxmega32d4", AVR_ISA_XMEGA,  bfd_mach_avrxmega2},
++  {"atxmega32a4", AVR_ISA_XMEGA,  bfd_mach_avrxmega3},
++  {"atxmega64a3", AVR_ISA_XMEGA,  bfd_mach_avrxmega4},
++  {"atxmega64d3", AVR_ISA_XMEGA,  bfd_mach_avrxmega4},
++  {"atxmega64a1", AVR_ISA_XMEGA,  bfd_mach_avrxmega5},
++  {"atxmega128a3", AVR_ISA_XMEGA, bfd_mach_avrxmega6},
++  {"atxmega128d3", AVR_ISA_XMEGA, bfd_mach_avrxmega6},
++  {"atxmega192a3", AVR_ISA_XMEGA, bfd_mach_avrxmega6},
++  {"atxmega192d3", AVR_ISA_XMEGA, bfd_mach_avrxmega6},
++  {"atxmega256a3", AVR_ISA_XMEGA, bfd_mach_avrxmega6},
++  {"atxmega256a3b",AVR_ISA_XMEGA, bfd_mach_avrxmega6},
++  {"atxmega256d3", AVR_ISA_XMEGA, bfd_mach_avrxmega6},
++  {"atxmega128a1", AVR_ISA_XMEGA, bfd_mach_avrxmega7},
+   {NULL, 0, 0}
+ };
+ 
+@@ -418,6 +441,11 @@
+ 	"                   avr5  - enhanced AVR core with up to 64K program memory\n"
+ 	"                   avr51 - enhanced AVR core with up to 128K program memory\n"
+ 	"                   avr6  - enhanced AVR core with up to 256K program memory\n"
++	"                   avrxmega3 - XMEGA, > 8K, <= 64K FLASH, > 64K RAM\n"
++	"                   avrxmega4 - XMEGA, > 64K, <= 128K FLASH, <= 64K RAM\n"
++	"                   avrxmega5 - XMEGA, > 64K, <= 128K FLASH, > 64K RAM\n"
++	"                   avrxmega6 - XMEGA, > 128K, <= 256K FLASH, <= 64K RAM\n"
++	"                   avrxmega7 - XMEGA, > 128K, <= 256K FLASH, > 64K RAM\n"
+ 	"                   or immediate microcontroller name.\n"));
+   fprintf (stream,
+       _("  -mall-opcodes    accept all AVR opcodes, even if not supported by MCU\n"
+@@ -845,7 +873,12 @@
+       if (*str == '+')
+ 	{
+ 	  ++str;
+-	  op_mask |= 1;
++          char *s;
++          for (s = opcode->opcode; *s; ++s)
++            {
++              if (*s == '+')
++                op_mask |= (1 << (15 - (s - opcode->opcode)));
++            }
+ 	}
+ 
+       /* attiny26 can do "lpm" and "lpm r,Z" but not "lpm r,Z+".  */
+@@ -962,6 +995,16 @@
+       }
+       break;
+ 
++    case 'E':
++      {
++	unsigned int x;
++
++	x = avr_get_constant (str, 15);
++	str = input_line_pointer;
++	op_mask |= (x << 4);
++      }
++      break;
++    
+     case '?':
+       break;
+ 
+diff -Nur ../binutils-2.20.orig/gas/doc/c-avr.texi ./gas/doc/c-avr.texi
+--- ../binutils-2.20.orig/gas/doc/c-avr.texi	2010-03-04 11:19:26.000000000 +0100
++++ ./gas/doc/c-avr.texi	2010-03-04 11:34:09.000000000 +0100
+@@ -86,6 +86,27 @@
+ Instruction set avr6 is for the enhanced AVR core with a 3-byte PC (MCU types:
+ atmega2560, atmega2561).
+ 
++Instruction set avrxmega2 is for the XMEGA AVR core with 8K to 64K program
++memory space and less than 64K data space (MCU types: atxmega16a4, atxmega16d4,
++atxmega32d4).
++
++Instruction set avrxmega3 is for the XMEGA AVR core with 8K to 64K program
++memory space and greater than 64K data space (MCU types: atxmega32a4).
++
++Instruction set avrxmega4 is for the XMEGA AVR core with up to 64K program
++memory space and less than 64K data space (MCU types: atxmega64a3, atxmega64d3).
++
++Instruction set avrxmega5 is for the XMEGA AVR core with up to 64K program 
++memory space and greater than 64K data space (MCU types: atxmega64a1).
++
++Instruction set avrxmega6 is for the XMEGA AVR core with up to 256K program
++memory space and less than 64K data space (MCU types: atxmega128a3,
++atxmega128d3, atxmega192a3, atxmega192d3, atxmega256a3, atxmega256a3b,
++atxmega192d3).
++
++Instruction set avrxmega7 is for the XMEGA AVR core with up to 256K program
++memory space and greater than 64K data space (MCU types: atxmega128a1).
++
+ @cindex @code{-mall-opcodes} command line option, AVR
+ @item -mall-opcodes
+ Accept all AVR opcodes, even if not supported by @code{-mmcu}.
+diff -Nur ../binutils-2.20.orig/include/elf/avr.h ./include/elf/avr.h
+--- ../binutils-2.20.orig/include/elf/avr.h	2008-08-09 07:35:13.000000000 +0200
++++ ./include/elf/avr.h	2010-03-04 11:34:09.000000000 +0100
+@@ -40,6 +40,13 @@
+ #define E_AVR_MACH_AVR5 5
+ #define E_AVR_MACH_AVR51 51
+ #define E_AVR_MACH_AVR6 6 
++#define E_AVR_MACH_XMEGA1 101
++#define E_AVR_MACH_XMEGA2 102
++#define E_AVR_MACH_XMEGA3 103
++#define E_AVR_MACH_XMEGA4 104
++#define E_AVR_MACH_XMEGA5 105
++#define E_AVR_MACH_XMEGA6 106
++#define E_AVR_MACH_XMEGA7 107
+ 
+ /* Relocations.  */
+ START_RELOC_NUMBERS (elf_avr_reloc_type)
+diff -Nur ../binutils-2.20.orig/include/opcode/avr.h ./include/opcode/avr.h
+--- ../binutils-2.20.orig/include/opcode/avr.h	2008-08-09 07:35:13.000000000 +0200
++++ ./include/opcode/avr.h	2010-03-04 11:34:09.000000000 +0100
+@@ -30,6 +30,8 @@
+ #define AVR_ISA_BRK   0x0400 /* device has BREAK (on-chip debug) */
+ #define AVR_ISA_EIND  0x0800 /* device has >128K program memory (none yet) */
+ #define AVR_ISA_MOVW  0x1000 /* device has MOVW */
++#define AVR_ISA_SPMX  0x2000 /* device has SPM Z[+] */
++#define AVR_ISA_DES   0x4000 /* device has DES */
+ 
+ #define AVR_ISA_TINY1 (AVR_ISA_1200 | AVR_ISA_LPM)
+ #define AVR_ISA_2xxx  (AVR_ISA_TINY1 | AVR_ISA_SRAM)
+@@ -48,6 +50,8 @@
+ #define AVR_ISA_94K   (AVR_ISA_M603 | AVR_ISA_MUL | AVR_ISA_MOVW | AVR_ISA_LPMX)
+ #define AVR_ISA_M323  (AVR_ISA_M161 | AVR_ISA_BRK)
+ #define AVR_ISA_M128  (AVR_ISA_M323 | AVR_ISA_ELPM | AVR_ISA_ELPMX)
++#define AVR_ISA_M256  (AVR_ISA_M128 | AVR_ISA_EIND)
++#define AVR_ISA_XMEGA (AVR_ISA_M256 | AVR_ISA_SPMX | AVR_ISA_DES)
+ 
+ #define AVR_ISA_AVR1   AVR_ISA_TINY1
+ #define AVR_ISA_AVR2   AVR_ISA_2xxx
+@@ -108,6 +112,7 @@
+    L - signed pc relative offset from -2048 to 2047
+    h - absolute code address (call, jmp)
+    S - immediate value from 0 to 7 (S = s << 4)
++   E - immediate value from 0 to 15, shifted left by 4 (des)
+    ? - use this opcode entry if no parameters, else use next opcode entry
+ 
+    Order is important - some binary opcodes have more than one name,
+@@ -168,7 +173,8 @@
+ AVR_INSN (sleep,"",    "1001010110001000", 1, AVR_ISA_1200, 0x9588)
+ AVR_INSN (break,"",    "1001010110011000", 1, AVR_ISA_BRK,  0x9598)
+ AVR_INSN (wdr,  "",    "1001010110101000", 1, AVR_ISA_1200, 0x95a8)
+-AVR_INSN (spm,  "",    "1001010111101000", 1, AVR_ISA_SPM,  0x95e8)
++AVR_INSN (spm,  "?",   "1001010111101000", 1, AVR_ISA_SPM,  0x95e8)
++AVR_INSN (spm,  "z",   "10010101111+1000", 1, AVR_ISA_SPMX, 0x95e8)
+ 
+ AVR_INSN (adc,  "r,r", "000111rdddddrrrr", 1, AVR_ISA_1200, 0x1c00)
+ AVR_INSN (add,  "r,r", "000011rdddddrrrr", 1, AVR_ISA_1200, 0x0c00)
+@@ -282,3 +288,6 @@
+ AVR_INSN (eicall, "",  "1001010100011001", 1, AVR_ISA_EIND, 0x9519)
+ AVR_INSN (eijmp, "",   "1001010000011001", 1, AVR_ISA_EIND, 0x9419)
+ 
++/* DES instruction for encryption and decryption */
++AVR_INSN (des,  "E",   "10010100EEEE1011", 1, AVR_ISA_DES,  0x940B)
++
+diff -Nur ../binutils-2.20.orig/ld/Makefile.am ./ld/Makefile.am
+--- ../binutils-2.20.orig/ld/Makefile.am	2009-09-01 22:56:51.000000000 +0200
++++ ./ld/Makefile.am	2010-03-04 11:34:09.000000000 +0100
+@@ -148,6 +148,13 @@
+ 	eavr5.o \
+ 	eavr51.o \
+ 	eavr6.o \
++	eavrxmega1.o \
++	eavrxmega2.o \
++	eavrxmega3.o \
++	eavrxmega4.o \
++	eavrxmega5.o \
++	eavrxmega6.o \
++	eavrxmega7.o \
+ 	ecoff_i860.o \
+ 	ecoff_sparc.o \
+ 	eelf32_spu.o \
+@@ -727,6 +734,34 @@
+   $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
+   ${GEN_DEPENDS}
+ 	${GENSCRIPTS} avr6 "$(tdir_avr2)"
++eavrxmega1.c: $(srcdir)/emulparams/avrxmega1.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega1 "$(tdir_avr2)"
++eavrxmega2.c: $(srcdir)/emulparams/avrxmega2.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega2 "$(tdir_avr2)"
++eavrxmega3.c: $(srcdir)/emulparams/avrxmega3.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega3 "$(tdir_avr2)"
++eavrxmega4.c: $(srcdir)/emulparams/avrxmega4.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega4 "$(tdir_avr2)"
++eavrxmega5.c: $(srcdir)/emulparams/avrxmega5.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega5 "$(tdir_avr2)"
++eavrxmega6.c: $(srcdir)/emulparams/avrxmega6.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega6 "$(tdir_avr2)"
++eavrxmega7.c: $(srcdir)/emulparams/avrxmega7.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega7 "$(tdir_avr2)"
+ ecoff_i860.c: $(srcdir)/emulparams/coff_i860.sh \
+   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/i860coff.sc ${GEN_DEPENDS}
+ 	${GENSCRIPTS} coff_i860 "$(tdir_coff_i860)"
+diff -Nur ../binutils-2.20.orig/ld/Makefile.in ./ld/Makefile.in
+--- ../binutils-2.20.orig/ld/Makefile.in	2009-09-07 14:10:24.000000000 +0200
++++ ./ld/Makefile.in	2010-03-04 11:34:09.000000000 +0100
+@@ -434,6 +434,13 @@
+ 	eavr5.o \
+ 	eavr51.o \
+ 	eavr6.o \
++	eavrxmega1.o \
++	eavrxmega2.o \
++	eavrxmega3.o \
++	eavrxmega4.o \
++	eavrxmega5.o \
++	eavrxmega6.o \
++	eavrxmega7.o \
+ 	ecoff_i860.o \
+ 	ecoff_sparc.o \
+ 	eelf32_spu.o \
+@@ -2068,6 +2075,34 @@
+   $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
+   ${GEN_DEPENDS}
+ 	${GENSCRIPTS} avr6 "$(tdir_avr2)"
++eavrxmega1.c: $(srcdir)/emulparams/avrxmega1.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega1 "$(tdir_avr2)"
++eavrxmega2.c: $(srcdir)/emulparams/avrxmega2.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega2 "$(tdir_avr2)"
++eavrxmega3.c: $(srcdir)/emulparams/avrxmega3.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega3 "$(tdir_avr2)"
++eavrxmega4.c: $(srcdir)/emulparams/avrxmega4.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega4 "$(tdir_avr2)"
++eavrxmega5.c: $(srcdir)/emulparams/avrxmega5.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega5 "$(tdir_avr2)"
++eavrxmega6.c: $(srcdir)/emulparams/avrxmega6.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega6 "$(tdir_avr2)"
++eavrxmega7.c: $(srcdir)/emulparams/avrxmega7.sh \
++  $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \
++  ${GEN_DEPENDS}
++	${GENSCRIPTS} avrxmega7 "$(tdir_avr2)"
+ ecoff_i860.c: $(srcdir)/emulparams/coff_i860.sh \
+   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/i860coff.sc ${GEN_DEPENDS}
+ 	${GENSCRIPTS} coff_i860 "$(tdir_coff_i860)"
+diff -Nur ../binutils-2.20.orig/ld/configure.tgt ./ld/configure.tgt
+--- ../binutils-2.20.orig/ld/configure.tgt	2009-08-06 19:38:03.000000000 +0200
++++ ./ld/configure.tgt	2010-03-04 11:34:09.000000000 +0100
+@@ -110,7 +110,7 @@
+ xscale-*-elf)		targ_emul=armelf
+ 			;;
+ avr-*-*)		targ_emul=avr2
+-			targ_extra_emuls="avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6"
++			targ_extra_emuls="avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7"
+ 			;;
+ bfin-*-elf)		targ_emul=elf32bfin;
+ 			targ_extra_emuls="elf32bfinfd"
+diff -Nur ../binutils-2.20.orig/ld/emulparams/avrxmega1.sh ./ld/emulparams/avrxmega1.sh
+--- ../binutils-2.20.orig/ld/emulparams/avrxmega1.sh	1970-01-01 01:00:00.000000000 +0100
++++ ./ld/emulparams/avrxmega1.sh	2010-03-04 11:34:09.000000000 +0100
+@@ -0,0 +1,12 @@
++ARCH=avr:101
++MACHINE=
++SCRIPT_NAME=avr
++OUTPUT_FORMAT="elf32-avr"
++MAXPAGESIZE=1
++EMBEDDED=yes
++TEMPLATE_NAME=elf32
++
++TEXT_LENGTH=1024K
++DATA_ORIGIN=0x802000
++DATA_LENGTH=0xffa0
++EXTRA_EM_FILE=avrelf
+diff -Nur ../binutils-2.20.orig/ld/emulparams/avrxmega2.sh ./ld/emulparams/avrxmega2.sh
+--- ../binutils-2.20.orig/ld/emulparams/avrxmega2.sh	1970-01-01 01:00:00.000000000 +0100
++++ ./ld/emulparams/avrxmega2.sh	2010-03-04 11:34:09.000000000 +0100
+@@ -0,0 +1,12 @@
++ARCH=avr:102
++MACHINE=
++SCRIPT_NAME=avr
++OUTPUT_FORMAT="elf32-avr"
++MAXPAGESIZE=1
++EMBEDDED=yes
++TEMPLATE_NAME=elf32
++
++TEXT_LENGTH=1024K
++DATA_ORIGIN=0x802000
++DATA_LENGTH=0xffa0
++EXTRA_EM_FILE=avrelf
+diff -Nur ../binutils-2.20.orig/ld/emulparams/avrxmega3.sh ./ld/emulparams/avrxmega3.sh
+--- ../binutils-2.20.orig/ld/emulparams/avrxmega3.sh	1970-01-01 01:00:00.000000000 +0100
++++ ./ld/emulparams/avrxmega3.sh	2010-03-04 11:34:09.000000000 +0100
+@@ -0,0 +1,12 @@
++ARCH=avr:103
++MACHINE=
++SCRIPT_NAME=avr
++OUTPUT_FORMAT="elf32-avr"
++MAXPAGESIZE=1
++EMBEDDED=yes
++TEMPLATE_NAME=elf32
++
++TEXT_LENGTH=1024K
++DATA_ORIGIN=0x802000
++DATA_LENGTH=0xffa0
++EXTRA_EM_FILE=avrelf
+diff -Nur ../binutils-2.20.orig/ld/emulparams/avrxmega4.sh ./ld/emulparams/avrxmega4.sh
+--- ../binutils-2.20.orig/ld/emulparams/avrxmega4.sh	1970-01-01 01:00:00.000000000 +0100
++++ ./ld/emulparams/avrxmega4.sh	2010-03-04 11:34:09.000000000 +0100
+@@ -0,0 +1,12 @@
++ARCH=avr:104
++MACHINE=
++SCRIPT_NAME=avr
++OUTPUT_FORMAT="elf32-avr"
++MAXPAGESIZE=1
++EMBEDDED=yes
++TEMPLATE_NAME=elf32
++
++TEXT_LENGTH=1024K
++DATA_ORIGIN=0x802000
++DATA_LENGTH=0xffa0
++EXTRA_EM_FILE=avrelf
+diff -Nur ../binutils-2.20.orig/ld/emulparams/avrxmega5.sh ./ld/emulparams/avrxmega5.sh
+--- ../binutils-2.20.orig/ld/emulparams/avrxmega5.sh	1970-01-01 01:00:00.000000000 +0100
++++ ./ld/emulparams/avrxmega5.sh	2010-03-04 11:34:09.000000000 +0100
+@@ -0,0 +1,12 @@
++ARCH=avr:105
++MACHINE=
++SCRIPT_NAME=avr
++OUTPUT_FORMAT="elf32-avr"
++MAXPAGESIZE=1
++EMBEDDED=yes
++TEMPLATE_NAME=elf32
++
++TEXT_LENGTH=1024K
++DATA_ORIGIN=0x802000
++DATA_LENGTH=0xffa0
++EXTRA_EM_FILE=avrelf
+diff -Nur ../binutils-2.20.orig/ld/emulparams/avrxmega6.sh ./ld/emulparams/avrxmega6.sh
+--- ../binutils-2.20.orig/ld/emulparams/avrxmega6.sh	1970-01-01 01:00:00.000000000 +0100
++++ ./ld/emulparams/avrxmega6.sh	2010-03-04 11:34:09.000000000 +0100
+@@ -0,0 +1,12 @@
++ARCH=avr:106
++MACHINE=
++SCRIPT_NAME=avr
++OUTPUT_FORMAT="elf32-avr"
++MAXPAGESIZE=1
++EMBEDDED=yes
++TEMPLATE_NAME=elf32
++
++TEXT_LENGTH=1024K
++DATA_ORIGIN=0x802000
++DATA_LENGTH=0xffa0
++EXTRA_EM_FILE=avrelf
+diff -Nur ../binutils-2.20.orig/ld/emulparams/avrxmega7.sh ./ld/emulparams/avrxmega7.sh
+--- ../binutils-2.20.orig/ld/emulparams/avrxmega7.sh	1970-01-01 01:00:00.000000000 +0100
++++ ./ld/emulparams/avrxmega7.sh	2010-03-04 11:34:09.000000000 +0100
+@@ -0,0 +1,12 @@
++ARCH=avr:107
++MACHINE=
++SCRIPT_NAME=avr
++OUTPUT_FORMAT="elf32-avr"
++MAXPAGESIZE=1
++EMBEDDED=yes
++TEMPLATE_NAME=elf32
++
++TEXT_LENGTH=1024K
++DATA_ORIGIN=0x802000
++DATA_LENGTH=0xffa0
++EXTRA_EM_FILE=avrelf
+diff -Nur ../binutils-2.20.orig/ld/emultempl/avrelf.em ./ld/emultempl/avrelf.em
+--- ../binutils-2.20.orig/ld/emultempl/avrelf.em	2009-09-02 09:25:35.000000000 +0200
++++ ./ld/emultempl/avrelf.em	2010-03-04 11:34:09.000000000 +0100
+@@ -71,8 +71,10 @@
+ 
+   gld${EMULATION_NAME}_before_allocation ();
+ 
+-  /* We only need stubs for the avr6 family.  */
+-  if (strcmp ("${EMULATION_NAME}","avr6"))
++  /* We only need stubs for avr6, avrxmega6, and avrxmega7. */
++  if (strcmp ("${EMULATION_NAME}","avr6") 
++      && strcmp ("${EMULATION_NAME}","avrxmega6")
++      && strcmp ("${EMULATION_NAME}","avrxmega7") )
+     avr_no_stubs = TRUE;
+ 
+   avr_elf_set_global_bfd_parameters ();
+diff -Nur ../binutils-2.20.orig/opcodes/avr-dis.c ./opcodes/avr-dis.c
+--- ../binutils-2.20.orig/opcodes/avr-dis.c	2008-11-06 13:03:24.000000000 +0100
++++ ./opcodes/avr-dis.c	2010-03-04 11:34:09.000000000 +0100
+@@ -50,7 +50,7 @@
+ 
+ static int
+ avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constraint,
+-             char *buf, char *comment, int regs, int *sym, bfd_vma *sym_addr)
++             char *opcode_str, char *buf, char *comment, int regs, int *sym, bfd_vma *sym_addr)
+ {
+   int ok = 1;
+   *sym = 0;
+@@ -118,8 +118,18 @@
+ 
+     case 'z':
+       *buf++ = 'Z';
+-      if (insn & 0x1)
+-	*buf++ = '+';
++
++      /* Check for post-increment. */
++      char *s;
++      for (s = opcode_str; *s; ++s)
++        {
++          if (*s == '+')
++            {
++              *buf++ = '+';
++              break;
++            }
++        }
++
+       *buf = '\0';
+       if (AVR_UNDEF_P (insn))
+ 	sprintf (comment, _("undefined"));
+@@ -226,6 +236,10 @@
+ 	sprintf (comment, "%d", x);
+       }
+       break;
++
++    case 'E':
++      sprintf (buf, "%d", (insn >> 4) & 15);
++      break;
+       
+     case '?':
+       *buf = '\0';
+@@ -331,7 +345,8 @@
+ 
+   if (opcode->name)
+     {
+-      char *op = opcode->constraints;
++      char *constraints = opcode->constraints;
++      char *opcode_str = opcode->opcode;
+ 
+       insn2 = 0;
+       ok = 1;
+@@ -342,14 +357,14 @@
+ 	  cmd_len = 4;
+ 	}
+ 
+-      if (*op && *op != '?')
++      if (*constraints && *constraints != '?')
+ 	{
+-	  int regs = REGISTER_P (*op);
++	  int regs = REGISTER_P (*constraints);
+ 
+-	  ok = avr_operand (insn, insn2, addr, *op, op1, comment1, 0, &sym_op1, &sym_addr1);
++	  ok = avr_operand (insn, insn2, addr, *constraints, opcode_str, op1, comment1, 0, &sym_op1, &sym_addr1);
+ 
+-	  if (ok && *(++op) == ',')
+-	    ok = avr_operand (insn, insn2, addr, *(++op), op2,
++	  if (ok && *(++constraints) == ',')
++	    ok = avr_operand (insn, insn2, addr, *(++constraints), opcode_str, op2,
+ 			      *comment1 ? comment2 : comment1, regs, &sym_op2, &sym_addr2);
+ 	}
+     }
