From 92a8e8195459dede059de04a50412743b8c6e1b5 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Tue, 7 Jul 2015 08:44:15 +0200 Subject: binutils: move patches: 2.20.1 -> 2.20.1a Signed-off-by: Michael Olbrich --- ...disable-some-docs-to-avoid-using-makeinfo.patch | 39 - ...VR-specific-output-format-to-size-utility.patch | 560 -- ...Atmels-AVR-COFF-output-to-objcopy-utility.patch | 5864 -------------------- ...ory-regions-to-the-AVR-linker-script-temp.patch | 65 - ...4-Fix-missing-symbol-for-dwarf2_emit_insn.patch | 43 - .../0005-Force-DWARF2-debug-output-for-AVR.patch | 51 - ...06-Add-support-for-XMEGA-arch-and-devices.patch | 733 --- .../0007-Add-remove-support-for-devices.patch | 253 - ...-support-for-devices-with-16-gp-registers.patch | 283 - .../0009-Add-support-for-more-XMEGA-devices.patch | 101 - patches/binutils-2.20.1/series | 13 - ...disable-some-docs-to-avoid-using-makeinfo.patch | 39 + ...VR-specific-output-format-to-size-utility.patch | 560 ++ ...Atmels-AVR-COFF-output-to-objcopy-utility.patch | 5864 ++++++++++++++++++++ ...ory-regions-to-the-AVR-linker-script-temp.patch | 65 + ...4-Fix-missing-symbol-for-dwarf2_emit_insn.patch | 43 + .../0005-Force-DWARF2-debug-output-for-AVR.patch | 51 + ...06-Add-support-for-XMEGA-arch-and-devices.patch | 733 +++ .../0007-Add-remove-support-for-devices.patch | 253 + ...-support-for-devices-with-16-gp-registers.patch | 283 + .../0009-Add-support-for-more-XMEGA-devices.patch | 101 + patches/binutils-2.20.1a/series | 13 + 22 files changed, 8005 insertions(+), 8005 deletions(-) delete mode 100644 patches/binutils-2.20.1/0001-HACK-disable-some-docs-to-avoid-using-makeinfo.patch delete mode 100644 patches/binutils-2.20.1/atmel/0001-Add-AVR-specific-output-format-to-size-utility.patch delete mode 100644 patches/binutils-2.20.1/atmel/0002-Add-Atmels-AVR-COFF-output-to-objcopy-utility.patch delete mode 100644 patches/binutils-2.20.1/atmel/0003-Add-new-memory-regions-to-the-AVR-linker-script-temp.patch delete mode 100644 patches/binutils-2.20.1/atmel/0004-Fix-missing-symbol-for-dwarf2_emit_insn.patch delete mode 100644 patches/binutils-2.20.1/atmel/0005-Force-DWARF2-debug-output-for-AVR.patch delete mode 100644 patches/binutils-2.20.1/atmel/0006-Add-support-for-XMEGA-arch-and-devices.patch delete mode 100644 patches/binutils-2.20.1/atmel/0007-Add-remove-support-for-devices.patch delete mode 100644 patches/binutils-2.20.1/atmel/0008-Add-support-for-devices-with-16-gp-registers.patch delete mode 100644 patches/binutils-2.20.1/atmel/0009-Add-support-for-more-XMEGA-devices.patch delete mode 100644 patches/binutils-2.20.1/series create mode 100644 patches/binutils-2.20.1a/0001-HACK-disable-some-docs-to-avoid-using-makeinfo.patch create mode 100644 patches/binutils-2.20.1a/atmel/0001-Add-AVR-specific-output-format-to-size-utility.patch create mode 100644 patches/binutils-2.20.1a/atmel/0002-Add-Atmels-AVR-COFF-output-to-objcopy-utility.patch create mode 100644 patches/binutils-2.20.1a/atmel/0003-Add-new-memory-regions-to-the-AVR-linker-script-temp.patch create mode 100644 patches/binutils-2.20.1a/atmel/0004-Fix-missing-symbol-for-dwarf2_emit_insn.patch create mode 100644 patches/binutils-2.20.1a/atmel/0005-Force-DWARF2-debug-output-for-AVR.patch create mode 100644 patches/binutils-2.20.1a/atmel/0006-Add-support-for-XMEGA-arch-and-devices.patch create mode 100644 patches/binutils-2.20.1a/atmel/0007-Add-remove-support-for-devices.patch create mode 100644 patches/binutils-2.20.1a/atmel/0008-Add-support-for-devices-with-16-gp-registers.patch create mode 100644 patches/binutils-2.20.1a/atmel/0009-Add-support-for-more-XMEGA-devices.patch create mode 100644 patches/binutils-2.20.1a/series diff --git a/patches/binutils-2.20.1/0001-HACK-disable-some-docs-to-avoid-using-makeinfo.patch b/patches/binutils-2.20.1/0001-HACK-disable-some-docs-to-avoid-using-makeinfo.patch deleted file mode 100644 index 94e8812..0000000 --- a/patches/binutils-2.20.1/0001-HACK-disable-some-docs-to-avoid-using-makeinfo.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: Michael Olbrich -Date: Mon, 10 Jun 2013 09:11:36 +0200 -Subject: [PATCH] HACK: disable some docs to avoid using makeinfo - -Patching Makefile.in because running automake fails. - -Signed-off-by: Michael Olbrich ---- - bfd/Makefile.in | 1 - - gas/Makefile.in | 1 - - 2 files changed, 2 deletions(-) - -diff --git a/bfd/Makefile.in b/bfd/Makefile.in -index 696b628..f779d38 100644 ---- a/bfd/Makefile.in -+++ b/bfd/Makefile.in -@@ -320,7 +320,6 @@ ACLOCAL_AMFLAGS = -I . -I .. -I ../config - # RELEASE=y - INCDIR = $(srcdir)/../include - CSEARCH = -I. -I$(srcdir) -I$(INCDIR) --SUBDIRS = doc po - bfddocdir = doc - libbfd_la_LDFLAGS = $(am__append_1) -release `cat libtool-soversion` \ - @SHARED_LDFLAGS@ $(am__empty) -diff --git a/gas/Makefile.in b/gas/Makefile.in -index 0b11739..cd3de73 100644 ---- a/gas/Makefile.in -+++ b/gas/Makefile.in -@@ -278,7 +278,6 @@ top_builddir = @top_builddir@ - top_srcdir = @top_srcdir@ - AUTOMAKE_OPTIONS = 1.11 dejagnu foreign no-dist - ACLOCAL_AMFLAGS = -I .. -I ../config -I ../bfd --SUBDIRS = doc po - tooldir = $(exec_prefix)/$(target_alias) - - # Automake 1.10+ disables lex and yacc output file regeneration if --- -1.8.2.rc2 - diff --git a/patches/binutils-2.20.1/atmel/0001-Add-AVR-specific-output-format-to-size-utility.patch b/patches/binutils-2.20.1/atmel/0001-Add-AVR-specific-output-format-to-size-utility.patch deleted file mode 100644 index 3fbb653..0000000 --- a/patches/binutils-2.20.1/atmel/0001-Add-AVR-specific-output-format-to-size-utility.patch +++ /dev/null @@ -1,560 +0,0 @@ -From 16ed0c7147c272be68aafe0cc42a2bc390f8efff Mon Sep 17 00:00:00 2001 -From: Stephan Linz -Date: Mon, 18 Apr 2011 19:48:27 +0200 -Subject: [PATCH 1/9] Add AVR specific output format to size utility - -Add a new AVR specific output format with more details about memory -saturation (absolute and relative in percent). The size utility gets -the command line options -C (short) and --format=avr (long). Both -options force the new command line option --mcu=. - -With this patch the size utility gets a AVR specific device database -for memory size informations per chip. But this database is completely -independent from the global binutils BFD/MACH database. - -To select an entry in the size utility internal device database you -have to use the new command line option --mcu=. - -Original ATMEL patch from: -http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/30-binutils-2.20.1-avr-size.patch - -Signed-off-by: Stephan Linz ---- - binutils/size.c | 419 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- - 1 files changed, 398 insertions(+), 21 deletions(-) - -diff --git a/binutils/size.c b/binutils/size.c -index 835aaa7..cd1635a 100644 ---- a/binutils/size.c -+++ b/binutils/size.c -@@ -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,249 @@ 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}, -+ {"atxmega128a1u", 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}, -+ {"atxmega64a1u", 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}, -+ {"m3000", AVR64K, AVR4K, 0UL}, -+ -+ {"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}, -+ {"atmega325a", AVR32K, AVR2K, AVR1K}, -+ {"atmega325p", AVR32K, AVR2K, AVR1K}, -+ {"atmega3250", AVR32K, AVR2K, AVR1K}, -+ {"atmega3250a", AVR32K, AVR2K, AVR1K}, -+ {"atmega3250p", AVR32K, AVR2K, AVR1K}, -+ {"atmega328", AVR32K, AVR2K, AVR1K}, -+ {"atmega328p", AVR32K, AVR2K, AVR1K}, -+ {"atmega329", AVR32K, AVR2K, AVR1K}, -+ {"atmega329a", AVR32K, AVR2K, AVR1K}, -+ {"atmega329p", AVR32K, AVR2K, AVR1K}, -+ {"atmega329pa", AVR32K, AVR2K, AVR1K}, -+ {"atmega3290", AVR32K, AVR2K, AVR1K}, -+ {"atmega3290a", AVR32K, AVR2K, AVR1K}, -+ {"atmega3290p", AVR32K, AVR2K, AVR1K}, -+ {"atmega32hvb", AVR32K, AVR2K, AVR1K}, -+ {"atmega32c1", AVR32K, AVR2K, AVR1K}, -+ {"atmega32hvb", AVR32K, AVR2K, AVR1K}, -+ {"atmega32m1", AVR32K, AVR2K, AVR1K}, -+ {"attiny327", AVR32K, AVR2K, AVR1K}, -+ {"atmega32u2", AVR32K, AVR2K, 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}, -+ {"atmega8hvd", AVR8K, AVR512, AVR256}, -+ {"attiny84", AVR8K, AVR512, AVR512}, -+ {"attiny84a", 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}, -+ {"atmega4hvd", 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 +342,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= 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 +352,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 +363,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 +371,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 +403,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 +412,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 +428,10 @@ main (int argc, char **argv) - } - break; - -+ case OPTION_MCU: -+ avrmcu = optarg; -+ break; -+ - case OPTION_TARGET: - target = optarg; - break; -@@ -190,10 +460,13 @@ 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': -@@ -240,7 +513,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; - -@@ -406,7 +679,7 @@ display_file (char *filename) - return; - } - } -- -+ - static int - size_number (bfd_size_type num) - { -@@ -599,13 +872,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; -+ } - } --- -1.6.0.4 - diff --git a/patches/binutils-2.20.1/atmel/0002-Add-Atmels-AVR-COFF-output-to-objcopy-utility.patch b/patches/binutils-2.20.1/atmel/0002-Add-Atmels-AVR-COFF-output-to-objcopy-utility.patch deleted file mode 100644 index 7c9c400..0000000 --- a/patches/binutils-2.20.1/atmel/0002-Add-Atmels-AVR-COFF-output-to-objcopy-utility.patch +++ /dev/null @@ -1,5864 +0,0 @@ -From b88360877c2d1143074ea8d9bae2bdf9a104743a Mon Sep 17 00:00:00 2001 -From: Stephan Linz -Date: Mon, 18 Apr 2011 20:41:41 +0200 -Subject: [PATCH 2/9] Add Atmels AVR COFF output to objcopy utility - -In order to convert the ELF format used in the opensource AVR -toolchain with its debugging information to the AVR COFF format as -defined by Atmel for its AVR Studio, the objcopy utility needs an -associated extension. - -There are two different file formats defined by Atmel, the original -AVR COFF format, and a newer version that is understood by AVR -Studio 4.07 and above called AVR Extended COFF. In order to provide -an easy way to distinguish both, two different BFD names have been -chose within GNU binutils, coff-avr for the former, coff-ext-avr -for the latter. - -More details at: -http://www.sax.de/~joerg/README.coff-avr-patch -http://www.amelek.gda.pl/avr/old/binutils/avrcoff.pdf - -Original ATMEL patch from: -http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/31-binutils-2.20.1-avr-coff.patch - -Signed-off-by: Stephan Linz ---- - bfd/Makefile.am | 4 + - bfd/Makefile.in | 4 + - bfd/README.coff-avr-patch | 264 ++++ - bfd/coff-avr.c | 613 ++++++++ - bfd/coff-ext-avr.c | 428 ++++++ - bfd/coffcode.h | 65 +- - bfd/coffgen.c | 63 +- - bfd/coffswap.h | 10 +- - bfd/config.bfd | 1 + - bfd/configure | 2 + - bfd/configure.in | 2 + - bfd/targets.c | 4 + - binutils/Makefile.am | 4 +- - binutils/Makefile.in | 6 +- - binutils/bucomm.c | 26 + - binutils/bucomm.h | 2 + - binutils/budbg.h | 5 +- - binutils/debug.c | 89 ++ - binutils/debug.h | 6 + - binutils/doc/objcopy.1 | 19 + - binutils/objcopy.c | 40 +- - binutils/rdcoff.c | 57 +- - binutils/wrcoff.c | 3410 +++++++++++++++++++++++++++++++++++++++++++++ - include/coff/avr.h | 110 ++ - include/coff/internal.h | 2 + - 25 files changed, 5199 insertions(+), 37 deletions(-) - create mode 100644 bfd/README.coff-avr-patch - create mode 100644 bfd/coff-avr.c - create mode 100644 bfd/coff-ext-avr.c - create mode 100644 binutils/wrcoff.c - create mode 100644 include/coff/avr.h - -diff --git a/bfd/Makefile.am b/bfd/Makefile.am -index 13ace29..9a12233 100644 ---- a/bfd/Makefile.am -+++ b/bfd/Makefile.am -@@ -228,6 +228,8 @@ BFD32_BACKENDS = \ - 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 @@ BFD32_BACKENDS_CFILES = \ - 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 --git a/bfd/Makefile.in b/bfd/Makefile.in -index 4068a2d..696b628 100644 ---- a/bfd/Makefile.in -+++ b/bfd/Makefile.in -@@ -524,6 +524,8 @@ BFD32_BACKENDS = \ - 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 @@ BFD32_BACKENDS_CFILES = \ - 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 --git a/bfd/README.coff-avr-patch b/bfd/README.coff-avr-patch -new file mode 100644 -index 0000000..1694089 ---- /dev/null -+++ b/bfd/README.coff-avr-patch -@@ -0,0 +1,264 @@ -+README for the »coff-avr-patch« 2003-05-16 -+=============================== -+ -+Background -+---------- -+ -+In order to convert the ELF format used in the opensource AVR -+toolchain (commonly known as just »avr-gcc«) with its debugging -+information that is called »stabs« to the AVR COFF format as defined -+by Atmel for its AVR Studio, two conversion steps are basically -+necessary: the object file format itself needs to be translated from -+ELF to COFF, which is a relatively simple conversion for the most -+part, since all the contents of the various sections of the object -+file can be copied verbatim, and the main change is a different object -+file header. The »objcopy« tool that comes with GNU binutils (called -+»avr-objcopy« in our case) has been designed for this kind of -+conversions, and the GNU binutils itself could already handle more -+than two dozens of different COFF file formats, so for most of the -+part, a common subset of COFF utilities could already be used. (COFF -+is a very old object file format that has been in wide use by end of -+the 1980s/beginning of the 1990s.) -+ -+There are two different file formats defined by Atmel, the original -+AVR COFF format, and a newer version that is understood by AVR Studio -+4.07 and above called AVR »extended« COFF. In order to provide an -+easy way to distinguish both, two different so-called BFD names have -+been chose within GNU binutils, coff-avr for the former, coff-ext-avr -+for the latter. (BFD stands for »binary filedescriptor« and is -+basically the central library of the GNU binutils suite that handles -+all the object file IO.) -+ -+In short, chose coff-ext-avr for AVR Studio 4.07 and above, and -+coff-avr for anything else (which includes AVR Studio 3.x, and VMLAB). -+The main differences are that the newer format can transport long -+filenames (so directory information will be retained), and has the -+option to debug struct types. -+ -+The tough part was to convert the stabs debugging information into the -+so-called native COFF debugging format, which is basically an -+extension of the symbol table that can usually be found in object file -+formats. Symbol tables provide a listing of names vs. object file -+sections plus addresses within that section, that can be displayed -+with the (avr-)nm tool. Now COFF has extended the meaning of a symbol -+by adding some debugging information to it within the symbol table. -+In contrast, the approach taken with ELF is to leave the symbol table -+as it is (the so-called non-debugging symbols), and add the debugging -+information in separate sections within the object file. Since the -+amount of information that can be transported by native COFF -+debugging, the approach to use (stabs) debugging information in -+separate sections has also been in widespread use with COFF on Unix -+systems, but unfortunately Atmel had chosen native COFF debugging -+information instead. -+ -+Fortunately, the objcopy tool already had implemented part of the -+task: the --debugging option was already there, and is meant to -+convert the debugging information from the input file into a generic -+internal debugging format, and from there into the debugging -+information required for the output file. So it was ``only'' that a -+COFF debugging generator needed to be written. (The source code for -+this converter alone is close to 100 KB, in almost 3,500 lines of C -+code...) -+ -+ -+The conversion from ELF/stabs to AVR COFF -+----------------------------------------- -+ -+The usage of objcopy to convert ELF/stabs debugging information into -+AVR COFF debugging information is (long lines wrapped with -+backslashes): -+ -+avr-objcopy \ -+ --debugging \ -+ -O ${FORMAT} \ -+ --change-section-address .data-0x800000 \ -+ --change-section-address .bss-0x800000 \ -+ --change-section-address .noinit-0x800000 \ -+ --change-section-address .eeprom-0x810000 \ -+ ${filename}.elf ${filename}.cof -+ -+where ${FORMAT} should either be "coff-avr" (COFF format that matches -+the older Atmel AVR COFF documentation, as understood by AVR Studio 3, -+early versions of AVR Studio 4, and also by VMLAB), or "coff-ext-avr" -+(current AVR »extended« COFF specification, as understood by AVR -+Studio 4.07; adds long filenames and structure debugging). There are -+some more options dealing with the mapping of debugging source file -+names for coff-ext-avr which i can explain later if you need this -+(coff-avr only supports 14-char filenames, so no source file directory -+information can be tranferred there). -+ -+In the WinAVR template Makefile, you can say »make coff« to get the -+resulting file ($(TARGET).cof) in the coff-avr format, and »make -+extcoff« to get it in the coff-ext-avr format. -+ -+There might be some warnings when you run the above, like -+ -+Warning: file {standard input} not found in symbol table, ignoring -+Warning: ignoring function __vectors() outside any compilation unit -+Warning: ignoring function __bad_interrupt() outside any compilation unit -+ -+Perhaps more of them if your avr-libc has been installed with -+debugging symbols (the default WinAVR installation strips debugging -+symbols from the installed library files). There should be no other -+warning normally. -+ -+Run it on your jobs, see if it works as expected. In particular, i'm -+interested in getting results for more complex datatypes, like arrays -+of pointers to function, or functions returning pointers to -+structures, and such. -+ -+ -+COFF woes -+--------- -+ -+When working with COFF files, keep in mind that it's fairly limited. -+Basically, you can cut it down to stating that native COFF debugging -+can only support anything that was already defined in the very first C -+implementation, the so-called Kernighan/Ritchie C. There wasn't a -+standard for C by that time, so the de-facto standard was what has -+been described by the creators of C, Brian Kernighan and Dennis -+Ritchie, in their book ``The C programming language''. -+ -+Anything that appeared later, starting with the extension by the -+so-called ANSI C (now called C89), is basically unsupported in COFF, -+because the debugging format has not been designed with extension in -+mind. Needless to say, this also includes any C99 or C++ extensions. -+ -+Also not supported in COFF are include files. So if you've got an -+include file that actually produces code (e. g. in an inline -+function), don't be surprised that the line numbers in the object file -+will come out as junk. -+ -+COFF tried to save space everywhere, so they defined line numbers as -+16-bit quantities. In order to not limit a single source file to 64 K -+lines, they then defined their line numbers relative to the beginning -+of a function. Thus, COFF line numbers can only exist inside -+functions, and since functions need an input file name, if we don't -+have one (as it can happen in some assembler files assembled with -+--gstabs), we are hosed. -+ -+Finally, even AVR Studio 4.07 implements only a subset of COFF -+debugging information. Currently still unsupported are bitfield -+structs, enums, and typedefs. Note that the binutils patch does -+support all of these features -- only AVR Studio cannot handle them. -+ -+ -+COFF file analysis using abr-objdump -+------------------------------------ -+ -+avr-objdump -g gives a nice pseudo-C code listing of the debug -+information contained in an object file. If you suspect any problems -+with the conversion of the debugging information, try first running -+this on both, the input ELF, and the output COFF file. -+ -+avr-objdump -t gives the raw COFF symbol table listing. It's not -+completely "raw" though, since AVR COFF has so many twists and -+abominations compared to the historic standard COFF, and in order to -+be able to use all the COFF infrastructure in GNU binutils, i'm -+"normalizing" most of this when reading the file (at the same boundary -+where the byte-swapping is handled inside binutils), and de-normalize -+it to the AVRisms when writing it. Thus, objdump -t shows the -+normalized internal form. -+ -+Should you ever need this, i'm happy to explain you in more detail, -+and give you both the current Atmel specs for AVR COFF, as well as a -+pointer to a generic COFF description. It'll be lengthy to explain -+that right now. -+ -+ -+Bug reporting -+------------- -+ -+If you suspect a bug, please make first sure that you've read and -+understood all of the above, in particular the limitations of COFF. -+Please also make sure that you don't just have a plain usage error. -+Remember that there has been a fair amount of alpha testing, so all -+the basic problems should have been shaken out by now. -+ -+Then, try breaking down what the bug might be. Use the avr-objdump -+tool as described above, to see what the debugging information in both -+files looks like. Obviously, they will never look identical (there -+are two many differences in the internal representation between stabs -+and native COFF debugging), but they should be similar. If -+avr-objdump -g produces the expected result but AVR Studio doesn't -+work the way you think, it's most likely not a bug in the conversion, -+but maybe either that the compiler gave incorrect information about an -+object to debug (i've seen situations where a variable got optimized -+completely away in a simple function, so obviously, the debugging -+information for it was wrong), or a problem in the debugger used (like -+AVR Studio). -+ -+Finally, try to make it reproducable. Don't send 500 KB entire -+project ZIP files. Keep in mind that i don't have Windows, and don't -+run AVR Studio -- so don't just make the assumption i could reproduce -+your problem. Please, break it down to the respective portion of the -+avr-objdump -t output (you can see the symbol name in the right -+column, use that for navigation), and send the portion of this dump -+that describes the problem. For a function, that »portion« starts at -+the symbol with the name of the function, and then goes from the .bf -+symbol to the corresponding .ef symbol. For a structure definition, -+it starts with the name of the struct, and goes through the .eos -+symbol. -+ -+So in order to send a bug report, please use the address -+ -+ -+ -+Depending on the time available, and the degree of your own -+investigation, i'll try to answer them. -+ -+ -+Known issues -+------------ -+ -+There are few remaining known issues with the generated COFF. -+ -+The so-called AUX entry pointerization is sometimes wrong. According -+to the COFF specs, all the .bf symbols should form a linked-list, -+where the "next" pointer in each of them points to the next .bf. -+There are similar issues for some other of these records. This should -+normally not upset the debuggers like AVR Studio because they don't -+care about it, and will be fixed anytime soon (but the fix is not so -+easy unfortunately). -+ -+There is a known and still uninvestigated issue where some bootloader -+code could not be debugged. -+ -+There is one issue with memory de-allocation that is not yet properly -+handled, which is merely cosmetical since when the objcopy tool exits, -+the memory will of course be freed anyway. -+ -+There are two known issues with the latest official (by now) version -+of AVR Studio 4.07's COFF parser. The first is that this parser used -+to assume a fixed section ordering instead of checking the COFF file -+header. Usually, gcc also emits the various sections in the order -+assumed by that parser (.text first, .data following), but under some -+circumstances, gcc could put .data first as well. With the buggy -+parser, this would make AVR Studio believe your variables were located -+in ROM. -+ -+The second issue is that AVR Studio until now didn't support the way -+gcc allocates the initialization data for initialized variables: they -+are not issued as part of the program code, but instead need to -+appended manually after the program code itself. (When preparing an -+Intel Hex file, this is usually done by specifying both, the .text and -+.data section in the call to avr-objcopy.) So in the end, AVR Studio -+was simulating with all the initializers still using 0xff as ROM -+contents. There is no fix for this behaviour for AVR Studio 3.x, -+and/or for older versions of AVR Studio 4.x (all released versions by -+now), and/or for other ELF->COFF conversion tools than the GNU -+binutils with the current coff-avr-patch. Starting with this patch, -+we have negotiated our own vendor ID in the extended AVR COFF header -+(0x9cc, mnemonic for "gcc"), and Atmel agreed to adjust their COFF -+parser so it also loads the contents of .data into the simulator flash -+after .text when it sees this vendor ID. -+ -+Both issues have been fixed internally in Atmel's sources, but by now, -+there is no official version of the updated COFF parser available yet. -+There have been rumours that they might release their own beta site to -+the public in order to test the updated COFF parser as well (which is -+just a DLL that needs to be replaced). -+ -+ -+Dresden, Germany, 2003-05-16 -+Joerg Wunsch -diff --git a/bfd/coff-avr.c b/bfd/coff-avr.c -new file mode 100644 -index 0000000..d02e933 ---- /dev/null -+++ b/bfd/coff-avr.c -@@ -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 --git a/bfd/coff-ext-avr.c b/bfd/coff-ext-avr.c -new file mode 100644 -index 0000000..717ef8e ---- /dev/null -+++ b/bfd/coff-ext-avr.c -@@ -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 --git a/bfd/coffcode.h b/bfd/coffcode.h -index 3beedef..0f8eed2 100644 ---- a/bfd/coffcode.h -+++ b/bfd/coffcode.h -@@ -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_mkobject (bfd * abfd) - 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_mkobject_hook (bfd * abfd, - - 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 @@ coff_set_arch_mach_hook (bfd *abfd, void * filehdr) - } - break; - #endif -+#ifdef AVRMAGIC -+ case AVRMAGIC: -+ arch = bfd_arch_avr; -+ break; -+#endif - #ifdef MC68MAGIC - case MC68MAGIC: - case M68MAGIC: -@@ -2871,6 +2877,13 @@ coff_set_flags (bfd * abfd, - 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 @@ coff_write_object_contents (bfd * abfd) - 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 @@ coff_write_object_contents (bfd * abfd) - 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 @@ coff_write_object_contents (bfd * abfd) - #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 @@ coff_slurp_symbol_table (bfd * abfd) - /* 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 @@ coff_slurp_symbol_table (bfd * abfd) - && 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 --git a/bfd/coffgen.c b/bfd/coffgen.c -index 5f6921d..d521643 100644 ---- a/bfd/coffgen.c -+++ b/bfd/coffgen.c -@@ -699,6 +699,20 @@ coff_renumber_symbols (bfd *bfd_ptr, int *first_undef) - if (last_file != NULL) - last_file->n_value = native_index; - last_file = &(s->u.syment); -+ if (bfd_get_arch (bfd_ptr) == bfd_arch_avr -+ && bfd_coff_long_filenames (bfd_ptr) -+ && s->u.syment.n_numaux > 0) -+ { -+ /* AVR COFF records long filenames in successive aux -+ records. Adjust the number of aux records -+ required here, so the renumbering will account -+ for them. */ -+ unsigned int filnmlen = bfd_coff_filnmlen (bfd_ptr); -+ unsigned int namelen = strlen (coff_symbol_ptr->symbol.name); -+ unsigned int n = (namelen + filnmlen - 1) / filnmlen; -+ -+ s->u.syment.n_numaux = n > NAUXENTS? NAUXENTS: n; -+ } - } - else - /* Modify the symbol values according to their section and -@@ -827,6 +841,20 @@ coff_fix_symbol_name (bfd *abfd, - { - if (name_length <= filnmlen) - strncpy (auxent->x_file.x_fname, name, filnmlen); -+ else if (bfd_get_arch (abfd) == bfd_arch_avr) -+ { -+ /* AVR COFF records long filenames in successive aux records. */ -+ int i = 1; -+ while (name_length > filnmlen && i < NAUXENTS) -+ { -+ strncpy (auxent->x_file.x_fname, name, filnmlen); -+ name += filnmlen; -+ name_length -= filnmlen; -+ i++; -+ auxent = &(native + i)->u.auxent; -+ } -+ strncpy (auxent->x_file.x_fname, name, filnmlen); -+ } - else - { - auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE; -@@ -1272,6 +1300,10 @@ coff_write_symbols (bfd *abfd) - 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 @@ coff_get_normalized_symtab (bfd *abfd) - { - /* Ordinary short filename, put into memory anyway. The - Microsoft PE tools sometimes store a filename in -- multiple AUX entries. */ -+ multiple AUX entries. -+ AVR COFF does it that way, too. */ - if (internal_ptr->u.syment.n_numaux > 1 -- && coff_data (abfd)->pe) -- internal_ptr->u.syment._n._n_n._n_offset = -- ((bfd_hostptr_t) -- copy_name (abfd, -- (internal_ptr + 1)->u.auxent.x_file.x_fname, -- internal_ptr->u.syment.n_numaux * symesz)); -+ && (coff_data (abfd)->pe -+ || (bfd_get_arch (abfd) == bfd_arch_avr))) -+ { -+ char *b; -+ unsigned int i; -+ -+ /* We allocate enough storage to fit the contents of -+ this many aux records, and simply append a \0. -+ This ensures the string will always be -+ terminated, even in the case where it just fit -+ into the aux records. */ -+ b = (char *) bfd_alloc (abfd, -+ internal_ptr->u.syment.n_numaux * FILNMLEN + 1); -+ internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) b; -+ b[internal_ptr->u.syment.n_numaux * FILNMLEN] = '\0'; -+ for (i = 0; i < internal_ptr->u.syment.n_numaux; i++, b += FILNMLEN) -+ memcpy (b, (internal_ptr + i + 1)->u.auxent.x_file.x_fname, FILNMLEN); -+ } - else - internal_ptr->u.syment._n._n_n._n_offset = - ((bfd_hostptr_t) -@@ -1823,9 +1868,9 @@ coff_bfd_make_debug_symbol (bfd *abfd, - - 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 --git a/bfd/coffswap.h b/bfd/coffswap.h -index 674fdc7..785f7da 100644 ---- a/bfd/coffswap.h -+++ b/bfd/coffswap.h -@@ -383,7 +383,11 @@ coff_swap_aux_in (bfd *abfd, - 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 @@ coff_swap_aux_in (bfd *abfd, - #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 --git a/bfd/config.bfd b/bfd/config.bfd -index e340251..7310224 100644 ---- a/bfd/config.bfd -+++ b/bfd/config.bfd -@@ -339,6 +339,7 @@ case "${targ}" in - - avr-*-*) - targ_defvec=bfd_elf32_avr_vec -+ targ_selvecs="bfd_elf32_avr_vec avrcoff_vec avrextcoff_vec" - ;; - - bfin-*-*) -diff --git a/bfd/configure b/bfd/configure -index 6502be6..b836006 100755 ---- a/bfd/configure -+++ b/bfd/configure -@@ -14782,6 +14782,8 @@ do - 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 --git a/bfd/configure.in b/bfd/configure.in -index e39187d..154b4a9 100644 ---- a/bfd/configure.in -+++ b/bfd/configure.in -@@ -670,6 +670,8 @@ do - 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 --git a/bfd/targets.c b/bfd/targets.c -index a33790b..9d2964e 100644 ---- a/bfd/targets.c -+++ b/bfd/targets.c -@@ -564,6 +564,8 @@ extern const bfd_target armpe_big_vec; - 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 @@ static const bfd_target * const _bfd_target_vector[] = - &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 --git a/binutils/Makefile.am b/binutils/Makefile.am -index db7a773..ace3138 100644 ---- a/binutils/Makefile.am -+++ b/binutils/Makefile.am -@@ -101,7 +101,7 @@ CFILES = \ - 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 @@ GENERATED_CFILES = \ - 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 --git a/binutils/Makefile.in b/binutils/Makefile.in -index ab0c1a6..3353fcc 100644 ---- a/binutils/Makefile.in -+++ b/binutils/Makefile.in -@@ -126,7 +126,7 @@ am_nm_new_OBJECTS = nm.$(OBJEXT) $(am__objects_1) - 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 @@ CFILES = \ - 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 @@ GENERATED_CFILES = \ - 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 --git a/binutils/bucomm.c b/binutils/bucomm.c -index e006e61..094d3e3 100644 ---- a/binutils/bucomm.c -+++ b/binutils/bucomm.c -@@ -550,6 +550,32 @@ parse_vma (const char *s, const char *arg) - 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 --git a/binutils/bucomm.h b/binutils/bucomm.h -index fcbc32b..3255d52 100644 ---- a/binutils/bucomm.h -+++ b/binutils/bucomm.h -@@ -58,6 +58,8 @@ bfd_vma parse_vma (const char *, const char *); - - off_t get_file_size (const char *); - -+const char *bu_basename PARAMS ((const char *)); -+ - extern char *program_name; - - /* filemode.c */ -diff --git a/binutils/budbg.h b/binutils/budbg.h -index b9de022..1bab100 100644 ---- a/binutils/budbg.h -+++ b/binutils/budbg.h -@@ -52,8 +52,11 @@ extern bfd_boolean parse_ieee (void *, bfd *, const bfd_byte *, bfd_size_type); - - 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 --git a/binutils/debug.c b/binutils/debug.c -index 57f5a2d..e4becfe 100644 ---- a/binutils/debug.c -+++ b/binutils/debug.c -@@ -31,6 +31,7 @@ - #include - #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_real_list - 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 @@ static bfd_boolean debug_type_samep - (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 @@ debug_set_filename (void *handle, const char *name) - - 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 @@ debug_start_source (void *handle, const char *name) - - if (name == NULL) - name = ""; -+ else -+ name = debug_xlat_pathname (name); - - if (info->current_unit == NULL) - { -@@ -3370,3 +3393,69 @@ debug_class_type_samep (struct debug_handle *info, struct debug_type_s *t1, - - 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 --git a/binutils/debug.h b/binutils/debug.h -index 3ba344c..e19cb07 100644 ---- a/binutils/debug.h -+++ b/binutils/debug.h -@@ -440,6 +440,12 @@ extern bfd_boolean debug_set_filename (void *, const char *); - - 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 --git a/binutils/doc/objcopy.1 b/binutils/doc/objcopy.1 -index cc041c0..5714f0d 100644 ---- a/binutils/doc/objcopy.1 -+++ b/binutils/doc/objcopy.1 -@@ -202,6 +202,8 @@ objcopy [\fB\-F\fR \fIbfdname\fR|\fB\-\-target=\fR\fIbfdname\fR] - [\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 @@ This option is used to build a \fI.sym\fR file for a VxWorks kernel. - 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 --git a/binutils/objcopy.c b/binutils/objcopy.c -index e0cac19..876b30d 100644 ---- a/binutils/objcopy.c -+++ b/binutils/objcopy.c -@@ -32,6 +32,7 @@ - #include "elf-bfd.h" - #include - #include "libbfd.h" -+#include "debug.h" - #include "coff/internal.h" - #include "libcoff.h" - -@@ -297,6 +298,8 @@ enum command_line_switch - 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 @@ static struct option copy_options[] = - {"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 @@ copy_usage (FILE *stream, int exit_status) - --prefix-alloc-sections \n\ - Add to start of every allocatable\n\ - section name\n\ -+ --change-pathname = Change debug pathnames from to \n\ -+ --basename Strip directory part from debug pathnames\n\ - --file-alignment Set PE file alignment to \n\ - --heap [,] Set PE reserve/commit heap to /\n\ - \n\ -@@ -999,6 +1006,8 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, - 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 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, - || 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 @@ write_debugging_info (bfd *obfd, void *dhandle, - 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 @@ copy_main (int argc, char *argv[]) - 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 --git a/binutils/rdcoff.c b/binutils/rdcoff.c -index 473305e..c3cbf77 100644 ---- a/binutils/rdcoff.c -+++ b/binutils/rdcoff.c -@@ -82,6 +82,9 @@ struct coff_types - 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 @@ static bfd_boolean parse_coff_symbol - (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 @@ parse_coff_base_type (bfd *abfd, struct coff_symbols *symbols, - 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 @@ parse_coff_base_type (bfd *abfd, struct coff_symbols *symbols, - 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 @@ parse_coff_base_type (bfd *abfd, struct coff_symbols *symbols, - 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 @@ parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types *types, - - 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 @@ parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types *types, - 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 @@ parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types *types, - 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 @@ external_coff_symbol_p (int sym_class) - 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 @@ parse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle) - 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 @@ parse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle) - switch (syment.n_sclass) - { - case C_EFCN: -- case C_EXTDEF: - case C_ULABEL: - case C_USTATIC: - case C_LINE: -@@ -757,6 +794,8 @@ parse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle) - /* 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 --git a/binutils/wrcoff.c b/binutils/wrcoff.c -new file mode 100644 -index 0000000..07cfbc8 ---- /dev/null -+++ b/binutils/wrcoff.c -@@ -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 -+#include -+ -+#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 (""); -+ 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 --git a/include/coff/avr.h b/include/coff/avr.h -new file mode 100644 -index 0000000..1895bdf ---- /dev/null -+++ b/include/coff/avr.h -@@ -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 --git a/include/coff/internal.h b/include/coff/internal.h -index 4ac96c3..150b603 100644 ---- a/include/coff/internal.h -+++ b/include/coff/internal.h -@@ -646,6 +646,8 @@ union internal_auxent - - }; - -+#define NAUXENTS 10 /* number of pre-allocated aux entries */ -+ - /********************** RELOCATION DIRECTIVES **********************/ - - struct internal_reloc --- -1.6.0.4 - diff --git a/patches/binutils-2.20.1/atmel/0003-Add-new-memory-regions-to-the-AVR-linker-script-temp.patch b/patches/binutils-2.20.1/atmel/0003-Add-new-memory-regions-to-the-AVR-linker-script-temp.patch deleted file mode 100644 index dae2a00..0000000 --- a/patches/binutils-2.20.1/atmel/0003-Add-new-memory-regions-to-the-AVR-linker-script-temp.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 4d26906081a15ebbd0961196721665241c499f54 Mon Sep 17 00:00:00 2001 -From: Stephan Linz -Date: Mon, 18 Apr 2011 21:08:29 +0200 -Subject: [PATCH 3/9] Add new memory regions to the AVR linker script template - -This adds support for fuse, lock and signature memory regions. -This patch has been used extensively in the field for a while -with no issues and allows this data to be added to the ELF output -file. The fuse and lock information is needed for programming the -AVR chip. So this allows the user to contain all information needed -for programming an AVR chip in one single ELF file. - -Quote by Eric Weddington (2011-03-14): -http://old.nabble.com/-AVR--Add-new-memory-regions-to-script-template-td31144851.html - -Original ATMEL patch from: -http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/32-binutils-2.20.1-new-sections.patch - -Signed-off-by: Stephan Linz ---- - ld/scripttempl/avr.sc | 21 +++++++++++++++++++++ - 1 files changed, 21 insertions(+), 0 deletions(-) - -diff --git a/ld/scripttempl/avr.sc b/ld/scripttempl/avr.sc -index 4545b72..c11de86 100644 ---- a/ld/scripttempl/avr.sc -+++ b/ld/scripttempl/avr.sc -@@ -7,6 +7,9 @@ MEMORY - 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 @@ SECTIONS - ${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) } --- -1.6.0.4 - diff --git a/patches/binutils-2.20.1/atmel/0004-Fix-missing-symbol-for-dwarf2_emit_insn.patch b/patches/binutils-2.20.1/atmel/0004-Fix-missing-symbol-for-dwarf2_emit_insn.patch deleted file mode 100644 index efc6af7..0000000 --- a/patches/binutils-2.20.1/atmel/0004-Fix-missing-symbol-for-dwarf2_emit_insn.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 35990cb04f3f56433bcf177918d0b727e98c2249 Mon Sep 17 00:00:00 2001 -From: Stephan Linz -Date: Mon, 18 Apr 2011 21:21:12 +0200 -Subject: [PATCH 4/9] Fix missing symbol for dwarf2_emit_insn - -Use gas header dwarf2dbg.h and keep DWARF2_ADDR_SIZE in consistency -with C compiler produced information. - -Original ATMEL patch from: -http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/34-binutils-2.20.1-as-dwarf.patch - -Signed-off-by: Stephan Linz ---- - gas/config/tc-avr.c | 1 + - gas/config/tc-avr.h | 3 +++ - 2 files changed, 4 insertions(+), 0 deletions(-) - -diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c -index 9d14f64..6a1c7ea 100644 ---- a/gas/config/tc-avr.c -+++ b/gas/config/tc-avr.c -@@ -24,6 +24,7 @@ - #include "as.h" - #include "safe-ctype.h" - #include "subsegs.h" -+#include "dwarf2dbg.h" - - struct avr_opcodes_s - { -diff --git a/gas/config/tc-avr.h b/gas/config/tc-avr.h -index f68bbbd..0f0cd30 100644 ---- a/gas/config/tc-avr.h -+++ b/gas/config/tc-avr.h -@@ -147,3 +147,6 @@ extern long md_pcrel_from_section (struct fix *, segT); - - /* 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 --- -1.6.0.4 - diff --git a/patches/binutils-2.20.1/atmel/0005-Force-DWARF2-debug-output-for-AVR.patch b/patches/binutils-2.20.1/atmel/0005-Force-DWARF2-debug-output-for-AVR.patch deleted file mode 100644 index 7b7020c..0000000 --- a/patches/binutils-2.20.1/atmel/0005-Force-DWARF2-debug-output-for-AVR.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 4a561ac6e874ccff6dddab5fc373925875238c7f Mon Sep 17 00:00:00 2001 -From: Stephan Linz -Date: Mon, 18 Apr 2011 22:39:58 +0200 -Subject: [PATCH 5/9] Force DWARF2 debug output for AVR - -This patch reduce the DWARF debug output line to 10 entries and -force DWARF2 output as only can interpreted by AVR Studio. In -contrast to standard DWARF3 config (13) this cuts the latest three -entries: DW_LNS_set_prologue_end, DW_LNS_set_epilogue_begin, -DW_LNS_set_isa - -Original ATMEL patch from: -http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/35-binutils-2.20.1-dwarf2-AVRStudio-workaround.patch - -Signed-off-by: Stephan Linz ---- - gas/dwarf2dbg.c | 7 ++++++- - 1 files changed, 6 insertions(+), 1 deletions(-) - -diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c -index 2896b21..c43a093 100644 ---- a/gas/dwarf2dbg.c -+++ b/gas/dwarf2dbg.c -@@ -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_debug_line (segT line_seg) - 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 (); - --- -1.6.0.4 - diff --git a/patches/binutils-2.20.1/atmel/0006-Add-support-for-XMEGA-arch-and-devices.patch b/patches/binutils-2.20.1/atmel/0006-Add-support-for-XMEGA-arch-and-devices.patch deleted file mode 100644 index 52942f0..0000000 --- a/patches/binutils-2.20.1/atmel/0006-Add-support-for-XMEGA-arch-and-devices.patch +++ /dev/null @@ -1,733 +0,0 @@ -From 905282b7846358c30058a35303161146317b8931 Mon Sep 17 00:00:00 2001 -From: Stephan Linz -Date: Mon, 18 Apr 2011 22:45:42 +0200 -Subject: [PATCH 6/9] Add support for XMEGA arch and devices - -Add support for the AVR XMEGA family of devices, a new architectures -(groupings), device names, and support for new opcodes that are used -in this family. This is the patch that has been used out in the field -in several AVR toolchain distributions successfully for a long time. - -Quote by Eric Weddington (2011-03-22): -http://old.nabble.com/-AVR--Add-support-for-XMEGA-arch-and-devices.-td31212035.html - -Original ATMEL patch from: -http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/50-binutils-2.20.1-xmega.patch - -Signed-off-by: Stephan Linz ---- - bfd/archures.c | 7 +++++ - bfd/bfd-in2.h | 7 +++++ - bfd/cpu-avr.c | 24 ++++++++++++++++++- - bfd/elf32-avr.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ - gas/config/tc-avr.c | 49 ++++++++++++++++++++++++++++++++++++-- - gas/doc/c-avr.texi | 21 ++++++++++++++++ - include/elf/avr.h | 7 +++++ - include/opcode/avr.h | 11 ++++++++- - ld/Makefile.am | 35 +++++++++++++++++++++++++++ - ld/Makefile.in | 35 +++++++++++++++++++++++++++ - ld/configure.tgt | 2 +- - ld/emulparams/avrxmega1.sh | 12 +++++++++ - ld/emulparams/avrxmega2.sh | 12 +++++++++ - ld/emulparams/avrxmega3.sh | 12 +++++++++ - ld/emulparams/avrxmega4.sh | 12 +++++++++ - ld/emulparams/avrxmega5.sh | 12 +++++++++ - ld/emulparams/avrxmega6.sh | 12 +++++++++ - ld/emulparams/avrxmega7.sh | 12 +++++++++ - ld/emultempl/avrelf.em | 6 +++- - opcodes/avr-dis.c | 31 ++++++++++++++++++------ - 20 files changed, 359 insertions(+), 16 deletions(-) - create mode 100644 ld/emulparams/avrxmega1.sh - create mode 100644 ld/emulparams/avrxmega2.sh - create mode 100644 ld/emulparams/avrxmega3.sh - create mode 100644 ld/emulparams/avrxmega4.sh - create mode 100644 ld/emulparams/avrxmega5.sh - create mode 100644 ld/emulparams/avrxmega6.sh - create mode 100644 ld/emulparams/avrxmega7.sh - -diff --git a/bfd/archures.c b/bfd/archures.c -index df73b3f..390ccec 100644 ---- a/bfd/archures.c -+++ b/bfd/archures.c -@@ -368,6 +368,13 @@ DESCRIPTION - .#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 --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h -index d98c6ec..0821cd0 100644 ---- a/bfd/bfd-in2.h -+++ b/bfd/bfd-in2.h -@@ -2042,6 +2042,13 @@ enum bfd_architecture - #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 --git a/bfd/cpu-avr.c b/bfd/cpu-avr.c -index 9e62ab4..6562ee5 100644 ---- a/bfd/cpu-avr.c -+++ b/bfd/cpu-avr.c -@@ -133,7 +133,29 @@ static const bfd_arch_info_type arch_info_struct[] = - 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 --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c -index cc06360..62ce9fb 100644 ---- a/bfd/elf32-avr.c -+++ b/bfd/elf32-avr.c -@@ -1328,6 +1328,34 @@ bfd_elf_avr_final_write_processing (bfd *abfd, - 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 @@ elf32_avr_object_p (bfd *abfd) - 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 --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c -index 6a1c7ea..184b028 100644 ---- a/gas/config/tc-avr.c -+++ b/gas/config/tc-avr.c -@@ -30,18 +30,19 @@ struct avr_opcodes_s - { - 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[] = ";"; -@@ -80,6 +81,13 @@ static struct mcu_type_s mcu_types[] = - {"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}, -@@ -216,6 +224,21 @@ static struct mcu_type_s mcu_types[] = - {"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}, -+ {"atxmega32a4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, -+ {"atxmega32d4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, -+ {"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} - }; - -@@ -393,6 +416,11 @@ md_show_usage (FILE *stream) - " 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" -@@ -820,7 +848,12 @@ avr_operand (struct avr_opcodes_s *opcode, - 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+". */ -@@ -937,6 +970,16 @@ avr_operand (struct avr_opcodes_s *opcode, - } - break; - -+ case 'E': -+ { -+ unsigned int x; -+ -+ x = avr_get_constant (str, 15); -+ str = input_line_pointer; -+ op_mask |= (x << 4); -+ } -+ break; -+ - case '?': - break; - -diff --git a/gas/doc/c-avr.texi b/gas/doc/c-avr.texi -index bc40a86..ba0927c 100644 ---- a/gas/doc/c-avr.texi -+++ b/gas/doc/c-avr.texi -@@ -80,6 +80,27 @@ atmega128rfa1, at90can128, at90usb1286, at90usb1287, m3000f, m3000s, m3001b). - 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 --git a/include/elf/avr.h b/include/elf/avr.h -index 627dc35..e86eb11 100644 ---- a/include/elf/avr.h -+++ b/include/elf/avr.h -@@ -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 --git a/include/opcode/avr.h b/include/opcode/avr.h -index 15a034a..cff7b06 100644 ---- a/include/opcode/avr.h -+++ b/include/opcode/avr.h -@@ -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 (reti, "", "1001010100011000", 1, AVR_ISA_1200, 0x9518) - 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 (st, "e,r", "100!001rrrrree-+", 1, AVR_ISA_1200, 0x8200) - 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 --git a/ld/Makefile.am b/ld/Makefile.am -index d8bd1f9..80b8f22 100644 ---- a/ld/Makefile.am -+++ b/ld/Makefile.am -@@ -148,6 +148,13 @@ ALL_EMULATIONS = \ - 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 @@ eavr6.c: $(srcdir)/emulparams/avr6.sh $(srcdir)/emultempl/avrelf.em \ - $(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 --git a/ld/Makefile.in b/ld/Makefile.in -index 3a8b4f5..2d5c8a0 100644 ---- a/ld/Makefile.in -+++ b/ld/Makefile.in -@@ -434,6 +434,13 @@ ALL_EMULATIONS = \ - 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 \ -@@ -2069,6 +2076,34 @@ eavr6.c: $(srcdir)/emulparams/avr6.sh $(srcdir)/emultempl/avrelf.em \ - $(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 --git a/ld/configure.tgt b/ld/configure.tgt -index d6d86ab..9ceefa5 100644 ---- a/ld/configure.tgt -+++ b/ld/configure.tgt -@@ -110,7 +110,7 @@ xscale-*-coff) targ_emul=armcoff ;; - 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 --git a/ld/emulparams/avrxmega1.sh b/ld/emulparams/avrxmega1.sh -new file mode 100644 -index 0000000..95e8aac ---- /dev/null -+++ b/ld/emulparams/avrxmega1.sh -@@ -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 --git a/ld/emulparams/avrxmega2.sh b/ld/emulparams/avrxmega2.sh -new file mode 100644 -index 0000000..f282a69 ---- /dev/null -+++ b/ld/emulparams/avrxmega2.sh -@@ -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 --git a/ld/emulparams/avrxmega3.sh b/ld/emulparams/avrxmega3.sh -new file mode 100644 -index 0000000..abaa5b3 ---- /dev/null -+++ b/ld/emulparams/avrxmega3.sh -@@ -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 --git a/ld/emulparams/avrxmega4.sh b/ld/emulparams/avrxmega4.sh -new file mode 100644 -index 0000000..829c8b7 ---- /dev/null -+++ b/ld/emulparams/avrxmega4.sh -@@ -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 --git a/ld/emulparams/avrxmega5.sh b/ld/emulparams/avrxmega5.sh -new file mode 100644 -index 0000000..0a09aee ---- /dev/null -+++ b/ld/emulparams/avrxmega5.sh -@@ -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 --git a/ld/emulparams/avrxmega6.sh b/ld/emulparams/avrxmega6.sh -new file mode 100644 -index 0000000..3c3a468 ---- /dev/null -+++ b/ld/emulparams/avrxmega6.sh -@@ -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 --git a/ld/emulparams/avrxmega7.sh b/ld/emulparams/avrxmega7.sh -new file mode 100644 -index 0000000..b84a0ba ---- /dev/null -+++ b/ld/emulparams/avrxmega7.sh -@@ -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 --git a/ld/emultempl/avrelf.em b/ld/emultempl/avrelf.em -index f0807dd..e328c77 100644 ---- a/ld/emultempl/avrelf.em -+++ b/ld/emultempl/avrelf.em -@@ -71,8 +71,10 @@ avr_elf_${EMULATION_NAME}_before_allocation (void) - - 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 --git a/opcodes/avr-dis.c b/opcodes/avr-dis.c -index 976c371..e3ff59c 100644 ---- a/opcodes/avr-dis.c -+++ b/opcodes/avr-dis.c -@@ -50,7 +50,7 @@ static const char * comment_start = "0x"; - - 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 @@ avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constra - - case 'z': - *buf++ = 'Z'; -- if (insn & 0x1) -+ -+ /* 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")); -@@ -227,6 +237,10 @@ avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constra - } - break; - -+ case 'E': -+ sprintf (buf, "%d", (insn >> 4) & 15); -+ break; -+ - case '?': - *buf = '\0'; - break; -@@ -331,7 +345,8 @@ print_insn_avr (bfd_vma addr, disassemble_info *info) - - if (opcode->name) - { -- char *op = opcode->constraints; -+ char *constraints = opcode->constraints; -+ char *opcode_str = opcode->opcode; - - insn2 = 0; - ok = 1; -@@ -342,14 +357,14 @@ print_insn_avr (bfd_vma addr, disassemble_info *info) - 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); - } - } --- -1.6.0.4 - diff --git a/patches/binutils-2.20.1/atmel/0007-Add-remove-support-for-devices.patch b/patches/binutils-2.20.1/atmel/0007-Add-remove-support-for-devices.patch deleted file mode 100644 index b4a915f..0000000 --- a/patches/binutils-2.20.1/atmel/0007-Add-remove-support-for-devices.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 29bc673719635293f6dd8fee0a16d7ed1630fb67 Mon Sep 17 00:00:00 2001 -From: Stephan Linz -Date: Mon, 18 Apr 2011 23:19:07 +0200 -Subject: [PATCH 7/9] Add/remove support for devices - -Add support for a bunch of new AVR devices, and removes support -for some listed devices as well: atmega8m1, atmega8c1, atmega16c1, -atmega4hvd, atmega8hvd, attiny327, m3000f, m3000s, m3001b. - -Quote by Eric Weddington (2010-04-08): -http://old.nabble.com/-PATCH%2C-AVR--Add-remove-support-for-devices-td28172078.html - -Original ATMEL patch from: -http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/51-binutils-2.20.1-new-devices.patch - -Signed-off-by: Stephan Linz ---- - binutils/size.c | 3 --- - gas/config/tc-avr.c | 43 ++++++++++++++++++++++++++++++++++--------- - gas/doc/c-avr.texi | 40 +++++++++++++++++++++++----------------- - 3 files changed, 57 insertions(+), 29 deletions(-) - -diff --git a/binutils/size.c b/binutils/size.c -index cd1635a..a6c8e6c 100644 ---- a/binutils/size.c -+++ b/binutils/size.c -@@ -208,7 +208,6 @@ avr_device_t avr[] = - {"atmega32c1", AVR32K, AVR2K, AVR1K}, - {"atmega32hvb", AVR32K, AVR2K, AVR1K}, - {"atmega32m1", AVR32K, AVR2K, AVR1K}, -- {"attiny327", AVR32K, AVR2K, AVR1K}, - {"atmega32u2", AVR32K, AVR2K, AVR1K}, - {"atmega32u4", AVR32K, 2560UL, AVR1K}, - {"atmega32u6", AVR32K, 2560UL, AVR1K}, -@@ -268,7 +267,6 @@ avr_device_t avr[] = - {"atmega88pa", AVR8K, AVR1K, AVR512}, - {"atmega8hva", AVR8K, 768UL, AVR256}, - {"atmega8u2", AVR8K, AVR512, AVR512}, -- {"atmega8hvd", AVR8K, AVR512, AVR256}, - {"attiny84", AVR8K, AVR512, AVR512}, - {"attiny84a", AVR8K, AVR512, AVR512}, - {"attiny85", AVR8K, AVR512, AVR512}, -@@ -283,7 +281,6 @@ avr_device_t avr[] = - {"atmega48", AVR4K, AVR512, AVR256}, - {"atmega48a", AVR4K, AVR512, AVR256}, - {"atmega48p", AVR4K, AVR512, AVR256}, -- {"atmega4hvd", AVR4K, AVR512, AVR256}, - {"attiny4313", AVR4K, AVR256, AVR256}, - {"attiny43u", AVR4K, AVR256, AVR64}, - {"attiny44", AVR4K, AVR256, AVR256}, -diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c -index 184b028..90918df 100644 ---- a/gas/config/tc-avr.c -+++ b/gas/config/tc-avr.c -@@ -115,12 +115,14 @@ static struct mcu_type_s mcu_types[] = - {"attiny44", AVR_ISA_AVR25, bfd_mach_avr25}, - {"attiny44a", AVR_ISA_AVR25, bfd_mach_avr25}, - {"attiny84", AVR_ISA_AVR25, bfd_mach_avr25}, -+ {"attiny84a", AVR_ISA_AVR25, bfd_mach_avr25}, - {"attiny25", AVR_ISA_AVR25, bfd_mach_avr25}, - {"attiny45", AVR_ISA_AVR25, bfd_mach_avr25}, - {"attiny85", AVR_ISA_AVR25, bfd_mach_avr25}, - {"attiny261", AVR_ISA_AVR25, bfd_mach_avr25}, - {"attiny261a", AVR_ISA_AVR25, bfd_mach_avr25}, - {"attiny461", AVR_ISA_AVR25, bfd_mach_avr25}, -+ {"attiny461a", AVR_ISA_AVR25, bfd_mach_avr25}, - {"attiny861", AVR_ISA_AVR25, bfd_mach_avr25}, - {"attiny861a", AVR_ISA_AVR25, bfd_mach_avr25}, - {"attiny87", AVR_ISA_AVR25, bfd_mach_avr25}, -@@ -134,7 +136,6 @@ static struct mcu_type_s mcu_types[] = - {"atmega103", AVR_ISA_AVR31, bfd_mach_avr31}, - {"at43usb320", AVR_ISA_AVR31, bfd_mach_avr31}, - {"attiny167", AVR_ISA_AVR35, bfd_mach_avr35}, -- {"attiny327", AVR_ISA_AVR35, bfd_mach_avr35}, - {"at90usb82", AVR_ISA_AVR35, bfd_mach_avr35}, - {"at90usb162", AVR_ISA_AVR35, bfd_mach_avr35}, - {"atmega8u2", AVR_ISA_AVR35, bfd_mach_avr35}, -@@ -142,16 +143,15 @@ static struct mcu_type_s mcu_types[] = - {"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}, -- {"atmega4hvd", AVR_ISA_AVR4, bfd_mach_avr4}, -- {"atmega8hvd", AVR_ISA_AVR4, bfd_mach_avr4}, -- {"atmega8c1", AVR_ISA_AVR4, bfd_mach_avr4}, -- {"atmega8m1", AVR_ISA_AVR4, bfd_mach_avr4}, - {"at90pwm1", AVR_ISA_AVR4, bfd_mach_avr4}, - {"at90pwm2", AVR_ISA_AVR4, bfd_mach_avr4}, - {"at90pwm2b", AVR_ISA_AVR4, bfd_mach_avr4}, -@@ -159,40 +159,67 @@ static struct mcu_type_s mcu_types[] = - {"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}, -+ {"atmega165a", 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}, -- {"atmega16c1", 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}, - {"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}, -+ {"atmega325a", AVR_ISA_AVR5, bfd_mach_avr5}, - {"atmega325p", AVR_ISA_AVR5, bfd_mach_avr5}, - {"atmega3250", AVR_ISA_AVR5, bfd_mach_avr5}, -+ {"atmega3250a",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}, -+ {"atmega329a", 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}, -+ {"atmega3290a",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}, -@@ -211,6 +238,7 @@ static struct mcu_type_s mcu_types[] = - {"at90usb647", AVR_ISA_AVR5, bfd_mach_avr5}, - {"at90scr100", AVR_ISA_AVR5, bfd_mach_avr5}, - {"at94k", AVR_ISA_94K, bfd_mach_avr5}, -+ {"m3000", AVR_ISA_AVR5, bfd_mach_avr5}, - {"atmega128", AVR_ISA_AVR51, bfd_mach_avr51}, - {"atmega1280", AVR_ISA_AVR51, bfd_mach_avr51}, - {"atmega1281", AVR_ISA_AVR51, bfd_mach_avr51}, -@@ -219,9 +247,6 @@ static struct mcu_type_s mcu_types[] = - {"at90can128", AVR_ISA_AVR51, bfd_mach_avr51}, - {"at90usb1286",AVR_ISA_AVR51, bfd_mach_avr51}, - {"at90usb1287",AVR_ISA_AVR51, bfd_mach_avr51}, -- {"m3000f", AVR_ISA_AVR51, bfd_mach_avr51}, -- {"m3000s", AVR_ISA_AVR51, bfd_mach_avr51}, -- {"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}, -diff --git a/gas/doc/c-avr.texi b/gas/doc/c-avr.texi -index ba0927c..c04c546 100644 ---- a/gas/doc/c-avr.texi -+++ b/gas/doc/c-avr.texi -@@ -43,9 +43,10 @@ at90s8535). - - 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, attiny84a, 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). -@@ -54,28 +55,33 @@ Instruction set avr31 is for the classic AVR core with exactly 128K program - memory space (MCU types: atmega103, at43usb320). - - Instruction set avr35 is for classic AVR core plus MOVW, CALL, and JMP --instructions (MCU types: attiny167, attiny327, at90usb82, at90usb162, atmega8u2, -+instructions (MCU types: attiny167, at90usb82, at90usb162, atmega8u2, - 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, -+at90pwm1,at90pwm2, at90pwm2b, at90pwm3, at90pwm3b, -+at90pwm81). - - 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, -+atmega32, atmega323, atmega324a, atmega324p, atmega324pa, atmega325, atmega325a, -+atmega325p, atmega3250, atmega3250a, atmega3250p, atmega328, atmega328p, -+atmega329, atmega329a, atmega329p, atmega329pa, atmega3290, atmega3290a, -+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, --atmega128rfa1, at90can128, at90usb1286, at90usb1287, m3000f, m3000s, m3001b). -+atmega128rfa1, at90can128, at90usb1286, at90usb1287, m3000). - - Instruction set avr6 is for the enhanced AVR core with a 3-byte PC (MCU types: - atmega2560, atmega2561). --- -1.6.0.4 - diff --git a/patches/binutils-2.20.1/atmel/0008-Add-support-for-devices-with-16-gp-registers.patch b/patches/binutils-2.20.1/atmel/0008-Add-support-for-devices-with-16-gp-registers.patch deleted file mode 100644 index 7a26a38..0000000 --- a/patches/binutils-2.20.1/atmel/0008-Add-support-for-devices-with-16-gp-registers.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 01a36bb280f0af0d84bbf09f37372919395f9de8 Mon Sep 17 00:00:00 2001 -From: Stephan Linz -Date: Tue, 19 Apr 2011 00:23:01 +0200 -Subject: [PATCH 8/9] Add support for devices with 16 gp registers - -Add support for a bunch of new AVR devices, especially tiny devices -with 16 gp registers: attiny4, attiny5, attiny9, attiny10, attiny20, -attiny40 - -Original ATMEL patch from: -http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/52-binutils-2.20.1-avrtiny10.patch - -Signed-off-by: Stephan Linz ---- - bfd/archures.c | 1 + - bfd/bfd-in2.h | 1 + - bfd/cpu-avr.c | 5 ++++- - bfd/elf32-avr.c | 8 ++++++++ - gas/config/tc-avr.c | 19 +++++++++++++++++++ - include/elf/avr.h | 1 + - include/opcode/avr.h | 14 +++++++------- - ld/Makefile.am | 5 +++++ - ld/Makefile.in | 5 +++++ - ld/configure.tgt | 2 +- - ld/emulparams/avrtiny10.sh | 12 ++++++++++++ - 11 files changed, 64 insertions(+), 9 deletions(-) - create mode 100644 ld/emulparams/avrtiny10.sh - -diff --git a/bfd/archures.c b/bfd/archures.c -index 390ccec..6a1062c 100644 ---- a/bfd/archures.c -+++ b/bfd/archures.c -@@ -375,6 +375,7 @@ DESCRIPTION - .#define bfd_mach_avrxmega5 105 - .#define bfd_mach_avrxmega6 106 - .#define bfd_mach_avrxmega7 107 -+.#define bfd_mach_avrtiny10 201 - . bfd_arch_bfin, {* ADI Blackfin *} - .#define bfd_mach_bfin 1 - . bfd_arch_cr16, {* National Semiconductor CompactRISC (ie CR16). *} -diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h -index 0821cd0..c093108 100644 ---- a/bfd/bfd-in2.h -+++ b/bfd/bfd-in2.h -@@ -2049,6 +2049,7 @@ enum bfd_architecture - #define bfd_mach_avrxmega5 105 - #define bfd_mach_avrxmega6 106 - #define bfd_mach_avrxmega7 107 -+#define bfd_mach_avrtiny10 201 - bfd_arch_bfin, /* ADI Blackfin */ - #define bfd_mach_bfin 1 - bfd_arch_cr16, /* National Semiconductor CompactRISC (ie CR16). */ -diff --git a/bfd/cpu-avr.c b/bfd/cpu-avr.c -index 6562ee5..0cc66fc 100644 ---- a/bfd/cpu-avr.c -+++ b/bfd/cpu-avr.c -@@ -154,7 +154,10 @@ static const bfd_arch_info_type arch_info_struct[] = - N (24, bfd_mach_avrxmega6, "avr:106", FALSE, & arch_info_struct[16]), - - /* Xmega 7 */ -- N (24, bfd_mach_avrxmega7, "avr:107", FALSE, NULL) -+ N (24, bfd_mach_avrxmega7, "avr:107", FALSE, & arch_info_struct[17]), -+ -+ /* attiny 10 */ -+ N (16, bfd_mach_avrtiny10, "avr:201", FALSE, NULL) - - }; - -diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c -index 62ce9fb..af85301 100644 ---- a/bfd/elf32-avr.c -+++ b/bfd/elf32-avr.c -@@ -1356,6 +1356,10 @@ bfd_elf_avr_final_write_processing (bfd *abfd, - case bfd_mach_avrxmega7: - val = E_AVR_MACH_XMEGA7; - break; -+ -+ case bfd_mach_avrtiny10: -+ val = E_AVR_MACH_AVRTINY10; -+ break; - } - - elf_elfheader (abfd)->e_machine = EM_AVR; -@@ -1446,6 +1450,10 @@ elf32_avr_object_p (bfd *abfd) - case E_AVR_MACH_XMEGA7: - e_set = bfd_mach_avrxmega7; - break; -+ -+ case E_AVR_MACH_AVRTINY10: -+ e_set = bfd_mach_avrtiny10; -+ break; - } - } - return bfd_default_set_arch_mach (abfd, bfd_arch_avr, -diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c -index 90918df..20501bb 100644 ---- a/gas/config/tc-avr.c -+++ b/gas/config/tc-avr.c -@@ -88,6 +88,7 @@ static struct mcu_type_s mcu_types[] = - {"avrxmega5", AVR_ISA_XMEGA, bfd_mach_avrxmega5}, - {"avrxmega6", AVR_ISA_XMEGA, bfd_mach_avrxmega6}, - {"avrxmega7", AVR_ISA_XMEGA, bfd_mach_avrxmega7}, -+ {"avrtiny10", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, - {"at90s1200", AVR_ISA_1200, bfd_mach_avr1}, - {"attiny11", AVR_ISA_AVR1, bfd_mach_avr1}, - {"attiny12", AVR_ISA_AVR1, bfd_mach_avr1}, -@@ -264,6 +265,12 @@ static struct mcu_type_s mcu_types[] = - {"atxmega256a3b",AVR_ISA_XMEGA, bfd_mach_avrxmega6}, - {"atxmega256d3", AVR_ISA_XMEGA, bfd_mach_avrxmega6}, - {"atxmega128a1", AVR_ISA_XMEGA, bfd_mach_avrxmega7}, -+ {"attiny4", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, -+ {"attiny5", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, -+ {"attiny9", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, -+ {"attiny10", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, -+ {"attiny20", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, -+ {"attiny40", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, - {NULL, 0, 0} - }; - -@@ -446,6 +453,7 @@ md_show_usage (FILE *stream) - " avrxmega5 - XMEGA, > 64K, <= 128K FLASH, > 64K RAM\n" - " avrxmega6 - XMEGA, > 128K, <= 256K FLASH, <= 64K RAM\n" - " avrxmega7 - XMEGA, > 128K, <= 256K FLASH, > 64K RAM\n" -+ " avrtiny10 - tiny devices with 16 gp registers\n" - " or immediate microcontroller name.\n")); - fprintf (stream, - _(" -mall-opcodes accept all AVR opcodes, even if not supported by MCU\n" -@@ -793,6 +801,17 @@ avr_operand (struct avr_opcodes_s *opcode, - op_mask = avr_get_constant (str, 31); - str = input_line_pointer; - } -+ if (strcmp(avr_mcu->name, "avrtiny10") == 0 -+ || strcmp(avr_mcu->name, "attiny10") == 0 -+ || strcmp(avr_mcu->name, "attiny4") == 0 -+ || strcmp(avr_mcu->name, "attiny5") == 0 -+ || strcmp(avr_mcu->name, "attiny9") == 0 -+ || strcmp(avr_mcu->name, "attiny20") == 0 -+ || strcmp(avr_mcu->name, "attiny40") == 0) -+ { -+ if(op_mask < 16) -+ as_bad (_("register number above 15 required")); -+ } - - if (op_mask <= 31) - { -diff --git a/include/elf/avr.h b/include/elf/avr.h -index e86eb11..d334870 100644 ---- a/include/elf/avr.h -+++ b/include/elf/avr.h -@@ -47,6 +47,7 @@ - #define E_AVR_MACH_XMEGA5 105 - #define E_AVR_MACH_XMEGA6 106 - #define E_AVR_MACH_XMEGA7 107 -+#define E_AVR_MACH_AVRTINY10 201 - - /* Relocations. */ - START_RELOC_NUMBERS (elf_avr_reloc_type) -diff --git a/include/opcode/avr.h b/include/opcode/avr.h -index cff7b06..3f0417d 100644 ---- a/include/opcode/avr.h -+++ b/include/opcode/avr.h -@@ -69,7 +69,7 @@ - AVR_ISA_ELPM | AVR_ISA_ELPMX | AVR_ISA_SPM | \ - AVR_ISA_SPM | AVR_ISA_BRK | AVR_ISA_EIND | \ - AVR_ISA_MOVW) -- -+#define AVR_ISA_AVRTINY10 (AVR_ISA_1200 | AVR_ISA_BRK | AVR_ISA_SRAM) - #define REGISTER_P(x) ((x) == 'r' \ - || (x) == 'd' \ - || (x) == 'w' \ -@@ -159,8 +159,8 @@ AVR_INSN (sez, "", "1001010000011000", 1, AVR_ISA_1200, 0x9418) - AVR_INSN (bclr, "S", "100101001SSS1000", 1, AVR_ISA_1200, 0x9488) - AVR_INSN (bset, "S", "100101000SSS1000", 1, AVR_ISA_1200, 0x9408) - --AVR_INSN (icall,"", "1001010100001001", 1, AVR_ISA_2xxx, 0x9509) --AVR_INSN (ijmp, "", "1001010000001001", 1, AVR_ISA_2xxx, 0x9409) -+AVR_INSN (icall,"", "1001010100001001", 1, AVR_ISA_SRAM, 0x9509) -+AVR_INSN (ijmp, "", "1001010000001001", 1, AVR_ISA_SRAM, 0x9409) - - AVR_INSN (lpm, "?", "1001010111001000", 1, AVR_ISA_TINY1,0x95c8) - AVR_INSN (lpm, "r,z", "1001000ddddd010+", 1, AVR_ISA_LPMX, 0x9004) -@@ -260,8 +260,8 @@ AVR_INSN (dec, "r", "1001010rrrrr1010", 1, AVR_ISA_1200, 0x940a) - AVR_INSN (inc, "r", "1001010rrrrr0011", 1, AVR_ISA_1200, 0x9403) - AVR_INSN (lsr, "r", "1001010rrrrr0110", 1, AVR_ISA_1200, 0x9406) - AVR_INSN (neg, "r", "1001010rrrrr0001", 1, AVR_ISA_1200, 0x9401) --AVR_INSN (pop, "r", "1001000rrrrr1111", 1, AVR_ISA_2xxx, 0x900f) --AVR_INSN (push, "r", "1001001rrrrr1111", 1, AVR_ISA_2xxx, 0x920f) -+AVR_INSN (pop, "r", "1001000rrrrr1111", 1, AVR_ISA_SRAM, 0x900f) -+AVR_INSN (push, "r", "1001001rrrrr1111", 1, AVR_ISA_SRAM, 0x920f) - AVR_INSN (ror, "r", "1001010rrrrr0111", 1, AVR_ISA_1200, 0x9407) - AVR_INSN (swap, "r", "1001010rrrrr0010", 1, AVR_ISA_1200, 0x9402) - -@@ -273,8 +273,8 @@ AVR_INSN (fmul, "a,a", "000000110ddd1rrr", 1, AVR_ISA_MUL, 0x0308) - AVR_INSN (fmuls,"a,a", "000000111ddd0rrr", 1, AVR_ISA_MUL, 0x0380) - AVR_INSN (fmulsu,"a,a","000000111ddd1rrr", 1, AVR_ISA_MUL, 0x0388) - --AVR_INSN (sts, "i,r", "1001001ddddd0000", 2, AVR_ISA_2xxx, 0x9200) --AVR_INSN (lds, "r,i", "1001000ddddd0000", 2, AVR_ISA_2xxx, 0x9000) -+AVR_INSN (sts, "i,r", "1001001ddddd0000", 2, AVR_ISA_SRAM, 0x9200) -+AVR_INSN (lds, "r,i", "1001000ddddd0000", 2, AVR_ISA_SRAM, 0x9000) - - /* Special case for b+0, `e' must be next entry after `b', - b={Y=1,Z=0}, ee={X=11,Y=10,Z=00}, !=1 if -e or e+ or X. */ -diff --git a/ld/Makefile.am b/ld/Makefile.am -index 80b8f22..484b944 100644 ---- a/ld/Makefile.am -+++ b/ld/Makefile.am -@@ -155,6 +155,7 @@ ALL_EMULATIONS = \ - eavrxmega5.o \ - eavrxmega6.o \ - eavrxmega7.o \ -+ eavrtiny10.o \ - ecoff_i860.o \ - ecoff_sparc.o \ - eelf32_spu.o \ -@@ -762,6 +763,10 @@ eavrxmega7.c: $(srcdir)/emulparams/avrxmega7.sh \ - $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \ - ${GEN_DEPENDS} - ${GENSCRIPTS} avrxmega7 "$(tdir_avr2)" -+eavrtiny10.c: $(srcdir)/emulparams/avrtiny10.sh \ -+ $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \ -+ ${GEN_DEPENDS} -+ ${GENSCRIPTS} avrtiny10 "$(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 --git a/ld/Makefile.in b/ld/Makefile.in -index 2d5c8a0..c1e9e9c 100644 ---- a/ld/Makefile.in -+++ b/ld/Makefile.in -@@ -441,6 +441,7 @@ ALL_EMULATIONS = \ - eavrxmega5.o \ - eavrxmega6.o \ - eavrxmega7.o \ -+ eavrtiny10.o \ - ecoff_i860.o \ - ecoff_sparc.o \ - eelf32_spu.o \ -@@ -2104,6 +2105,10 @@ eavrxmega7.c: $(srcdir)/emulparams/avrxmega7.sh \ - $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \ - ${GEN_DEPENDS} - ${GENSCRIPTS} avrxmega7 "$(tdir_avr2)" -+eavrtiny10.c: $(srcdir)/emulparams/avrtiny10.sh \ -+ $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \ -+ ${GEN_DEPENDS} -+ ${GENSCRIPTS} avrtiny10 "$(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 --git a/ld/configure.tgt b/ld/configure.tgt -index 9ceefa5..f64dd5b 100644 ---- a/ld/configure.tgt -+++ b/ld/configure.tgt -@@ -110,7 +110,7 @@ xscale-*-coff) targ_emul=armcoff ;; - xscale-*-elf) targ_emul=armelf - ;; - avr-*-*) targ_emul=avr2 -- targ_extra_emuls="avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7" -+ targ_extra_emuls="avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny10" - ;; - bfin-*-elf) targ_emul=elf32bfin; - targ_extra_emuls="elf32bfinfd" -diff --git a/ld/emulparams/avrtiny10.sh b/ld/emulparams/avrtiny10.sh -new file mode 100644 -index 0000000..d530097 ---- /dev/null -+++ b/ld/emulparams/avrtiny10.sh -@@ -0,0 +1,12 @@ -+ARCH=avr:201 -+MACHINE= -+SCRIPT_NAME=avr -+OUTPUT_FORMAT="elf32-avr" -+MAXPAGESIZE=1 -+EMBEDDED=yes -+TEMPLATE_NAME=elf32 -+ -+TEXT_LENGTH=4K -+DATA_ORIGIN=0x800040 -+DATA_LENGTH=0x140 -+EXTRA_EM_FILE=avrelf --- -1.6.0.4 - diff --git a/patches/binutils-2.20.1/atmel/0009-Add-support-for-more-XMEGA-devices.patch b/patches/binutils-2.20.1/atmel/0009-Add-support-for-more-XMEGA-devices.patch deleted file mode 100644 index bbb8b64..0000000 --- a/patches/binutils-2.20.1/atmel/0009-Add-support-for-more-XMEGA-devices.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0a532d69add35e87bd577d6e9341897d8b5080be Mon Sep 17 00:00:00 2001 -From: Stephan Linz -Date: Tue, 19 Apr 2011 00:55:01 +0200 -Subject: [PATCH 9/9] Add support for more XMEGA devices - -Add support for a bunch of new AVR XMEGA devices: atxmega64a1u, -atxmega128a1u, atxmega128b1, atxmega16x1, atxmega32x1 - -Original ATMEL patch from: -http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/53-binutils-2.20.1-xmega128a1u-64a1u.patch -http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/54-binutils-2.20.1-atxmega16x1-32x1.patch -http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/55-binutils-2.20.1-atxmega128b1.patch - -Signed-off-by: Stephan Linz ---- - binutils/size.c | 1 + - gas/config/tc-avr.c | 5 +++++ - gas/doc/c-avr.texi | 14 ++++++++------ - 3 files changed, 14 insertions(+), 6 deletions(-) - -diff --git a/binutils/size.c b/binutils/size.c -index a6c8e6c..f5ca64b 100644 ---- a/binutils/size.c -+++ b/binutils/size.c -@@ -132,6 +132,7 @@ avr_device_t avr[] = - {"atxmega128a1", AVR136K, AVR8K, AVR2K}, - {"atxmega128a1u", AVR136K, AVR8K, AVR2K}, - {"atxmega128a3", AVR136K, AVR8K, AVR2K}, -+ {"atxmega128b1", AVR136K, AVR8K, AVR2K}, - {"atxmega128d3", AVR136K, AVR8K, AVR2K}, - - {"at43usb320", AVR128K, 608UL, 0UL}, -diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c -index 20501bb..1a22ae7 100644 ---- a/gas/config/tc-avr.c -+++ b/gas/config/tc-avr.c -@@ -252,12 +252,16 @@ static struct mcu_type_s mcu_types[] = - {"atmega2561", AVR_ISA_AVR6, bfd_mach_avr6}, - {"atxmega16a4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, - {"atxmega16d4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, -+ {"atxmega16x1", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, - {"atxmega32a4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, - {"atxmega32d4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, -+ {"atxmega32x1", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, - {"atxmega64a3", AVR_ISA_XMEGA, bfd_mach_avrxmega4}, - {"atxmega64d3", AVR_ISA_XMEGA, bfd_mach_avrxmega4}, - {"atxmega64a1", AVR_ISA_XMEGA, bfd_mach_avrxmega5}, -+ {"atxmega64a1u",AVR_ISA_XMEGA, bfd_mach_avrxmega5}, - {"atxmega128a3", AVR_ISA_XMEGA, bfd_mach_avrxmega6}, -+ {"atxmega128b1", 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}, -@@ -265,6 +269,7 @@ static struct mcu_type_s mcu_types[] = - {"atxmega256a3b",AVR_ISA_XMEGA, bfd_mach_avrxmega6}, - {"atxmega256d3", AVR_ISA_XMEGA, bfd_mach_avrxmega6}, - {"atxmega128a1", AVR_ISA_XMEGA, bfd_mach_avrxmega7}, -+ {"atxmega128a1u",AVR_ISA_XMEGA, bfd_mach_avrxmega7}, - {"attiny4", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, - {"attiny5", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, - {"attiny9", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, -diff --git a/gas/doc/c-avr.texi b/gas/doc/c-avr.texi -index c04c546..07637bf 100644 ---- a/gas/doc/c-avr.texi -+++ b/gas/doc/c-avr.texi -@@ -88,24 +88,26 @@ 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). -+atxmega16x1, atxmega32a4, atxmega32d4, atxmega32x1). - - 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). -+memory space and greater than 64K data space (MCU types: none). - - 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). -+memory space and greater than 64K data space (MCU types: atxmega64a1, -+atxmega64a1u). - - 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). -+atxmega128d3, atxmega192a3, atxmega128b1, 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). -+memory space and greater than 64K data space (MCU types: atxmega128a1, -+atxmega128a1u). - - @cindex @code{-mall-opcodes} command line option, AVR - @item -mall-opcodes --- -1.6.0.4 - diff --git a/patches/binutils-2.20.1/series b/patches/binutils-2.20.1/series deleted file mode 100644 index d1043c8..0000000 --- a/patches/binutils-2.20.1/series +++ /dev/null @@ -1,13 +0,0 @@ -# Atmel's patch set reviewed and pulled from: -# http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1 -atmel/0001-Add-AVR-specific-output-format-to-size-utility.patch -atmel/0002-Add-Atmels-AVR-COFF-output-to-objcopy-utility.patch -atmel/0003-Add-new-memory-regions-to-the-AVR-linker-script-temp.patch -atmel/0004-Fix-missing-symbol-for-dwarf2_emit_insn.patch -atmel/0005-Force-DWARF2-debug-output-for-AVR.patch -atmel/0006-Add-support-for-XMEGA-arch-and-devices.patch -atmel/0007-Add-remove-support-for-devices.patch -atmel/0008-Add-support-for-devices-with-16-gp-registers.patch -atmel/0009-Add-support-for-more-XMEGA-devices.patch - -0001-HACK-disable-some-docs-to-avoid-using-makeinfo.patch diff --git a/patches/binutils-2.20.1a/0001-HACK-disable-some-docs-to-avoid-using-makeinfo.patch b/patches/binutils-2.20.1a/0001-HACK-disable-some-docs-to-avoid-using-makeinfo.patch new file mode 100644 index 0000000..94e8812 --- /dev/null +++ b/patches/binutils-2.20.1a/0001-HACK-disable-some-docs-to-avoid-using-makeinfo.patch @@ -0,0 +1,39 @@ +From: Michael Olbrich +Date: Mon, 10 Jun 2013 09:11:36 +0200 +Subject: [PATCH] HACK: disable some docs to avoid using makeinfo + +Patching Makefile.in because running automake fails. + +Signed-off-by: Michael Olbrich +--- + bfd/Makefile.in | 1 - + gas/Makefile.in | 1 - + 2 files changed, 2 deletions(-) + +diff --git a/bfd/Makefile.in b/bfd/Makefile.in +index 696b628..f779d38 100644 +--- a/bfd/Makefile.in ++++ b/bfd/Makefile.in +@@ -320,7 +320,6 @@ ACLOCAL_AMFLAGS = -I . -I .. -I ../config + # RELEASE=y + INCDIR = $(srcdir)/../include + CSEARCH = -I. -I$(srcdir) -I$(INCDIR) +-SUBDIRS = doc po + bfddocdir = doc + libbfd_la_LDFLAGS = $(am__append_1) -release `cat libtool-soversion` \ + @SHARED_LDFLAGS@ $(am__empty) +diff --git a/gas/Makefile.in b/gas/Makefile.in +index 0b11739..cd3de73 100644 +--- a/gas/Makefile.in ++++ b/gas/Makefile.in +@@ -278,7 +278,6 @@ top_builddir = @top_builddir@ + top_srcdir = @top_srcdir@ + AUTOMAKE_OPTIONS = 1.11 dejagnu foreign no-dist + ACLOCAL_AMFLAGS = -I .. -I ../config -I ../bfd +-SUBDIRS = doc po + tooldir = $(exec_prefix)/$(target_alias) + + # Automake 1.10+ disables lex and yacc output file regeneration if +-- +1.8.2.rc2 + diff --git a/patches/binutils-2.20.1a/atmel/0001-Add-AVR-specific-output-format-to-size-utility.patch b/patches/binutils-2.20.1a/atmel/0001-Add-AVR-specific-output-format-to-size-utility.patch new file mode 100644 index 0000000..3fbb653 --- /dev/null +++ b/patches/binutils-2.20.1a/atmel/0001-Add-AVR-specific-output-format-to-size-utility.patch @@ -0,0 +1,560 @@ +From 16ed0c7147c272be68aafe0cc42a2bc390f8efff Mon Sep 17 00:00:00 2001 +From: Stephan Linz +Date: Mon, 18 Apr 2011 19:48:27 +0200 +Subject: [PATCH 1/9] Add AVR specific output format to size utility + +Add a new AVR specific output format with more details about memory +saturation (absolute and relative in percent). The size utility gets +the command line options -C (short) and --format=avr (long). Both +options force the new command line option --mcu=. + +With this patch the size utility gets a AVR specific device database +for memory size informations per chip. But this database is completely +independent from the global binutils BFD/MACH database. + +To select an entry in the size utility internal device database you +have to use the new command line option --mcu=. + +Original ATMEL patch from: +http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/30-binutils-2.20.1-avr-size.patch + +Signed-off-by: Stephan Linz +--- + binutils/size.c | 419 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- + 1 files changed, 398 insertions(+), 21 deletions(-) + +diff --git a/binutils/size.c b/binutils/size.c +index 835aaa7..cd1635a 100644 +--- a/binutils/size.c ++++ b/binutils/size.c +@@ -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,249 @@ 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}, ++ {"atxmega128a1u", 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}, ++ {"atxmega64a1u", 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}, ++ {"m3000", AVR64K, AVR4K, 0UL}, ++ ++ {"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}, ++ {"atmega325a", AVR32K, AVR2K, AVR1K}, ++ {"atmega325p", AVR32K, AVR2K, AVR1K}, ++ {"atmega3250", AVR32K, AVR2K, AVR1K}, ++ {"atmega3250a", AVR32K, AVR2K, AVR1K}, ++ {"atmega3250p", AVR32K, AVR2K, AVR1K}, ++ {"atmega328", AVR32K, AVR2K, AVR1K}, ++ {"atmega328p", AVR32K, AVR2K, AVR1K}, ++ {"atmega329", AVR32K, AVR2K, AVR1K}, ++ {"atmega329a", AVR32K, AVR2K, AVR1K}, ++ {"atmega329p", AVR32K, AVR2K, AVR1K}, ++ {"atmega329pa", AVR32K, AVR2K, AVR1K}, ++ {"atmega3290", AVR32K, AVR2K, AVR1K}, ++ {"atmega3290a", AVR32K, AVR2K, AVR1K}, ++ {"atmega3290p", AVR32K, AVR2K, AVR1K}, ++ {"atmega32hvb", AVR32K, AVR2K, AVR1K}, ++ {"atmega32c1", AVR32K, AVR2K, AVR1K}, ++ {"atmega32hvb", AVR32K, AVR2K, AVR1K}, ++ {"atmega32m1", AVR32K, AVR2K, AVR1K}, ++ {"attiny327", AVR32K, AVR2K, AVR1K}, ++ {"atmega32u2", AVR32K, AVR2K, 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}, ++ {"atmega8hvd", AVR8K, AVR512, AVR256}, ++ {"attiny84", AVR8K, AVR512, AVR512}, ++ {"attiny84a", 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}, ++ {"atmega4hvd", 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 +342,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= 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 +352,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 +363,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 +371,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 +403,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 +412,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 +428,10 @@ main (int argc, char **argv) + } + break; + ++ case OPTION_MCU: ++ avrmcu = optarg; ++ break; ++ + case OPTION_TARGET: + target = optarg; + break; +@@ -190,10 +460,13 @@ 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': +@@ -240,7 +513,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; + +@@ -406,7 +679,7 @@ display_file (char *filename) + return; + } + } +- ++ + static int + size_number (bfd_size_type num) + { +@@ -599,13 +872,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; ++ } + } +-- +1.6.0.4 + diff --git a/patches/binutils-2.20.1a/atmel/0002-Add-Atmels-AVR-COFF-output-to-objcopy-utility.patch b/patches/binutils-2.20.1a/atmel/0002-Add-Atmels-AVR-COFF-output-to-objcopy-utility.patch new file mode 100644 index 0000000..7c9c400 --- /dev/null +++ b/patches/binutils-2.20.1a/atmel/0002-Add-Atmels-AVR-COFF-output-to-objcopy-utility.patch @@ -0,0 +1,5864 @@ +From b88360877c2d1143074ea8d9bae2bdf9a104743a Mon Sep 17 00:00:00 2001 +From: Stephan Linz +Date: Mon, 18 Apr 2011 20:41:41 +0200 +Subject: [PATCH 2/9] Add Atmels AVR COFF output to objcopy utility + +In order to convert the ELF format used in the opensource AVR +toolchain with its debugging information to the AVR COFF format as +defined by Atmel for its AVR Studio, the objcopy utility needs an +associated extension. + +There are two different file formats defined by Atmel, the original +AVR COFF format, and a newer version that is understood by AVR +Studio 4.07 and above called AVR Extended COFF. In order to provide +an easy way to distinguish both, two different BFD names have been +chose within GNU binutils, coff-avr for the former, coff-ext-avr +for the latter. + +More details at: +http://www.sax.de/~joerg/README.coff-avr-patch +http://www.amelek.gda.pl/avr/old/binutils/avrcoff.pdf + +Original ATMEL patch from: +http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/31-binutils-2.20.1-avr-coff.patch + +Signed-off-by: Stephan Linz +--- + bfd/Makefile.am | 4 + + bfd/Makefile.in | 4 + + bfd/README.coff-avr-patch | 264 ++++ + bfd/coff-avr.c | 613 ++++++++ + bfd/coff-ext-avr.c | 428 ++++++ + bfd/coffcode.h | 65 +- + bfd/coffgen.c | 63 +- + bfd/coffswap.h | 10 +- + bfd/config.bfd | 1 + + bfd/configure | 2 + + bfd/configure.in | 2 + + bfd/targets.c | 4 + + binutils/Makefile.am | 4 +- + binutils/Makefile.in | 6 +- + binutils/bucomm.c | 26 + + binutils/bucomm.h | 2 + + binutils/budbg.h | 5 +- + binutils/debug.c | 89 ++ + binutils/debug.h | 6 + + binutils/doc/objcopy.1 | 19 + + binutils/objcopy.c | 40 +- + binutils/rdcoff.c | 57 +- + binutils/wrcoff.c | 3410 +++++++++++++++++++++++++++++++++++++++++++++ + include/coff/avr.h | 110 ++ + include/coff/internal.h | 2 + + 25 files changed, 5199 insertions(+), 37 deletions(-) + create mode 100644 bfd/README.coff-avr-patch + create mode 100644 bfd/coff-avr.c + create mode 100644 bfd/coff-ext-avr.c + create mode 100644 binutils/wrcoff.c + create mode 100644 include/coff/avr.h + +diff --git a/bfd/Makefile.am b/bfd/Makefile.am +index 13ace29..9a12233 100644 +--- a/bfd/Makefile.am ++++ b/bfd/Makefile.am +@@ -228,6 +228,8 @@ BFD32_BACKENDS = \ + 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 @@ BFD32_BACKENDS_CFILES = \ + 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 --git a/bfd/Makefile.in b/bfd/Makefile.in +index 4068a2d..696b628 100644 +--- a/bfd/Makefile.in ++++ b/bfd/Makefile.in +@@ -524,6 +524,8 @@ BFD32_BACKENDS = \ + 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 @@ BFD32_BACKENDS_CFILES = \ + 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 --git a/bfd/README.coff-avr-patch b/bfd/README.coff-avr-patch +new file mode 100644 +index 0000000..1694089 +--- /dev/null ++++ b/bfd/README.coff-avr-patch +@@ -0,0 +1,264 @@ ++README for the »coff-avr-patch« 2003-05-16 ++=============================== ++ ++Background ++---------- ++ ++In order to convert the ELF format used in the opensource AVR ++toolchain (commonly known as just »avr-gcc«) with its debugging ++information that is called »stabs« to the AVR COFF format as defined ++by Atmel for its AVR Studio, two conversion steps are basically ++necessary: the object file format itself needs to be translated from ++ELF to COFF, which is a relatively simple conversion for the most ++part, since all the contents of the various sections of the object ++file can be copied verbatim, and the main change is a different object ++file header. The »objcopy« tool that comes with GNU binutils (called ++»avr-objcopy« in our case) has been designed for this kind of ++conversions, and the GNU binutils itself could already handle more ++than two dozens of different COFF file formats, so for most of the ++part, a common subset of COFF utilities could already be used. (COFF ++is a very old object file format that has been in wide use by end of ++the 1980s/beginning of the 1990s.) ++ ++There are two different file formats defined by Atmel, the original ++AVR COFF format, and a newer version that is understood by AVR Studio ++4.07 and above called AVR »extended« COFF. In order to provide an ++easy way to distinguish both, two different so-called BFD names have ++been chose within GNU binutils, coff-avr for the former, coff-ext-avr ++for the latter. (BFD stands for »binary filedescriptor« and is ++basically the central library of the GNU binutils suite that handles ++all the object file IO.) ++ ++In short, chose coff-ext-avr for AVR Studio 4.07 and above, and ++coff-avr for anything else (which includes AVR Studio 3.x, and VMLAB). ++The main differences are that the newer format can transport long ++filenames (so directory information will be retained), and has the ++option to debug struct types. ++ ++The tough part was to convert the stabs debugging information into the ++so-called native COFF debugging format, which is basically an ++extension of the symbol table that can usually be found in object file ++formats. Symbol tables provide a listing of names vs. object file ++sections plus addresses within that section, that can be displayed ++with the (avr-)nm tool. Now COFF has extended the meaning of a symbol ++by adding some debugging information to it within the symbol table. ++In contrast, the approach taken with ELF is to leave the symbol table ++as it is (the so-called non-debugging symbols), and add the debugging ++information in separate sections within the object file. Since the ++amount of information that can be transported by native COFF ++debugging, the approach to use (stabs) debugging information in ++separate sections has also been in widespread use with COFF on Unix ++systems, but unfortunately Atmel had chosen native COFF debugging ++information instead. ++ ++Fortunately, the objcopy tool already had implemented part of the ++task: the --debugging option was already there, and is meant to ++convert the debugging information from the input file into a generic ++internal debugging format, and from there into the debugging ++information required for the output file. So it was ``only'' that a ++COFF debugging generator needed to be written. (The source code for ++this converter alone is close to 100 KB, in almost 3,500 lines of C ++code...) ++ ++ ++The conversion from ELF/stabs to AVR COFF ++----------------------------------------- ++ ++The usage of objcopy to convert ELF/stabs debugging information into ++AVR COFF debugging information is (long lines wrapped with ++backslashes): ++ ++avr-objcopy \ ++ --debugging \ ++ -O ${FORMAT} \ ++ --change-section-address .data-0x800000 \ ++ --change-section-address .bss-0x800000 \ ++ --change-section-address .noinit-0x800000 \ ++ --change-section-address .eeprom-0x810000 \ ++ ${filename}.elf ${filename}.cof ++ ++where ${FORMAT} should either be "coff-avr" (COFF format that matches ++the older Atmel AVR COFF documentation, as understood by AVR Studio 3, ++early versions of AVR Studio 4, and also by VMLAB), or "coff-ext-avr" ++(current AVR »extended« COFF specification, as understood by AVR ++Studio 4.07; adds long filenames and structure debugging). There are ++some more options dealing with the mapping of debugging source file ++names for coff-ext-avr which i can explain later if you need this ++(coff-avr only supports 14-char filenames, so no source file directory ++information can be tranferred there). ++ ++In the WinAVR template Makefile, you can say »make coff« to get the ++resulting file ($(TARGET).cof) in the coff-avr format, and »make ++extcoff« to get it in the coff-ext-avr format. ++ ++There might be some warnings when you run the above, like ++ ++Warning: file {standard input} not found in symbol table, ignoring ++Warning: ignoring function __vectors() outside any compilation unit ++Warning: ignoring function __bad_interrupt() outside any compilation unit ++ ++Perhaps more of them if your avr-libc has been installed with ++debugging symbols (the default WinAVR installation strips debugging ++symbols from the installed library files). There should be no other ++warning normally. ++ ++Run it on your jobs, see if it works as expected. In particular, i'm ++interested in getting results for more complex datatypes, like arrays ++of pointers to function, or functions returning pointers to ++structures, and such. ++ ++ ++COFF woes ++--------- ++ ++When working with COFF files, keep in mind that it's fairly limited. ++Basically, you can cut it down to stating that native COFF debugging ++can only support anything that was already defined in the very first C ++implementation, the so-called Kernighan/Ritchie C. There wasn't a ++standard for C by that time, so the de-facto standard was what has ++been described by the creators of C, Brian Kernighan and Dennis ++Ritchie, in their book ``The C programming language''. ++ ++Anything that appeared later, starting with the extension by the ++so-called ANSI C (now called C89), is basically unsupported in COFF, ++because the debugging format has not been designed with extension in ++mind. Needless to say, this also includes any C99 or C++ extensions. ++ ++Also not supported in COFF are include files. So if you've got an ++include file that actually produces code (e. g. in an inline ++function), don't be surprised that the line numbers in the object file ++will come out as junk. ++ ++COFF tried to save space everywhere, so they defined line numbers as ++16-bit quantities. In order to not limit a single source file to 64 K ++lines, they then defined their line numbers relative to the beginning ++of a function. Thus, COFF line numbers can only exist inside ++functions, and since functions need an input file name, if we don't ++have one (as it can happen in some assembler files assembled with ++--gstabs), we are hosed. ++ ++Finally, even AVR Studio 4.07 implements only a subset of COFF ++debugging information. Currently still unsupported are bitfield ++structs, enums, and typedefs. Note that the binutils patch does ++support all of these features -- only AVR Studio cannot handle them. ++ ++ ++COFF file analysis using abr-objdump ++------------------------------------ ++ ++avr-objdump -g gives a nice pseudo-C code listing of the debug ++information contained in an object file. If you suspect any problems ++with the conversion of the debugging information, try first running ++this on both, the input ELF, and the output COFF file. ++ ++avr-objdump -t gives the raw COFF symbol table listing. It's not ++completely "raw" though, since AVR COFF has so many twists and ++abominations compared to the historic standard COFF, and in order to ++be able to use all the COFF infrastructure in GNU binutils, i'm ++"normalizing" most of this when reading the file (at the same boundary ++where the byte-swapping is handled inside binutils), and de-normalize ++it to the AVRisms when writing it. Thus, objdump -t shows the ++normalized internal form. ++ ++Should you ever need this, i'm happy to explain you in more detail, ++and give you both the current Atmel specs for AVR COFF, as well as a ++pointer to a generic COFF description. It'll be lengthy to explain ++that right now. ++ ++ ++Bug reporting ++------------- ++ ++If you suspect a bug, please make first sure that you've read and ++understood all of the above, in particular the limitations of COFF. ++Please also make sure that you don't just have a plain usage error. ++Remember that there has been a fair amount of alpha testing, so all ++the basic problems should have been shaken out by now. ++ ++Then, try breaking down what the bug might be. Use the avr-objdump ++tool as described above, to see what the debugging information in both ++files looks like. Obviously, they will never look identical (there ++are two many differences in the internal representation between stabs ++and native COFF debugging), but they should be similar. If ++avr-objdump -g produces the expected result but AVR Studio doesn't ++work the way you think, it's most likely not a bug in the conversion, ++but maybe either that the compiler gave incorrect information about an ++object to debug (i've seen situations where a variable got optimized ++completely away in a simple function, so obviously, the debugging ++information for it was wrong), or a problem in the debugger used (like ++AVR Studio). ++ ++Finally, try to make it reproducable. Don't send 500 KB entire ++project ZIP files. Keep in mind that i don't have Windows, and don't ++run AVR Studio -- so don't just make the assumption i could reproduce ++your problem. Please, break it down to the respective portion of the ++avr-objdump -t output (you can see the symbol name in the right ++column, use that for navigation), and send the portion of this dump ++that describes the problem. For a function, that »portion« starts at ++the symbol with the name of the function, and then goes from the .bf ++symbol to the corresponding .ef symbol. For a structure definition, ++it starts with the name of the struct, and goes through the .eos ++symbol. ++ ++So in order to send a bug report, please use the address ++ ++ ++ ++Depending on the time available, and the degree of your own ++investigation, i'll try to answer them. ++ ++ ++Known issues ++------------ ++ ++There are few remaining known issues with the generated COFF. ++ ++The so-called AUX entry pointerization is sometimes wrong. According ++to the COFF specs, all the .bf symbols should form a linked-list, ++where the "next" pointer in each of them points to the next .bf. ++There are similar issues for some other of these records. This should ++normally not upset the debuggers like AVR Studio because they don't ++care about it, and will be fixed anytime soon (but the fix is not so ++easy unfortunately). ++ ++There is a known and still uninvestigated issue where some bootloader ++code could not be debugged. ++ ++There is one issue with memory de-allocation that is not yet properly ++handled, which is merely cosmetical since when the objcopy tool exits, ++the memory will of course be freed anyway. ++ ++There are two known issues with the latest official (by now) version ++of AVR Studio 4.07's COFF parser. The first is that this parser used ++to assume a fixed section ordering instead of checking the COFF file ++header. Usually, gcc also emits the various sections in the order ++assumed by that parser (.text first, .data following), but under some ++circumstances, gcc could put .data first as well. With the buggy ++parser, this would make AVR Studio believe your variables were located ++in ROM. ++ ++The second issue is that AVR Studio until now didn't support the way ++gcc allocates the initialization data for initialized variables: they ++are not issued as part of the program code, but instead need to ++appended manually after the program code itself. (When preparing an ++Intel Hex file, this is usually done by specifying both, the .text and ++.data section in the call to avr-objcopy.) So in the end, AVR Studio ++was simulating with all the initializers still using 0xff as ROM ++contents. There is no fix for this behaviour for AVR Studio 3.x, ++and/or for older versions of AVR Studio 4.x (all released versions by ++now), and/or for other ELF->COFF conversion tools than the GNU ++binutils with the current coff-avr-patch. Starting with this patch, ++we have negotiated our own vendor ID in the extended AVR COFF header ++(0x9cc, mnemonic for "gcc"), and Atmel agreed to adjust their COFF ++parser so it also loads the contents of .data into the simulator flash ++after .text when it sees this vendor ID. ++ ++Both issues have been fixed internally in Atmel's sources, but by now, ++there is no official version of the updated COFF parser available yet. ++There have been rumours that they might release their own beta site to ++the public in order to test the updated COFF parser as well (which is ++just a DLL that needs to be replaced). ++ ++ ++Dresden, Germany, 2003-05-16 ++Joerg Wunsch +diff --git a/bfd/coff-avr.c b/bfd/coff-avr.c +new file mode 100644 +index 0000000..d02e933 +--- /dev/null ++++ b/bfd/coff-avr.c +@@ -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 --git a/bfd/coff-ext-avr.c b/bfd/coff-ext-avr.c +new file mode 100644 +index 0000000..717ef8e +--- /dev/null ++++ b/bfd/coff-ext-avr.c +@@ -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 --git a/bfd/coffcode.h b/bfd/coffcode.h +index 3beedef..0f8eed2 100644 +--- a/bfd/coffcode.h ++++ b/bfd/coffcode.h +@@ -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_mkobject (bfd * abfd) + 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_mkobject_hook (bfd * abfd, + + 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 @@ coff_set_arch_mach_hook (bfd *abfd, void * filehdr) + } + break; + #endif ++#ifdef AVRMAGIC ++ case AVRMAGIC: ++ arch = bfd_arch_avr; ++ break; ++#endif + #ifdef MC68MAGIC + case MC68MAGIC: + case M68MAGIC: +@@ -2871,6 +2877,13 @@ coff_set_flags (bfd * abfd, + 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 @@ coff_write_object_contents (bfd * abfd) + 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 @@ coff_write_object_contents (bfd * abfd) + 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 @@ coff_write_object_contents (bfd * abfd) + #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 @@ coff_slurp_symbol_table (bfd * abfd) + /* 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 @@ coff_slurp_symbol_table (bfd * abfd) + && 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 --git a/bfd/coffgen.c b/bfd/coffgen.c +index 5f6921d..d521643 100644 +--- a/bfd/coffgen.c ++++ b/bfd/coffgen.c +@@ -699,6 +699,20 @@ coff_renumber_symbols (bfd *bfd_ptr, int *first_undef) + if (last_file != NULL) + last_file->n_value = native_index; + last_file = &(s->u.syment); ++ if (bfd_get_arch (bfd_ptr) == bfd_arch_avr ++ && bfd_coff_long_filenames (bfd_ptr) ++ && s->u.syment.n_numaux > 0) ++ { ++ /* AVR COFF records long filenames in successive aux ++ records. Adjust the number of aux records ++ required here, so the renumbering will account ++ for them. */ ++ unsigned int filnmlen = bfd_coff_filnmlen (bfd_ptr); ++ unsigned int namelen = strlen (coff_symbol_ptr->symbol.name); ++ unsigned int n = (namelen + filnmlen - 1) / filnmlen; ++ ++ s->u.syment.n_numaux = n > NAUXENTS? NAUXENTS: n; ++ } + } + else + /* Modify the symbol values according to their section and +@@ -827,6 +841,20 @@ coff_fix_symbol_name (bfd *abfd, + { + if (name_length <= filnmlen) + strncpy (auxent->x_file.x_fname, name, filnmlen); ++ else if (bfd_get_arch (abfd) == bfd_arch_avr) ++ { ++ /* AVR COFF records long filenames in successive aux records. */ ++ int i = 1; ++ while (name_length > filnmlen && i < NAUXENTS) ++ { ++ strncpy (auxent->x_file.x_fname, name, filnmlen); ++ name += filnmlen; ++ name_length -= filnmlen; ++ i++; ++ auxent = &(native + i)->u.auxent; ++ } ++ strncpy (auxent->x_file.x_fname, name, filnmlen); ++ } + else + { + auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE; +@@ -1272,6 +1300,10 @@ coff_write_symbols (bfd *abfd) + 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 @@ coff_get_normalized_symtab (bfd *abfd) + { + /* Ordinary short filename, put into memory anyway. The + Microsoft PE tools sometimes store a filename in +- multiple AUX entries. */ ++ multiple AUX entries. ++ AVR COFF does it that way, too. */ + if (internal_ptr->u.syment.n_numaux > 1 +- && coff_data (abfd)->pe) +- internal_ptr->u.syment._n._n_n._n_offset = +- ((bfd_hostptr_t) +- copy_name (abfd, +- (internal_ptr + 1)->u.auxent.x_file.x_fname, +- internal_ptr->u.syment.n_numaux * symesz)); ++ && (coff_data (abfd)->pe ++ || (bfd_get_arch (abfd) == bfd_arch_avr))) ++ { ++ char *b; ++ unsigned int i; ++ ++ /* We allocate enough storage to fit the contents of ++ this many aux records, and simply append a \0. ++ This ensures the string will always be ++ terminated, even in the case where it just fit ++ into the aux records. */ ++ b = (char *) bfd_alloc (abfd, ++ internal_ptr->u.syment.n_numaux * FILNMLEN + 1); ++ internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) b; ++ b[internal_ptr->u.syment.n_numaux * FILNMLEN] = '\0'; ++ for (i = 0; i < internal_ptr->u.syment.n_numaux; i++, b += FILNMLEN) ++ memcpy (b, (internal_ptr + i + 1)->u.auxent.x_file.x_fname, FILNMLEN); ++ } + else + internal_ptr->u.syment._n._n_n._n_offset = + ((bfd_hostptr_t) +@@ -1823,9 +1868,9 @@ coff_bfd_make_debug_symbol (bfd *abfd, + + 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 --git a/bfd/coffswap.h b/bfd/coffswap.h +index 674fdc7..785f7da 100644 +--- a/bfd/coffswap.h ++++ b/bfd/coffswap.h +@@ -383,7 +383,11 @@ coff_swap_aux_in (bfd *abfd, + 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 @@ coff_swap_aux_in (bfd *abfd, + #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 --git a/bfd/config.bfd b/bfd/config.bfd +index e340251..7310224 100644 +--- a/bfd/config.bfd ++++ b/bfd/config.bfd +@@ -339,6 +339,7 @@ case "${targ}" in + + avr-*-*) + targ_defvec=bfd_elf32_avr_vec ++ targ_selvecs="bfd_elf32_avr_vec avrcoff_vec avrextcoff_vec" + ;; + + bfin-*-*) +diff --git a/bfd/configure b/bfd/configure +index 6502be6..b836006 100755 +--- a/bfd/configure ++++ b/bfd/configure +@@ -14782,6 +14782,8 @@ do + 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 --git a/bfd/configure.in b/bfd/configure.in +index e39187d..154b4a9 100644 +--- a/bfd/configure.in ++++ b/bfd/configure.in +@@ -670,6 +670,8 @@ do + 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 --git a/bfd/targets.c b/bfd/targets.c +index a33790b..9d2964e 100644 +--- a/bfd/targets.c ++++ b/bfd/targets.c +@@ -564,6 +564,8 @@ extern const bfd_target armpe_big_vec; + 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 @@ static const bfd_target * const _bfd_target_vector[] = + &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 --git a/binutils/Makefile.am b/binutils/Makefile.am +index db7a773..ace3138 100644 +--- a/binutils/Makefile.am ++++ b/binutils/Makefile.am +@@ -101,7 +101,7 @@ CFILES = \ + 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 @@ GENERATED_CFILES = \ + 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 --git a/binutils/Makefile.in b/binutils/Makefile.in +index ab0c1a6..3353fcc 100644 +--- a/binutils/Makefile.in ++++ b/binutils/Makefile.in +@@ -126,7 +126,7 @@ am_nm_new_OBJECTS = nm.$(OBJEXT) $(am__objects_1) + 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 @@ CFILES = \ + 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 @@ GENERATED_CFILES = \ + 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 --git a/binutils/bucomm.c b/binutils/bucomm.c +index e006e61..094d3e3 100644 +--- a/binutils/bucomm.c ++++ b/binutils/bucomm.c +@@ -550,6 +550,32 @@ parse_vma (const char *s, const char *arg) + 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 --git a/binutils/bucomm.h b/binutils/bucomm.h +index fcbc32b..3255d52 100644 +--- a/binutils/bucomm.h ++++ b/binutils/bucomm.h +@@ -58,6 +58,8 @@ bfd_vma parse_vma (const char *, const char *); + + off_t get_file_size (const char *); + ++const char *bu_basename PARAMS ((const char *)); ++ + extern char *program_name; + + /* filemode.c */ +diff --git a/binutils/budbg.h b/binutils/budbg.h +index b9de022..1bab100 100644 +--- a/binutils/budbg.h ++++ b/binutils/budbg.h +@@ -52,8 +52,11 @@ extern bfd_boolean parse_ieee (void *, bfd *, const bfd_byte *, bfd_size_type); + + 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 --git a/binutils/debug.c b/binutils/debug.c +index 57f5a2d..e4becfe 100644 +--- a/binutils/debug.c ++++ b/binutils/debug.c +@@ -31,6 +31,7 @@ + #include + #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_real_list + 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 @@ static bfd_boolean debug_type_samep + (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 @@ debug_set_filename (void *handle, const char *name) + + 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 @@ debug_start_source (void *handle, const char *name) + + if (name == NULL) + name = ""; ++ else ++ name = debug_xlat_pathname (name); + + if (info->current_unit == NULL) + { +@@ -3370,3 +3393,69 @@ debug_class_type_samep (struct debug_handle *info, struct debug_type_s *t1, + + 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 --git a/binutils/debug.h b/binutils/debug.h +index 3ba344c..e19cb07 100644 +--- a/binutils/debug.h ++++ b/binutils/debug.h +@@ -440,6 +440,12 @@ extern bfd_boolean debug_set_filename (void *, const char *); + + 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 --git a/binutils/doc/objcopy.1 b/binutils/doc/objcopy.1 +index cc041c0..5714f0d 100644 +--- a/binutils/doc/objcopy.1 ++++ b/binutils/doc/objcopy.1 +@@ -202,6 +202,8 @@ objcopy [\fB\-F\fR \fIbfdname\fR|\fB\-\-target=\fR\fIbfdname\fR] + [\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 @@ This option is used to build a \fI.sym\fR file for a VxWorks kernel. + 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 --git a/binutils/objcopy.c b/binutils/objcopy.c +index e0cac19..876b30d 100644 +--- a/binutils/objcopy.c ++++ b/binutils/objcopy.c +@@ -32,6 +32,7 @@ + #include "elf-bfd.h" + #include + #include "libbfd.h" ++#include "debug.h" + #include "coff/internal.h" + #include "libcoff.h" + +@@ -297,6 +298,8 @@ enum command_line_switch + 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 @@ static struct option copy_options[] = + {"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 @@ copy_usage (FILE *stream, int exit_status) + --prefix-alloc-sections \n\ + Add to start of every allocatable\n\ + section name\n\ ++ --change-pathname = Change debug pathnames from to \n\ ++ --basename Strip directory part from debug pathnames\n\ + --file-alignment Set PE file alignment to \n\ + --heap [,] Set PE reserve/commit heap to /\n\ + \n\ +@@ -999,6 +1006,8 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, + 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 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms, + || 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 @@ write_debugging_info (bfd *obfd, void *dhandle, + 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 @@ copy_main (int argc, char *argv[]) + 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 --git a/binutils/rdcoff.c b/binutils/rdcoff.c +index 473305e..c3cbf77 100644 +--- a/binutils/rdcoff.c ++++ b/binutils/rdcoff.c +@@ -82,6 +82,9 @@ struct coff_types + 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 @@ static bfd_boolean parse_coff_symbol + (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 @@ parse_coff_base_type (bfd *abfd, struct coff_symbols *symbols, + 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 @@ parse_coff_base_type (bfd *abfd, struct coff_symbols *symbols, + 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 @@ parse_coff_base_type (bfd *abfd, struct coff_symbols *symbols, + 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 @@ parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types *types, + + 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 @@ parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types *types, + 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 @@ parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct coff_types *types, + 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 @@ external_coff_symbol_p (int sym_class) + 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 @@ parse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle) + 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 @@ parse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle) + switch (syment.n_sclass) + { + case C_EFCN: +- case C_EXTDEF: + case C_ULABEL: + case C_USTATIC: + case C_LINE: +@@ -757,6 +794,8 @@ parse_coff (bfd *abfd, asymbol **syms, long symcount, void *dhandle) + /* 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 --git a/binutils/wrcoff.c b/binutils/wrcoff.c +new file mode 100644 +index 0000000..07cfbc8 +--- /dev/null ++++ b/binutils/wrcoff.c +@@ -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 ++#include ++ ++#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 (""); ++ 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 --git a/include/coff/avr.h b/include/coff/avr.h +new file mode 100644 +index 0000000..1895bdf +--- /dev/null ++++ b/include/coff/avr.h +@@ -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 --git a/include/coff/internal.h b/include/coff/internal.h +index 4ac96c3..150b603 100644 +--- a/include/coff/internal.h ++++ b/include/coff/internal.h +@@ -646,6 +646,8 @@ union internal_auxent + + }; + ++#define NAUXENTS 10 /* number of pre-allocated aux entries */ ++ + /********************** RELOCATION DIRECTIVES **********************/ + + struct internal_reloc +-- +1.6.0.4 + diff --git a/patches/binutils-2.20.1a/atmel/0003-Add-new-memory-regions-to-the-AVR-linker-script-temp.patch b/patches/binutils-2.20.1a/atmel/0003-Add-new-memory-regions-to-the-AVR-linker-script-temp.patch new file mode 100644 index 0000000..dae2a00 --- /dev/null +++ b/patches/binutils-2.20.1a/atmel/0003-Add-new-memory-regions-to-the-AVR-linker-script-temp.patch @@ -0,0 +1,65 @@ +From 4d26906081a15ebbd0961196721665241c499f54 Mon Sep 17 00:00:00 2001 +From: Stephan Linz +Date: Mon, 18 Apr 2011 21:08:29 +0200 +Subject: [PATCH 3/9] Add new memory regions to the AVR linker script template + +This adds support for fuse, lock and signature memory regions. +This patch has been used extensively in the field for a while +with no issues and allows this data to be added to the ELF output +file. The fuse and lock information is needed for programming the +AVR chip. So this allows the user to contain all information needed +for programming an AVR chip in one single ELF file. + +Quote by Eric Weddington (2011-03-14): +http://old.nabble.com/-AVR--Add-new-memory-regions-to-script-template-td31144851.html + +Original ATMEL patch from: +http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/32-binutils-2.20.1-new-sections.patch + +Signed-off-by: Stephan Linz +--- + ld/scripttempl/avr.sc | 21 +++++++++++++++++++++ + 1 files changed, 21 insertions(+), 0 deletions(-) + +diff --git a/ld/scripttempl/avr.sc b/ld/scripttempl/avr.sc +index 4545b72..c11de86 100644 +--- a/ld/scripttempl/avr.sc ++++ b/ld/scripttempl/avr.sc +@@ -7,6 +7,9 @@ MEMORY + 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 @@ SECTIONS + ${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) } +-- +1.6.0.4 + diff --git a/patches/binutils-2.20.1a/atmel/0004-Fix-missing-symbol-for-dwarf2_emit_insn.patch b/patches/binutils-2.20.1a/atmel/0004-Fix-missing-symbol-for-dwarf2_emit_insn.patch new file mode 100644 index 0000000..efc6af7 --- /dev/null +++ b/patches/binutils-2.20.1a/atmel/0004-Fix-missing-symbol-for-dwarf2_emit_insn.patch @@ -0,0 +1,43 @@ +From 35990cb04f3f56433bcf177918d0b727e98c2249 Mon Sep 17 00:00:00 2001 +From: Stephan Linz +Date: Mon, 18 Apr 2011 21:21:12 +0200 +Subject: [PATCH 4/9] Fix missing symbol for dwarf2_emit_insn + +Use gas header dwarf2dbg.h and keep DWARF2_ADDR_SIZE in consistency +with C compiler produced information. + +Original ATMEL patch from: +http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/34-binutils-2.20.1-as-dwarf.patch + +Signed-off-by: Stephan Linz +--- + gas/config/tc-avr.c | 1 + + gas/config/tc-avr.h | 3 +++ + 2 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c +index 9d14f64..6a1c7ea 100644 +--- a/gas/config/tc-avr.c ++++ b/gas/config/tc-avr.c +@@ -24,6 +24,7 @@ + #include "as.h" + #include "safe-ctype.h" + #include "subsegs.h" ++#include "dwarf2dbg.h" + + struct avr_opcodes_s + { +diff --git a/gas/config/tc-avr.h b/gas/config/tc-avr.h +index f68bbbd..0f0cd30 100644 +--- a/gas/config/tc-avr.h ++++ b/gas/config/tc-avr.h +@@ -147,3 +147,6 @@ extern long md_pcrel_from_section (struct fix *, segT); + + /* 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 +-- +1.6.0.4 + diff --git a/patches/binutils-2.20.1a/atmel/0005-Force-DWARF2-debug-output-for-AVR.patch b/patches/binutils-2.20.1a/atmel/0005-Force-DWARF2-debug-output-for-AVR.patch new file mode 100644 index 0000000..7b7020c --- /dev/null +++ b/patches/binutils-2.20.1a/atmel/0005-Force-DWARF2-debug-output-for-AVR.patch @@ -0,0 +1,51 @@ +From 4a561ac6e874ccff6dddab5fc373925875238c7f Mon Sep 17 00:00:00 2001 +From: Stephan Linz +Date: Mon, 18 Apr 2011 22:39:58 +0200 +Subject: [PATCH 5/9] Force DWARF2 debug output for AVR + +This patch reduce the DWARF debug output line to 10 entries and +force DWARF2 output as only can interpreted by AVR Studio. In +contrast to standard DWARF3 config (13) this cuts the latest three +entries: DW_LNS_set_prologue_end, DW_LNS_set_epilogue_begin, +DW_LNS_set_isa + +Original ATMEL patch from: +http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/35-binutils-2.20.1-dwarf2-AVRStudio-workaround.patch + +Signed-off-by: Stephan Linz +--- + gas/dwarf2dbg.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c +index 2896b21..c43a093 100644 +--- a/gas/dwarf2dbg.c ++++ b/gas/dwarf2dbg.c +@@ -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_debug_line (segT line_seg) + 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 (); + +-- +1.6.0.4 + diff --git a/patches/binutils-2.20.1a/atmel/0006-Add-support-for-XMEGA-arch-and-devices.patch b/patches/binutils-2.20.1a/atmel/0006-Add-support-for-XMEGA-arch-and-devices.patch new file mode 100644 index 0000000..52942f0 --- /dev/null +++ b/patches/binutils-2.20.1a/atmel/0006-Add-support-for-XMEGA-arch-and-devices.patch @@ -0,0 +1,733 @@ +From 905282b7846358c30058a35303161146317b8931 Mon Sep 17 00:00:00 2001 +From: Stephan Linz +Date: Mon, 18 Apr 2011 22:45:42 +0200 +Subject: [PATCH 6/9] Add support for XMEGA arch and devices + +Add support for the AVR XMEGA family of devices, a new architectures +(groupings), device names, and support for new opcodes that are used +in this family. This is the patch that has been used out in the field +in several AVR toolchain distributions successfully for a long time. + +Quote by Eric Weddington (2011-03-22): +http://old.nabble.com/-AVR--Add-support-for-XMEGA-arch-and-devices.-td31212035.html + +Original ATMEL patch from: +http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/50-binutils-2.20.1-xmega.patch + +Signed-off-by: Stephan Linz +--- + bfd/archures.c | 7 +++++ + bfd/bfd-in2.h | 7 +++++ + bfd/cpu-avr.c | 24 ++++++++++++++++++- + bfd/elf32-avr.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ + gas/config/tc-avr.c | 49 ++++++++++++++++++++++++++++++++++++-- + gas/doc/c-avr.texi | 21 ++++++++++++++++ + include/elf/avr.h | 7 +++++ + include/opcode/avr.h | 11 ++++++++- + ld/Makefile.am | 35 +++++++++++++++++++++++++++ + ld/Makefile.in | 35 +++++++++++++++++++++++++++ + ld/configure.tgt | 2 +- + ld/emulparams/avrxmega1.sh | 12 +++++++++ + ld/emulparams/avrxmega2.sh | 12 +++++++++ + ld/emulparams/avrxmega3.sh | 12 +++++++++ + ld/emulparams/avrxmega4.sh | 12 +++++++++ + ld/emulparams/avrxmega5.sh | 12 +++++++++ + ld/emulparams/avrxmega6.sh | 12 +++++++++ + ld/emulparams/avrxmega7.sh | 12 +++++++++ + ld/emultempl/avrelf.em | 6 +++- + opcodes/avr-dis.c | 31 ++++++++++++++++++------ + 20 files changed, 359 insertions(+), 16 deletions(-) + create mode 100644 ld/emulparams/avrxmega1.sh + create mode 100644 ld/emulparams/avrxmega2.sh + create mode 100644 ld/emulparams/avrxmega3.sh + create mode 100644 ld/emulparams/avrxmega4.sh + create mode 100644 ld/emulparams/avrxmega5.sh + create mode 100644 ld/emulparams/avrxmega6.sh + create mode 100644 ld/emulparams/avrxmega7.sh + +diff --git a/bfd/archures.c b/bfd/archures.c +index df73b3f..390ccec 100644 +--- a/bfd/archures.c ++++ b/bfd/archures.c +@@ -368,6 +368,13 @@ DESCRIPTION + .#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 --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index d98c6ec..0821cd0 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -2042,6 +2042,13 @@ enum bfd_architecture + #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 --git a/bfd/cpu-avr.c b/bfd/cpu-avr.c +index 9e62ab4..6562ee5 100644 +--- a/bfd/cpu-avr.c ++++ b/bfd/cpu-avr.c +@@ -133,7 +133,29 @@ static const bfd_arch_info_type arch_info_struct[] = + 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 --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c +index cc06360..62ce9fb 100644 +--- a/bfd/elf32-avr.c ++++ b/bfd/elf32-avr.c +@@ -1328,6 +1328,34 @@ bfd_elf_avr_final_write_processing (bfd *abfd, + 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 @@ elf32_avr_object_p (bfd *abfd) + 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 --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c +index 6a1c7ea..184b028 100644 +--- a/gas/config/tc-avr.c ++++ b/gas/config/tc-avr.c +@@ -30,18 +30,19 @@ struct avr_opcodes_s + { + 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[] = ";"; +@@ -80,6 +81,13 @@ static struct mcu_type_s mcu_types[] = + {"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}, +@@ -216,6 +224,21 @@ static struct mcu_type_s mcu_types[] = + {"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}, ++ {"atxmega32a4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, ++ {"atxmega32d4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, ++ {"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} + }; + +@@ -393,6 +416,11 @@ md_show_usage (FILE *stream) + " 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" +@@ -820,7 +848,12 @@ avr_operand (struct avr_opcodes_s *opcode, + 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+". */ +@@ -937,6 +970,16 @@ avr_operand (struct avr_opcodes_s *opcode, + } + break; + ++ case 'E': ++ { ++ unsigned int x; ++ ++ x = avr_get_constant (str, 15); ++ str = input_line_pointer; ++ op_mask |= (x << 4); ++ } ++ break; ++ + case '?': + break; + +diff --git a/gas/doc/c-avr.texi b/gas/doc/c-avr.texi +index bc40a86..ba0927c 100644 +--- a/gas/doc/c-avr.texi ++++ b/gas/doc/c-avr.texi +@@ -80,6 +80,27 @@ atmega128rfa1, at90can128, at90usb1286, at90usb1287, m3000f, m3000s, m3001b). + 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 --git a/include/elf/avr.h b/include/elf/avr.h +index 627dc35..e86eb11 100644 +--- a/include/elf/avr.h ++++ b/include/elf/avr.h +@@ -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 --git a/include/opcode/avr.h b/include/opcode/avr.h +index 15a034a..cff7b06 100644 +--- a/include/opcode/avr.h ++++ b/include/opcode/avr.h +@@ -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 (reti, "", "1001010100011000", 1, AVR_ISA_1200, 0x9518) + 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 (st, "e,r", "100!001rrrrree-+", 1, AVR_ISA_1200, 0x8200) + 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 --git a/ld/Makefile.am b/ld/Makefile.am +index d8bd1f9..80b8f22 100644 +--- a/ld/Makefile.am ++++ b/ld/Makefile.am +@@ -148,6 +148,13 @@ ALL_EMULATIONS = \ + 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 @@ eavr6.c: $(srcdir)/emulparams/avr6.sh $(srcdir)/emultempl/avrelf.em \ + $(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 --git a/ld/Makefile.in b/ld/Makefile.in +index 3a8b4f5..2d5c8a0 100644 +--- a/ld/Makefile.in ++++ b/ld/Makefile.in +@@ -434,6 +434,13 @@ ALL_EMULATIONS = \ + 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 \ +@@ -2069,6 +2076,34 @@ eavr6.c: $(srcdir)/emulparams/avr6.sh $(srcdir)/emultempl/avrelf.em \ + $(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 --git a/ld/configure.tgt b/ld/configure.tgt +index d6d86ab..9ceefa5 100644 +--- a/ld/configure.tgt ++++ b/ld/configure.tgt +@@ -110,7 +110,7 @@ xscale-*-coff) targ_emul=armcoff ;; + 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 --git a/ld/emulparams/avrxmega1.sh b/ld/emulparams/avrxmega1.sh +new file mode 100644 +index 0000000..95e8aac +--- /dev/null ++++ b/ld/emulparams/avrxmega1.sh +@@ -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 --git a/ld/emulparams/avrxmega2.sh b/ld/emulparams/avrxmega2.sh +new file mode 100644 +index 0000000..f282a69 +--- /dev/null ++++ b/ld/emulparams/avrxmega2.sh +@@ -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 --git a/ld/emulparams/avrxmega3.sh b/ld/emulparams/avrxmega3.sh +new file mode 100644 +index 0000000..abaa5b3 +--- /dev/null ++++ b/ld/emulparams/avrxmega3.sh +@@ -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 --git a/ld/emulparams/avrxmega4.sh b/ld/emulparams/avrxmega4.sh +new file mode 100644 +index 0000000..829c8b7 +--- /dev/null ++++ b/ld/emulparams/avrxmega4.sh +@@ -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 --git a/ld/emulparams/avrxmega5.sh b/ld/emulparams/avrxmega5.sh +new file mode 100644 +index 0000000..0a09aee +--- /dev/null ++++ b/ld/emulparams/avrxmega5.sh +@@ -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 --git a/ld/emulparams/avrxmega6.sh b/ld/emulparams/avrxmega6.sh +new file mode 100644 +index 0000000..3c3a468 +--- /dev/null ++++ b/ld/emulparams/avrxmega6.sh +@@ -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 --git a/ld/emulparams/avrxmega7.sh b/ld/emulparams/avrxmega7.sh +new file mode 100644 +index 0000000..b84a0ba +--- /dev/null ++++ b/ld/emulparams/avrxmega7.sh +@@ -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 --git a/ld/emultempl/avrelf.em b/ld/emultempl/avrelf.em +index f0807dd..e328c77 100644 +--- a/ld/emultempl/avrelf.em ++++ b/ld/emultempl/avrelf.em +@@ -71,8 +71,10 @@ avr_elf_${EMULATION_NAME}_before_allocation (void) + + 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 --git a/opcodes/avr-dis.c b/opcodes/avr-dis.c +index 976c371..e3ff59c 100644 +--- a/opcodes/avr-dis.c ++++ b/opcodes/avr-dis.c +@@ -50,7 +50,7 @@ static const char * comment_start = "0x"; + + 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 @@ avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constra + + case 'z': + *buf++ = 'Z'; +- if (insn & 0x1) ++ ++ /* 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")); +@@ -227,6 +237,10 @@ avr_operand (unsigned int insn, unsigned int insn2, unsigned int pc, int constra + } + break; + ++ case 'E': ++ sprintf (buf, "%d", (insn >> 4) & 15); ++ break; ++ + case '?': + *buf = '\0'; + break; +@@ -331,7 +345,8 @@ print_insn_avr (bfd_vma addr, disassemble_info *info) + + if (opcode->name) + { +- char *op = opcode->constraints; ++ char *constraints = opcode->constraints; ++ char *opcode_str = opcode->opcode; + + insn2 = 0; + ok = 1; +@@ -342,14 +357,14 @@ print_insn_avr (bfd_vma addr, disassemble_info *info) + 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); + } + } +-- +1.6.0.4 + diff --git a/patches/binutils-2.20.1a/atmel/0007-Add-remove-support-for-devices.patch b/patches/binutils-2.20.1a/atmel/0007-Add-remove-support-for-devices.patch new file mode 100644 index 0000000..b4a915f --- /dev/null +++ b/patches/binutils-2.20.1a/atmel/0007-Add-remove-support-for-devices.patch @@ -0,0 +1,253 @@ +From 29bc673719635293f6dd8fee0a16d7ed1630fb67 Mon Sep 17 00:00:00 2001 +From: Stephan Linz +Date: Mon, 18 Apr 2011 23:19:07 +0200 +Subject: [PATCH 7/9] Add/remove support for devices + +Add support for a bunch of new AVR devices, and removes support +for some listed devices as well: atmega8m1, atmega8c1, atmega16c1, +atmega4hvd, atmega8hvd, attiny327, m3000f, m3000s, m3001b. + +Quote by Eric Weddington (2010-04-08): +http://old.nabble.com/-PATCH%2C-AVR--Add-remove-support-for-devices-td28172078.html + +Original ATMEL patch from: +http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/51-binutils-2.20.1-new-devices.patch + +Signed-off-by: Stephan Linz +--- + binutils/size.c | 3 --- + gas/config/tc-avr.c | 43 ++++++++++++++++++++++++++++++++++--------- + gas/doc/c-avr.texi | 40 +++++++++++++++++++++++----------------- + 3 files changed, 57 insertions(+), 29 deletions(-) + +diff --git a/binutils/size.c b/binutils/size.c +index cd1635a..a6c8e6c 100644 +--- a/binutils/size.c ++++ b/binutils/size.c +@@ -208,7 +208,6 @@ avr_device_t avr[] = + {"atmega32c1", AVR32K, AVR2K, AVR1K}, + {"atmega32hvb", AVR32K, AVR2K, AVR1K}, + {"atmega32m1", AVR32K, AVR2K, AVR1K}, +- {"attiny327", AVR32K, AVR2K, AVR1K}, + {"atmega32u2", AVR32K, AVR2K, AVR1K}, + {"atmega32u4", AVR32K, 2560UL, AVR1K}, + {"atmega32u6", AVR32K, 2560UL, AVR1K}, +@@ -268,7 +267,6 @@ avr_device_t avr[] = + {"atmega88pa", AVR8K, AVR1K, AVR512}, + {"atmega8hva", AVR8K, 768UL, AVR256}, + {"atmega8u2", AVR8K, AVR512, AVR512}, +- {"atmega8hvd", AVR8K, AVR512, AVR256}, + {"attiny84", AVR8K, AVR512, AVR512}, + {"attiny84a", AVR8K, AVR512, AVR512}, + {"attiny85", AVR8K, AVR512, AVR512}, +@@ -283,7 +281,6 @@ avr_device_t avr[] = + {"atmega48", AVR4K, AVR512, AVR256}, + {"atmega48a", AVR4K, AVR512, AVR256}, + {"atmega48p", AVR4K, AVR512, AVR256}, +- {"atmega4hvd", AVR4K, AVR512, AVR256}, + {"attiny4313", AVR4K, AVR256, AVR256}, + {"attiny43u", AVR4K, AVR256, AVR64}, + {"attiny44", AVR4K, AVR256, AVR256}, +diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c +index 184b028..90918df 100644 +--- a/gas/config/tc-avr.c ++++ b/gas/config/tc-avr.c +@@ -115,12 +115,14 @@ static struct mcu_type_s mcu_types[] = + {"attiny44", AVR_ISA_AVR25, bfd_mach_avr25}, + {"attiny44a", AVR_ISA_AVR25, bfd_mach_avr25}, + {"attiny84", AVR_ISA_AVR25, bfd_mach_avr25}, ++ {"attiny84a", AVR_ISA_AVR25, bfd_mach_avr25}, + {"attiny25", AVR_ISA_AVR25, bfd_mach_avr25}, + {"attiny45", AVR_ISA_AVR25, bfd_mach_avr25}, + {"attiny85", AVR_ISA_AVR25, bfd_mach_avr25}, + {"attiny261", AVR_ISA_AVR25, bfd_mach_avr25}, + {"attiny261a", AVR_ISA_AVR25, bfd_mach_avr25}, + {"attiny461", AVR_ISA_AVR25, bfd_mach_avr25}, ++ {"attiny461a", AVR_ISA_AVR25, bfd_mach_avr25}, + {"attiny861", AVR_ISA_AVR25, bfd_mach_avr25}, + {"attiny861a", AVR_ISA_AVR25, bfd_mach_avr25}, + {"attiny87", AVR_ISA_AVR25, bfd_mach_avr25}, +@@ -134,7 +136,6 @@ static struct mcu_type_s mcu_types[] = + {"atmega103", AVR_ISA_AVR31, bfd_mach_avr31}, + {"at43usb320", AVR_ISA_AVR31, bfd_mach_avr31}, + {"attiny167", AVR_ISA_AVR35, bfd_mach_avr35}, +- {"attiny327", AVR_ISA_AVR35, bfd_mach_avr35}, + {"at90usb82", AVR_ISA_AVR35, bfd_mach_avr35}, + {"at90usb162", AVR_ISA_AVR35, bfd_mach_avr35}, + {"atmega8u2", AVR_ISA_AVR35, bfd_mach_avr35}, +@@ -142,16 +143,15 @@ static struct mcu_type_s mcu_types[] = + {"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}, +- {"atmega4hvd", AVR_ISA_AVR4, bfd_mach_avr4}, +- {"atmega8hvd", AVR_ISA_AVR4, bfd_mach_avr4}, +- {"atmega8c1", AVR_ISA_AVR4, bfd_mach_avr4}, +- {"atmega8m1", AVR_ISA_AVR4, bfd_mach_avr4}, + {"at90pwm1", AVR_ISA_AVR4, bfd_mach_avr4}, + {"at90pwm2", AVR_ISA_AVR4, bfd_mach_avr4}, + {"at90pwm2b", AVR_ISA_AVR4, bfd_mach_avr4}, +@@ -159,40 +159,67 @@ static struct mcu_type_s mcu_types[] = + {"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}, ++ {"atmega165a", 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}, +- {"atmega16c1", 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}, + {"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}, ++ {"atmega325a", AVR_ISA_AVR5, bfd_mach_avr5}, + {"atmega325p", AVR_ISA_AVR5, bfd_mach_avr5}, + {"atmega3250", AVR_ISA_AVR5, bfd_mach_avr5}, ++ {"atmega3250a",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}, ++ {"atmega329a", 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}, ++ {"atmega3290a",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}, +@@ -211,6 +238,7 @@ static struct mcu_type_s mcu_types[] = + {"at90usb647", AVR_ISA_AVR5, bfd_mach_avr5}, + {"at90scr100", AVR_ISA_AVR5, bfd_mach_avr5}, + {"at94k", AVR_ISA_94K, bfd_mach_avr5}, ++ {"m3000", AVR_ISA_AVR5, bfd_mach_avr5}, + {"atmega128", AVR_ISA_AVR51, bfd_mach_avr51}, + {"atmega1280", AVR_ISA_AVR51, bfd_mach_avr51}, + {"atmega1281", AVR_ISA_AVR51, bfd_mach_avr51}, +@@ -219,9 +247,6 @@ static struct mcu_type_s mcu_types[] = + {"at90can128", AVR_ISA_AVR51, bfd_mach_avr51}, + {"at90usb1286",AVR_ISA_AVR51, bfd_mach_avr51}, + {"at90usb1287",AVR_ISA_AVR51, bfd_mach_avr51}, +- {"m3000f", AVR_ISA_AVR51, bfd_mach_avr51}, +- {"m3000s", AVR_ISA_AVR51, bfd_mach_avr51}, +- {"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}, +diff --git a/gas/doc/c-avr.texi b/gas/doc/c-avr.texi +index ba0927c..c04c546 100644 +--- a/gas/doc/c-avr.texi ++++ b/gas/doc/c-avr.texi +@@ -43,9 +43,10 @@ at90s8535). + + 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, attiny84a, 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). +@@ -54,28 +55,33 @@ Instruction set avr31 is for the classic AVR core with exactly 128K program + memory space (MCU types: atmega103, at43usb320). + + Instruction set avr35 is for classic AVR core plus MOVW, CALL, and JMP +-instructions (MCU types: attiny167, attiny327, at90usb82, at90usb162, atmega8u2, ++instructions (MCU types: attiny167, at90usb82, at90usb162, atmega8u2, + 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, ++at90pwm1,at90pwm2, at90pwm2b, at90pwm3, at90pwm3b, ++at90pwm81). + + 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, ++atmega32, atmega323, atmega324a, atmega324p, atmega324pa, atmega325, atmega325a, ++atmega325p, atmega3250, atmega3250a, atmega3250p, atmega328, atmega328p, ++atmega329, atmega329a, atmega329p, atmega329pa, atmega3290, atmega3290a, ++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, +-atmega128rfa1, at90can128, at90usb1286, at90usb1287, m3000f, m3000s, m3001b). ++atmega128rfa1, at90can128, at90usb1286, at90usb1287, m3000). + + Instruction set avr6 is for the enhanced AVR core with a 3-byte PC (MCU types: + atmega2560, atmega2561). +-- +1.6.0.4 + diff --git a/patches/binutils-2.20.1a/atmel/0008-Add-support-for-devices-with-16-gp-registers.patch b/patches/binutils-2.20.1a/atmel/0008-Add-support-for-devices-with-16-gp-registers.patch new file mode 100644 index 0000000..7a26a38 --- /dev/null +++ b/patches/binutils-2.20.1a/atmel/0008-Add-support-for-devices-with-16-gp-registers.patch @@ -0,0 +1,283 @@ +From 01a36bb280f0af0d84bbf09f37372919395f9de8 Mon Sep 17 00:00:00 2001 +From: Stephan Linz +Date: Tue, 19 Apr 2011 00:23:01 +0200 +Subject: [PATCH 8/9] Add support for devices with 16 gp registers + +Add support for a bunch of new AVR devices, especially tiny devices +with 16 gp registers: attiny4, attiny5, attiny9, attiny10, attiny20, +attiny40 + +Original ATMEL patch from: +http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/52-binutils-2.20.1-avrtiny10.patch + +Signed-off-by: Stephan Linz +--- + bfd/archures.c | 1 + + bfd/bfd-in2.h | 1 + + bfd/cpu-avr.c | 5 ++++- + bfd/elf32-avr.c | 8 ++++++++ + gas/config/tc-avr.c | 19 +++++++++++++++++++ + include/elf/avr.h | 1 + + include/opcode/avr.h | 14 +++++++------- + ld/Makefile.am | 5 +++++ + ld/Makefile.in | 5 +++++ + ld/configure.tgt | 2 +- + ld/emulparams/avrtiny10.sh | 12 ++++++++++++ + 11 files changed, 64 insertions(+), 9 deletions(-) + create mode 100644 ld/emulparams/avrtiny10.sh + +diff --git a/bfd/archures.c b/bfd/archures.c +index 390ccec..6a1062c 100644 +--- a/bfd/archures.c ++++ b/bfd/archures.c +@@ -375,6 +375,7 @@ DESCRIPTION + .#define bfd_mach_avrxmega5 105 + .#define bfd_mach_avrxmega6 106 + .#define bfd_mach_avrxmega7 107 ++.#define bfd_mach_avrtiny10 201 + . bfd_arch_bfin, {* ADI Blackfin *} + .#define bfd_mach_bfin 1 + . bfd_arch_cr16, {* National Semiconductor CompactRISC (ie CR16). *} +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index 0821cd0..c093108 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -2049,6 +2049,7 @@ enum bfd_architecture + #define bfd_mach_avrxmega5 105 + #define bfd_mach_avrxmega6 106 + #define bfd_mach_avrxmega7 107 ++#define bfd_mach_avrtiny10 201 + bfd_arch_bfin, /* ADI Blackfin */ + #define bfd_mach_bfin 1 + bfd_arch_cr16, /* National Semiconductor CompactRISC (ie CR16). */ +diff --git a/bfd/cpu-avr.c b/bfd/cpu-avr.c +index 6562ee5..0cc66fc 100644 +--- a/bfd/cpu-avr.c ++++ b/bfd/cpu-avr.c +@@ -154,7 +154,10 @@ static const bfd_arch_info_type arch_info_struct[] = + N (24, bfd_mach_avrxmega6, "avr:106", FALSE, & arch_info_struct[16]), + + /* Xmega 7 */ +- N (24, bfd_mach_avrxmega7, "avr:107", FALSE, NULL) ++ N (24, bfd_mach_avrxmega7, "avr:107", FALSE, & arch_info_struct[17]), ++ ++ /* attiny 10 */ ++ N (16, bfd_mach_avrtiny10, "avr:201", FALSE, NULL) + + }; + +diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c +index 62ce9fb..af85301 100644 +--- a/bfd/elf32-avr.c ++++ b/bfd/elf32-avr.c +@@ -1356,6 +1356,10 @@ bfd_elf_avr_final_write_processing (bfd *abfd, + case bfd_mach_avrxmega7: + val = E_AVR_MACH_XMEGA7; + break; ++ ++ case bfd_mach_avrtiny10: ++ val = E_AVR_MACH_AVRTINY10; ++ break; + } + + elf_elfheader (abfd)->e_machine = EM_AVR; +@@ -1446,6 +1450,10 @@ elf32_avr_object_p (bfd *abfd) + case E_AVR_MACH_XMEGA7: + e_set = bfd_mach_avrxmega7; + break; ++ ++ case E_AVR_MACH_AVRTINY10: ++ e_set = bfd_mach_avrtiny10; ++ break; + } + } + return bfd_default_set_arch_mach (abfd, bfd_arch_avr, +diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c +index 90918df..20501bb 100644 +--- a/gas/config/tc-avr.c ++++ b/gas/config/tc-avr.c +@@ -88,6 +88,7 @@ static struct mcu_type_s mcu_types[] = + {"avrxmega5", AVR_ISA_XMEGA, bfd_mach_avrxmega5}, + {"avrxmega6", AVR_ISA_XMEGA, bfd_mach_avrxmega6}, + {"avrxmega7", AVR_ISA_XMEGA, bfd_mach_avrxmega7}, ++ {"avrtiny10", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, + {"at90s1200", AVR_ISA_1200, bfd_mach_avr1}, + {"attiny11", AVR_ISA_AVR1, bfd_mach_avr1}, + {"attiny12", AVR_ISA_AVR1, bfd_mach_avr1}, +@@ -264,6 +265,12 @@ static struct mcu_type_s mcu_types[] = + {"atxmega256a3b",AVR_ISA_XMEGA, bfd_mach_avrxmega6}, + {"atxmega256d3", AVR_ISA_XMEGA, bfd_mach_avrxmega6}, + {"atxmega128a1", AVR_ISA_XMEGA, bfd_mach_avrxmega7}, ++ {"attiny4", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, ++ {"attiny5", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, ++ {"attiny9", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, ++ {"attiny10", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, ++ {"attiny20", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, ++ {"attiny40", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, + {NULL, 0, 0} + }; + +@@ -446,6 +453,7 @@ md_show_usage (FILE *stream) + " avrxmega5 - XMEGA, > 64K, <= 128K FLASH, > 64K RAM\n" + " avrxmega6 - XMEGA, > 128K, <= 256K FLASH, <= 64K RAM\n" + " avrxmega7 - XMEGA, > 128K, <= 256K FLASH, > 64K RAM\n" ++ " avrtiny10 - tiny devices with 16 gp registers\n" + " or immediate microcontroller name.\n")); + fprintf (stream, + _(" -mall-opcodes accept all AVR opcodes, even if not supported by MCU\n" +@@ -793,6 +801,17 @@ avr_operand (struct avr_opcodes_s *opcode, + op_mask = avr_get_constant (str, 31); + str = input_line_pointer; + } ++ if (strcmp(avr_mcu->name, "avrtiny10") == 0 ++ || strcmp(avr_mcu->name, "attiny10") == 0 ++ || strcmp(avr_mcu->name, "attiny4") == 0 ++ || strcmp(avr_mcu->name, "attiny5") == 0 ++ || strcmp(avr_mcu->name, "attiny9") == 0 ++ || strcmp(avr_mcu->name, "attiny20") == 0 ++ || strcmp(avr_mcu->name, "attiny40") == 0) ++ { ++ if(op_mask < 16) ++ as_bad (_("register number above 15 required")); ++ } + + if (op_mask <= 31) + { +diff --git a/include/elf/avr.h b/include/elf/avr.h +index e86eb11..d334870 100644 +--- a/include/elf/avr.h ++++ b/include/elf/avr.h +@@ -47,6 +47,7 @@ + #define E_AVR_MACH_XMEGA5 105 + #define E_AVR_MACH_XMEGA6 106 + #define E_AVR_MACH_XMEGA7 107 ++#define E_AVR_MACH_AVRTINY10 201 + + /* Relocations. */ + START_RELOC_NUMBERS (elf_avr_reloc_type) +diff --git a/include/opcode/avr.h b/include/opcode/avr.h +index cff7b06..3f0417d 100644 +--- a/include/opcode/avr.h ++++ b/include/opcode/avr.h +@@ -69,7 +69,7 @@ + AVR_ISA_ELPM | AVR_ISA_ELPMX | AVR_ISA_SPM | \ + AVR_ISA_SPM | AVR_ISA_BRK | AVR_ISA_EIND | \ + AVR_ISA_MOVW) +- ++#define AVR_ISA_AVRTINY10 (AVR_ISA_1200 | AVR_ISA_BRK | AVR_ISA_SRAM) + #define REGISTER_P(x) ((x) == 'r' \ + || (x) == 'd' \ + || (x) == 'w' \ +@@ -159,8 +159,8 @@ AVR_INSN (sez, "", "1001010000011000", 1, AVR_ISA_1200, 0x9418) + AVR_INSN (bclr, "S", "100101001SSS1000", 1, AVR_ISA_1200, 0x9488) + AVR_INSN (bset, "S", "100101000SSS1000", 1, AVR_ISA_1200, 0x9408) + +-AVR_INSN (icall,"", "1001010100001001", 1, AVR_ISA_2xxx, 0x9509) +-AVR_INSN (ijmp, "", "1001010000001001", 1, AVR_ISA_2xxx, 0x9409) ++AVR_INSN (icall,"", "1001010100001001", 1, AVR_ISA_SRAM, 0x9509) ++AVR_INSN (ijmp, "", "1001010000001001", 1, AVR_ISA_SRAM, 0x9409) + + AVR_INSN (lpm, "?", "1001010111001000", 1, AVR_ISA_TINY1,0x95c8) + AVR_INSN (lpm, "r,z", "1001000ddddd010+", 1, AVR_ISA_LPMX, 0x9004) +@@ -260,8 +260,8 @@ AVR_INSN (dec, "r", "1001010rrrrr1010", 1, AVR_ISA_1200, 0x940a) + AVR_INSN (inc, "r", "1001010rrrrr0011", 1, AVR_ISA_1200, 0x9403) + AVR_INSN (lsr, "r", "1001010rrrrr0110", 1, AVR_ISA_1200, 0x9406) + AVR_INSN (neg, "r", "1001010rrrrr0001", 1, AVR_ISA_1200, 0x9401) +-AVR_INSN (pop, "r", "1001000rrrrr1111", 1, AVR_ISA_2xxx, 0x900f) +-AVR_INSN (push, "r", "1001001rrrrr1111", 1, AVR_ISA_2xxx, 0x920f) ++AVR_INSN (pop, "r", "1001000rrrrr1111", 1, AVR_ISA_SRAM, 0x900f) ++AVR_INSN (push, "r", "1001001rrrrr1111", 1, AVR_ISA_SRAM, 0x920f) + AVR_INSN (ror, "r", "1001010rrrrr0111", 1, AVR_ISA_1200, 0x9407) + AVR_INSN (swap, "r", "1001010rrrrr0010", 1, AVR_ISA_1200, 0x9402) + +@@ -273,8 +273,8 @@ AVR_INSN (fmul, "a,a", "000000110ddd1rrr", 1, AVR_ISA_MUL, 0x0308) + AVR_INSN (fmuls,"a,a", "000000111ddd0rrr", 1, AVR_ISA_MUL, 0x0380) + AVR_INSN (fmulsu,"a,a","000000111ddd1rrr", 1, AVR_ISA_MUL, 0x0388) + +-AVR_INSN (sts, "i,r", "1001001ddddd0000", 2, AVR_ISA_2xxx, 0x9200) +-AVR_INSN (lds, "r,i", "1001000ddddd0000", 2, AVR_ISA_2xxx, 0x9000) ++AVR_INSN (sts, "i,r", "1001001ddddd0000", 2, AVR_ISA_SRAM, 0x9200) ++AVR_INSN (lds, "r,i", "1001000ddddd0000", 2, AVR_ISA_SRAM, 0x9000) + + /* Special case for b+0, `e' must be next entry after `b', + b={Y=1,Z=0}, ee={X=11,Y=10,Z=00}, !=1 if -e or e+ or X. */ +diff --git a/ld/Makefile.am b/ld/Makefile.am +index 80b8f22..484b944 100644 +--- a/ld/Makefile.am ++++ b/ld/Makefile.am +@@ -155,6 +155,7 @@ ALL_EMULATIONS = \ + eavrxmega5.o \ + eavrxmega6.o \ + eavrxmega7.o \ ++ eavrtiny10.o \ + ecoff_i860.o \ + ecoff_sparc.o \ + eelf32_spu.o \ +@@ -762,6 +763,10 @@ eavrxmega7.c: $(srcdir)/emulparams/avrxmega7.sh \ + $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \ + ${GEN_DEPENDS} + ${GENSCRIPTS} avrxmega7 "$(tdir_avr2)" ++eavrtiny10.c: $(srcdir)/emulparams/avrtiny10.sh \ ++ $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \ ++ ${GEN_DEPENDS} ++ ${GENSCRIPTS} avrtiny10 "$(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 --git a/ld/Makefile.in b/ld/Makefile.in +index 2d5c8a0..c1e9e9c 100644 +--- a/ld/Makefile.in ++++ b/ld/Makefile.in +@@ -441,6 +441,7 @@ ALL_EMULATIONS = \ + eavrxmega5.o \ + eavrxmega6.o \ + eavrxmega7.o \ ++ eavrtiny10.o \ + ecoff_i860.o \ + ecoff_sparc.o \ + eelf32_spu.o \ +@@ -2104,6 +2105,10 @@ eavrxmega7.c: $(srcdir)/emulparams/avrxmega7.sh \ + $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \ + ${GEN_DEPENDS} + ${GENSCRIPTS} avrxmega7 "$(tdir_avr2)" ++eavrtiny10.c: $(srcdir)/emulparams/avrtiny10.sh \ ++ $(srcdir)/emultempl/avrelf.em $(ELF_DEPS) $(srcdir)/scripttempl/avr.sc \ ++ ${GEN_DEPENDS} ++ ${GENSCRIPTS} avrtiny10 "$(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 --git a/ld/configure.tgt b/ld/configure.tgt +index 9ceefa5..f64dd5b 100644 +--- a/ld/configure.tgt ++++ b/ld/configure.tgt +@@ -110,7 +110,7 @@ xscale-*-coff) targ_emul=armcoff ;; + xscale-*-elf) targ_emul=armelf + ;; + avr-*-*) targ_emul=avr2 +- targ_extra_emuls="avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7" ++ targ_extra_emuls="avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny10" + ;; + bfin-*-elf) targ_emul=elf32bfin; + targ_extra_emuls="elf32bfinfd" +diff --git a/ld/emulparams/avrtiny10.sh b/ld/emulparams/avrtiny10.sh +new file mode 100644 +index 0000000..d530097 +--- /dev/null ++++ b/ld/emulparams/avrtiny10.sh +@@ -0,0 +1,12 @@ ++ARCH=avr:201 ++MACHINE= ++SCRIPT_NAME=avr ++OUTPUT_FORMAT="elf32-avr" ++MAXPAGESIZE=1 ++EMBEDDED=yes ++TEMPLATE_NAME=elf32 ++ ++TEXT_LENGTH=4K ++DATA_ORIGIN=0x800040 ++DATA_LENGTH=0x140 ++EXTRA_EM_FILE=avrelf +-- +1.6.0.4 + diff --git a/patches/binutils-2.20.1a/atmel/0009-Add-support-for-more-XMEGA-devices.patch b/patches/binutils-2.20.1a/atmel/0009-Add-support-for-more-XMEGA-devices.patch new file mode 100644 index 0000000..bbb8b64 --- /dev/null +++ b/patches/binutils-2.20.1a/atmel/0009-Add-support-for-more-XMEGA-devices.patch @@ -0,0 +1,101 @@ +From 0a532d69add35e87bd577d6e9341897d8b5080be Mon Sep 17 00:00:00 2001 +From: Stephan Linz +Date: Tue, 19 Apr 2011 00:55:01 +0200 +Subject: [PATCH 9/9] Add support for more XMEGA devices + +Add support for a bunch of new AVR XMEGA devices: atxmega64a1u, +atxmega128a1u, atxmega128b1, atxmega16x1, atxmega32x1 + +Original ATMEL patch from: +http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/53-binutils-2.20.1-xmega128a1u-64a1u.patch +http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/54-binutils-2.20.1-atxmega16x1-32x1.patch +http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1/55-binutils-2.20.1-atxmega128b1.patch + +Signed-off-by: Stephan Linz +--- + binutils/size.c | 1 + + gas/config/tc-avr.c | 5 +++++ + gas/doc/c-avr.texi | 14 ++++++++------ + 3 files changed, 14 insertions(+), 6 deletions(-) + +diff --git a/binutils/size.c b/binutils/size.c +index a6c8e6c..f5ca64b 100644 +--- a/binutils/size.c ++++ b/binutils/size.c +@@ -132,6 +132,7 @@ avr_device_t avr[] = + {"atxmega128a1", AVR136K, AVR8K, AVR2K}, + {"atxmega128a1u", AVR136K, AVR8K, AVR2K}, + {"atxmega128a3", AVR136K, AVR8K, AVR2K}, ++ {"atxmega128b1", AVR136K, AVR8K, AVR2K}, + {"atxmega128d3", AVR136K, AVR8K, AVR2K}, + + {"at43usb320", AVR128K, 608UL, 0UL}, +diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c +index 20501bb..1a22ae7 100644 +--- a/gas/config/tc-avr.c ++++ b/gas/config/tc-avr.c +@@ -252,12 +252,16 @@ static struct mcu_type_s mcu_types[] = + {"atmega2561", AVR_ISA_AVR6, bfd_mach_avr6}, + {"atxmega16a4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, + {"atxmega16d4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, ++ {"atxmega16x1", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, + {"atxmega32a4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, + {"atxmega32d4", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, ++ {"atxmega32x1", AVR_ISA_XMEGA, bfd_mach_avrxmega2}, + {"atxmega64a3", AVR_ISA_XMEGA, bfd_mach_avrxmega4}, + {"atxmega64d3", AVR_ISA_XMEGA, bfd_mach_avrxmega4}, + {"atxmega64a1", AVR_ISA_XMEGA, bfd_mach_avrxmega5}, ++ {"atxmega64a1u",AVR_ISA_XMEGA, bfd_mach_avrxmega5}, + {"atxmega128a3", AVR_ISA_XMEGA, bfd_mach_avrxmega6}, ++ {"atxmega128b1", 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}, +@@ -265,6 +269,7 @@ static struct mcu_type_s mcu_types[] = + {"atxmega256a3b",AVR_ISA_XMEGA, bfd_mach_avrxmega6}, + {"atxmega256d3", AVR_ISA_XMEGA, bfd_mach_avrxmega6}, + {"atxmega128a1", AVR_ISA_XMEGA, bfd_mach_avrxmega7}, ++ {"atxmega128a1u",AVR_ISA_XMEGA, bfd_mach_avrxmega7}, + {"attiny4", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, + {"attiny5", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, + {"attiny9", AVR_ISA_AVRTINY10, bfd_mach_avrtiny10}, +diff --git a/gas/doc/c-avr.texi b/gas/doc/c-avr.texi +index c04c546..07637bf 100644 +--- a/gas/doc/c-avr.texi ++++ b/gas/doc/c-avr.texi +@@ -88,24 +88,26 @@ 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). ++atxmega16x1, atxmega32a4, atxmega32d4, atxmega32x1). + + 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). ++memory space and greater than 64K data space (MCU types: none). + + 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). ++memory space and greater than 64K data space (MCU types: atxmega64a1, ++atxmega64a1u). + + 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). ++atxmega128d3, atxmega192a3, atxmega128b1, 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). ++memory space and greater than 64K data space (MCU types: atxmega128a1, ++atxmega128a1u). + + @cindex @code{-mall-opcodes} command line option, AVR + @item -mall-opcodes +-- +1.6.0.4 + diff --git a/patches/binutils-2.20.1a/series b/patches/binutils-2.20.1a/series new file mode 100644 index 0000000..d1043c8 --- /dev/null +++ b/patches/binutils-2.20.1a/series @@ -0,0 +1,13 @@ +# Atmel's patch set reviewed and pulled from: +# http://distribute.atmel.no/tools/opensource/avr-gcc/binutils-2.20.1 +atmel/0001-Add-AVR-specific-output-format-to-size-utility.patch +atmel/0002-Add-Atmels-AVR-COFF-output-to-objcopy-utility.patch +atmel/0003-Add-new-memory-regions-to-the-AVR-linker-script-temp.patch +atmel/0004-Fix-missing-symbol-for-dwarf2_emit_insn.patch +atmel/0005-Force-DWARF2-debug-output-for-AVR.patch +atmel/0006-Add-support-for-XMEGA-arch-and-devices.patch +atmel/0007-Add-remove-support-for-devices.patch +atmel/0008-Add-support-for-devices-with-16-gp-registers.patch +atmel/0009-Add-support-for-more-XMEGA-devices.patch + +0001-HACK-disable-some-docs-to-avoid-using-makeinfo.patch -- cgit v1.2.3