public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PE+ and new COFF format for x86_64 target for XP64 and Vista binaries
@ 2006-08-17 16:25 Kai Tietz
  2006-08-17 16:45 ` H. J. Lu
  2006-09-08  9:48 ` Pedro Alves
  0 siblings, 2 replies; 17+ messages in thread
From: Kai Tietz @ 2006-08-17 16:25 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 1461 bytes --]

Hallo,

This is a port of binutils-2.17 for COFF-format x86-64 (AMD64) and the PE+ 
for Windows XP64 and Vista EXE/DLL. The target is named x86_64-pc-mingw64. 
I enabled windres and dlltool for this target. For the tool objdump the 
processing and printing methods for DLL-imports are adjusted (they are now 
8 bytes long :( )

I made a copy of the pe_dll(.c&.h) as pep_dll(.c&.h) to minimize 
intersections. May these files can be merged.

In the "include/coff/external.h" I introduced the proper PE+ external 
aouthdr structure without the data_start member. Because this non-existing 
member breaks the
size of the PEPAOUT structure in include/coff/pe.h.

For the bfd/pexxigen.c template I used the pex64 name alias for 
generation.

I added the following new files:
        bfd/coff-x86_64.c
        bfd/pe-x86_64.c
        bfd/pei-x86_64.c
        gas/config/te-pep.h
        include/coff/x86_54.h
        ld/pep_dll.c
        ld/pep_dll.h
        ld/emulparams/i386pep.sh
        ld/emultempl/pep.em
        ld/scripttempl/pep.sc


I tested the ld of this target by MSVC object-files and by (a patched) gcc 
object-files (using this gas) linking against MS-Runtime-libraries.

i.A. Kai Tietz



----------------------------------------
  Kai Tietz - Software engineering
  OneVision Software Entwicklungs GmbH & Co KG
  Dr.-Leo-Ritter-Str. 9, 93049 Regensburg, Germany
  Phone: +49-941-78004-0
  FAX:   +49-941-78004-489
  WWW:   http://www.OneVision.com

[-- Attachment #2: binutils-2.17.pex64.diff --]
[-- Type: application/octet-stream, Size: 217614 bytes --]

diff -rNbu binutils-2.17_org/bfd/Makefile.am binutils-2.17/bfd/Makefile.am
--- binutils-2.17_org/bfd/Makefile.am	2006-06-23 20:17:17.000000000 +0200
+++ binutils-2.17/bfd/Makefile.am	2006-08-09 10:16:54.000000000 +0200
@@ -555,7 +555,11 @@
 	mmo.lo \
 	nlm32-alpha.lo \
 	nlm64.lo \
-	pepigen.lo
+	coff-x86_64.lo \
+	pe-x86_64.lo \
+	pei-x86_64.lo \
+	pepigen.lo \
+	pex64igen.lo
 
 BFD64_BACKENDS_CFILES = \
 	aix5ppc-core.c \
@@ -578,6 +582,9 @@
 	elf64.c \
 	mmo.c \
 	nlm32-alpha.c \
+	coff-x86_64.c \
+	pe-x86_64.c \
+	pei-x86_64.c \
 	nlm64.c
 
 OPTIONAL_BACKENDS = \
@@ -628,7 +635,7 @@
 	$(OPTIONAL_BACKENDS_CFILES)
 
 BUILD_CFILES = \
-	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c
+	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c pex64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 
@@ -781,6 +788,11 @@
 	sed -e s/XX/pe/g < $(srcdir)/peXXigen.c > peigen.new
 	mv -f peigen.new peigen.c
 
+pex64igen.c : peXXigen.c
+	rm -f pex64igen.c
+	sed -e s/XX/pex64/g < $(srcdir)/peXXigen.c > pex64igen.new
+	mv -f pex64igen.new pex64igen.c
+
 pepigen.c : peXXigen.c
 	rm -f pepigen.c
 	sed -e s/XX/pep/g < $(srcdir)/peXXigen.c > pepigen.new
@@ -1830,6 +1842,9 @@
   $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/ia64.h \
   $(INCDIR)/elf/ia64.h $(INCDIR)/elf/reloc-macros.h $(INCDIR)/objalloc.h \
   elf64-target.h
+pex64igen.lo: pex64igen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+  $(INCDIR)/coff/internal.h $(INCDIR)/coff/x86_64.h $(INCDIR)/coff/external.h \
+  $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
 peigen.lo: peigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
diff -rNbu binutils-2.17_org/bfd/Makefile.in binutils-2.17/bfd/Makefile.in
--- binutils-2.17_org/bfd/Makefile.in	2006-06-23 20:17:19.000000000 +0200
+++ binutils-2.17/bfd/Makefile.in	2006-08-09 10:17:56.000000000 +0200
@@ -793,7 +793,11 @@
 	mmo.lo \
 	nlm32-alpha.lo \
 	nlm64.lo \
-	pepigen.lo
+	coff-x86_64.lo \
+	pe-x86_64.lo \
+	pei-x86_64.lo \
+	pepigen.lo \
+	pex64igen.lo
 
 BFD64_BACKENDS_CFILES = \
 	aix5ppc-core.c \
@@ -816,6 +820,9 @@
 	elf64.c \
 	mmo.c \
 	nlm32-alpha.c \
+	coff-x86_64.c \
+	pe-x86_64.c \
+	pei-x86_64.c \
 	nlm64.c
 
 OPTIONAL_BACKENDS = \
@@ -867,7 +874,7 @@
 	$(OPTIONAL_BACKENDS_CFILES)
 
 BUILD_CFILES = \
-	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c
+	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c pex64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 SOURCE_HFILES = \
@@ -1365,6 +1372,11 @@
 	sed -e s/XX/pe/g < $(srcdir)/peXXigen.c > peigen.new
 	mv -f peigen.new peigen.c
 
+pex64igen.c : peXXigen.c
+	rm -f pex64igen.c
+	sed -e s/XX/pex64/g < $(srcdir)/peXXigen.c > pex64igen.new
+	mv -f pex64igen.new pex64igen.c
+	
 pepigen.c : peXXigen.c
 	rm -f pepigen.c
 	sed -e s/XX/pep/g < $(srcdir)/peXXigen.c > pepigen.new
@@ -2399,6 +2411,9 @@
 peigen.lo: peigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
+pex64igen.lo: pex64igen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+  $(INCDIR)/coff/internal.h $(INCDIR)/coff/x86_64.h $(INCDIR)/coff/external.h \
+  $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
 pepigen.lo: pepigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/ia64.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
diff -rNbu binutils-2.17_org/bfd/bfd.c binutils-2.17/bfd/bfd.c
--- binutils-2.17_org/bfd/bfd.c	2006-03-16 13:20:15.000000000 +0100
+++ binutils-2.17/bfd/bfd.c	2006-08-04 11:42:38.000000000 +0200
@@ -858,7 +858,8 @@
      a place will have to be found.  Until then, this hack will do.  */
   if (strncmp (name, "coff-go32", sizeof ("coff-go32") - 1) == 0
       || strcmp (name, "pe-i386") == 0
-      || strcmp (name, "pei-i386") == 0)
+      || strcmp (name, "pei-i386") == 0 ||
+	  strcmp(name,"pe-x86-64")==0 || strcmp(name,"pei-x86-64"))
     return 1;
 
   bfd_set_error (bfd_error_wrong_format);
diff -rNbu binutils-2.17_org/bfd/coff-x86_64.c binutils-2.17/bfd/coff-x86_64.c
--- binutils-2.17_org/bfd/coff-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/bfd/coff-x86_64.c	2006-08-17 09:06:15.000000000 +0200
@@ -0,0 +1,728 @@
+/* BFD back-end for AMD 64 COFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+#ifndef COFF_WITH_pex64
+#define COFF_WITH_pex64
+#endif
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#include "coff/x86_64.h"
+#include "coff/internal.h"
+#include "coff/pe.h"
+#include "libcoff.h"
+
+#define BADMAG(x) AMD64BADMAG(x)
+
+#ifdef COFF_WITH_pex64
+# undef AOUTSZ
+# define AOUTSZ		PEPAOUTSZ
+# define PEAOUTHDR	PEPAOUTHDR
+#endif
+
+static bfd_reloc_status_type coff_amd64_reloc(bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **);
+static reloc_howto_type *coff_amd64_rtype_to_howto(bfd *, asection *, struct internal_reloc *,struct coff_link_hash_entry *, struct internal_syment *,bfd_vma *);
+static reloc_howto_type *coff_amd64_reloc_type_lookup(bfd *, bfd_reloc_code_real_type);
+
+#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 AMD 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 relocatable 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_amd64_reloc(bfd *abfd,arelent *reloc_entry,asymbol *symbol,PTR data,asection *input_section ATTRIBUTE_UNUSED,
+				 bfd *output_bfd,char **error_message ATTRIBUTE_UNUSED)
+{
+  symvalue diff;
+
+#ifndef COFF_WITH_PE
+  if(output_bfd == (bfd *) NULL)
+    return bfd_reloc_continue;
+#endif
+
+  if(bfd_is_com_section (symbol->section)) {
+#ifndef COFF_WITH_PE
+      /* 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
+      /* In PE mode, we do not offset the common symbol.  */
+      diff = reloc_entry->addend;
+#endif
+    }
+  else
+    {
+      /* For some reason bfd_perform_relocation always effectively
+	 ignores the addend for a COFF target when producing
+	 relocatable output.  This seems to be always wrong for 386
+	 COFF, so we handle the addend here instead.  */
+#ifdef COFF_WITH_PE
+      if(output_bfd == (bfd *) NULL)
+	{
+	  reloc_howto_type *howto = reloc_entry->howto;
+
+	  /* Although PC relative relocations are very similar between
+	     PE and non-PE formats, but they are off by 1 << howto->size
+	     bytes. For the external relocation, PE is very different
+	     from others. See md_apply_fix3 () in gas/config/tc-amd64.c.
+	     When we link PE and non-PE object files together to
+	     generate a non-PE executable, we have to compensate it
+	     here.  */
+	  if(howto->pc_relative && howto->pcrel_offset)
+	    diff = -(1 << howto->size);
+	  else if(symbol->flags & BSF_WEAK)
+	    diff = reloc_entry->addend - symbol->value;
+	  else
+	    diff = -reloc_entry->addend;
+	}
+      else
+#endif
+	diff = reloc_entry->addend;
+    }
+
+#ifdef COFF_WITH_PE
+  /* FIXME: How should this case be handled?  */
+  if(reloc_entry->howto->type == R_AMD64_IMAGEBASE
+      && output_bfd!=NULL
+      && bfd_get_flavour(output_bfd) == bfd_target_coff_flavour)
+    diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
+#endif
+
+#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;
+	  case 4:
+	    {
+	      long long x = bfd_get_64 (abfd, addr);
+	      DOIT (x);
+	      bfd_put_64 (abfd, (bfd_vma) x, addr);
+	    }
+	    break;
+
+	  default:
+	    abort ();
+	  }
+      }
+
+  /* Now let bfd_perform_relocation finish everything up.  */
+  return bfd_reloc_continue;
+}
+
+#ifdef COFF_WITH_PE
+/* Return TRUE if this relocation should appear in the output .reloc
+   section.  */
+
+static bfd_boolean in_reloc_p(bfd *, reloc_howto_type *);
+
+static bfd_boolean in_reloc_p(bfd *abfd ATTRIBUTE_UNUSED,reloc_howto_type *howto)
+{
+  return ! howto->pc_relative && howto->type!=R_AMD64_IMAGEBASE;
+}
+#endif /* COFF_WITH_PE */
+
+#ifndef PCRELOFFSET
+#define PCRELOFFSET TRUE
+#endif
+
+static reloc_howto_type howto_table[] =
+{
+  EMPTY_HOWTO (0),
+  HOWTO (R_AMD64_DIR64,		/* type  1*/
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long, 4 = long long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "dir64",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffffffffffff,		/* src_mask */
+	 0xffffffffffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+  HOWTO (R_AMD64_DIR32,		/* type 2 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "dir32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+  /* PE IMAGE_REL_AMD64_ADDR32NB relocation (3).	*/
+  HOWTO (R_AMD64_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_amd64_reloc,	/* special_function */
+	 "rva32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+  /* 32-bit longword PC relative relocation (4).  */
+  HOWTO (R_AMD64_PCRLONG,		/* type 4 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+
+ HOWTO (R_AMD64_PCRLONG_1,		/* type 5 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_2,		/* type 6 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_3,		/* type 7 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_4,		/* type 8 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_5,		/* type 9 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  EMPTY_HOWTO (10), // R_AMD64_SECTION 10
+#ifdef COFF_WITH_PE
+  /* 32-bit longword section relative relocation (11).  */
+  HOWTO (R_AMD64_SECREL,		/* 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_amd64_reloc,	/* special_function */
+	 "secrel32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+#else
+  EMPTY_HOWTO (11),
+#endif
+  EMPTY_HOWTO (12),
+  EMPTY_HOWTO (13),
+  EMPTY_HOWTO (14),
+  /* Byte relocation (15).  */
+  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_amd64_reloc,	/* special_function */
+	 "8",			/* name */
+	 TRUE,			/* partial_inplace */
+	 0x000000ff,		/* src_mask */
+	 0x000000ff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 16-bit word relocation (16).  */
+  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_amd64_reloc,	/* special_function */
+	 "16",			/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 32-bit longword relocation (17).	*/
+  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_amd64_reloc,	/* special_function */
+	 "32",			/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* Byte PC relative relocation (18).	 */
+  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_amd64_reloc,	/* special_function */
+	 "DISP8",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0x000000ff,		/* src_mask */
+	 0x000000ff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 16-bit word PC relative relocation (19).	*/
+  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_amd64_reloc,	/* special_function */
+	 "DISP16",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 32-bit longword PC relative relocation (20).  */
+  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_amd64_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 I386 1			/* Customize coffcode.h */
+#define AMD64 1
+#define RTYPE2HOWTO(cache_ptr, dst)					\
+  ((cache_ptr)->howto =							\
+   ((dst)->r_type < sizeof (howto_table) / sizeof (howto_table[0])	\
+    ? howto_table + (dst)->r_type					\
+    : NULL))
+
+/* For 386 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.  For normal AMD64 COFF, we
+   can use the generic relocate_section routine.  For PE, we need our
+   own routine.  */
+
+#ifndef COFF_WITH_PE
+
+#define coff_relocate_section _bfd_coff_generic_relocate_section
+
+#else /* COFF_WITH_PE */
+
+/* The PE relocate section routine.  The only difference between this
+   and the regular routine is that we don't want to do anything for a
+   relocatable link.  */
+
+static bfd_boolean coff_pe_amd64_relocate_section(bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,struct internal_reloc *, struct internal_syment *, asection **);
+
+static bfd_boolean
+coff_pe_amd64_relocate_section(bfd *output_bfd,struct bfd_link_info *info,bfd *input_bfd,asection *input_section,bfd_byte *contents,struct internal_reloc *relocs,struct internal_syment *syms,asection **sections)
+{
+  if(info->relocatable)
+    return TRUE;
+
+  return _bfd_coff_generic_relocate_section(output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
+}
+
+#define coff_relocate_section coff_pe_amd64_relocate_section
+
+#endif /* COFF_WITH_PE */
+
+/* Convert an rtype to howto for the COFF backend linker.  */
+
+static reloc_howto_type *
+coff_amd64_rtype_to_howto(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;
+
+  if(rel->r_type > sizeof (howto_table) / sizeof (howto_table[0])) {
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
+  if(rel->r_type>=R_AMD64_PCRLONG_1 && rel->r_type<=R_AMD64_PCRLONG_5) {
+	  rel->r_vaddr+=(bfd_vma)(rel->r_type-R_AMD64_PCRLONG);
+	  rel->r_type=R_AMD64_PCRLONG;
+  }
+  howto = howto_table + rel->r_type;
+
+#ifdef COFF_WITH_PE
+  /* Cancel out code in _bfd_coff_generic_relocate_section.  */
+  *addendp = 0;
+#endif
+
+  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);
+
+#ifndef COFF_WITH_PE
+      /* I think we *do* want to bypass this.  If we don't, I have
+	 seen some data parameters get the wrong relocation 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;
+#endif
+    }
+
+#ifndef COFF_WITH_PE
+  /* If the output symbol is common (in which case this must be a
+     relocatable 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;
+#endif
+
+#ifdef COFF_WITH_PE
+  if(howto->pc_relative)
+    {
+      *addendp -= 4;
+
+      /* If the symbol is defined, then the generic code is going to
+         add back the symbol value in order to cancel out an
+         adjustment it made to the addend.  However, we set the addend
+         to 0 at the start of this function.  We need to adjust here,
+         to avoid the adjustment the generic code will make.  FIXME:
+         This is getting a bit hackish.  */
+      if(sym!=NULL && sym->n_scnum!=0)
+	*addendp -= sym->n_value;
+    }
+
+  if(rel->r_type == R_AMD64_IMAGEBASE && (bfd_get_flavour(sec->output_section->owner) == bfd_target_coff_flavour)) {
+      *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
+  }
+
+  if(rel->r_type == R_AMD64_SECREL) {
+      bfd_vma osect_vma;
+
+      if(h && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak))
+	osect_vma = h->root.u.def.section->output_section->vma;
+      else {
+	  asection *sec;
+	  int i;
+
+	  /* Sigh, the only way to get the section to offset against
+	     is to find it the hard way.  */
+
+	  for (sec = abfd->sections, i = 1; i < sym->n_scnum; i++)
+	    sec = sec->next;
+
+	  osect_vma = sec->output_section->vma;
+	}
+
+      *addendp -= osect_vma;
+    }
+#endif
+
+  return howto;
+}
+
+#define coff_bfd_reloc_type_lookup coff_amd64_reloc_type_lookup
+
+static reloc_howto_type *
+coff_amd64_reloc_type_lookup(bfd *abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)
+{
+  switch (code) {
+    case BFD_RELOC_RVA:
+      return howto_table + R_AMD64_IMAGEBASE;
+    case BFD_RELOC_32:
+      return howto_table + R_AMD64_DIR32;
+	 case BFD_RELOC_64:
+		  return howto_table + R_AMD64_DIR64;
+    case BFD_RELOC_32_PCREL:
+	case BFD_RELOC_X86_64_32S:
+      return howto_table + R_AMD64_PCRLONG;
+    case BFD_RELOC_16:
+      return howto_table + R_RELWORD;
+    case BFD_RELOC_16_PCREL:
+      return howto_table + R_PCRWORD;
+    case BFD_RELOC_8:
+      return howto_table + R_RELBYTE;
+    case BFD_RELOC_8_PCREL:
+      return howto_table + R_PCRBYTE;
+#ifdef COFF_WITH_PE
+    case BFD_RELOC_32_SECREL:
+      return howto_table + R_AMD64_SECREL;
+#endif
+    default:
+      BFD_FAIL ();
+      return 0;
+    }
+}
+
+#define coff_rtype_to_howto coff_amd64_rtype_to_howto
+
+#ifdef TARGET_UNDERSCORE
+
+/* If amd64 gcc uses underscores for symbol names, then it does not use
+   a leading dot for local labels, so if TARGET_UNDERSCORE is defined
+   we treat all symbols starting with L as local.  */
+
+static bfd_boolean coff_amd64_is_local_label_name(bfd *, const char *);
+
+static bfd_boolean coff_amd64_is_local_label_name(bfd *abfd,const char *name)
+{
+  if(name[0] == 'L')
+    return TRUE;
+
+  return _bfd_coff_is_local_label_name (abfd, name);
+}
+
+#define coff_bfd_is_local_label_name coff_amd64_is_local_label_name
+
+#endif /* TARGET_UNDERSCORE */
+
+#include "coffcode.h"
+
+#ifdef PE
+#define amd64coff_object_p pe_bfd_object_p
+#else
+#define amd64coff_object_p coff_object_p
+#endif
+
+const bfd_target
+#ifdef TARGET_SYM
+  TARGET_SYM =
+#else
+  x86_64coff_vec =
+#endif
+{
+#ifdef TARGET_NAME
+  TARGET_NAME,
+#else
+ "coff-x86-64",			/* 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 | D_PAGED),
+
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
+#ifdef COFF_WITH_PE
+   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY
+#endif
+   | SEC_CODE | SEC_DATA),
+
+#ifdef TARGET_UNDERSCORE
+  TARGET_UNDERSCORE,		/* leading underscore */
+#else
+  0,				/* leading underscore */
+#endif
+  '/',				/* 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, amd64coff_object_p, /* bfd_check_format */
+       bfd_generic_archive_p, amd64coff_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 -rNbu binutils-2.17_org/bfd/coffcode.h binutils-2.17/bfd/coffcode.h
--- binutils-2.17_org/bfd/coffcode.h	2005-10-25 19:40:09.000000000 +0200
+++ binutils-2.17/bfd/coffcode.h	2006-08-09 12:00:50.000000000 +0200
@@ -1883,6 +1883,12 @@
       arch = bfd_arch_i386;
       break;
 #endif
+#ifdef AMD64MAGIC
+	case AMD64MAGIC:
+		arch=bfd_arch_i386;
+		machine=bfd_mach_x86_64;
+		break;
+#endif
 #ifdef IA64MAGIC
     case IA64MAGIC:
       arch = bfd_arch_ia64;
@@ -2713,13 +2719,18 @@
       return TRUE;
 #endif
 
-#ifdef I386MAGIC
+#if defined(I386MAGIC) || defined(AMD64MAGIC)
     case bfd_arch_i386:
+#ifdef I386MAGIC
       *magicp = I386MAGIC;
+#endif
 #ifdef LYNXOS
       /* Just overwrite the usual value if we're doing Lynx.  */
       *magicp = LYNXCOFFMAGIC;
 #endif
+#ifdef AMD64MAGIC
+	  *magicp=AMD64MAGIC;
+#endif
       return TRUE;
 #endif
 
@@ -3752,13 +3763,17 @@
 #endif
 
 #ifdef COFF_WITH_PE
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   internal_f.f_flags |= IMAGE_FILE_32BIT_MACHINE;
+#endif
 #else
+#ifndef COFF_WITH_pex64
   if (bfd_little_endian (abfd))
     internal_f.f_flags |= F_AR32WR;
   else
     internal_f.f_flags |= F_AR32W;
 #endif
+#endif
 
 #ifdef TI_TARGET_ID
   /* Target id is used in TI COFF v1 and later; COFF0 won't use this field,
@@ -3855,7 +3870,11 @@
 #if defined(LYNXOS)
     internal_a.magic = LYNXCOFFMAGIC;
 #else  /* LYNXOS */
+#ifdef AMD64
+	internal_a.magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+#else
     internal_a.magic = ZMAGIC;
+#endif
 #endif /* LYNXOS */
 #endif /* I386 */
 
diff -rNbu binutils-2.17_org/bfd/config.bfd binutils-2.17/bfd/config.bfd
--- binutils-2.17_org/bfd/config.bfd	2006-04-05 14:41:57.000000000 +0200
+++ binutils-2.17/bfd/config.bfd	2006-07-27 10:10:35.000000000 +0200
@@ -98,7 +98,7 @@
 strongarm*)	 targ_archs=bfd_arm_arch ;;
 thumb*)		 targ_archs=bfd_arm_arch ;;
 v850*)		 targ_archs=bfd_v850_arch ;;
-x86_64)		 targ_archs=bfd_i386_arch ;;
+x86_64*)		 targ_archs=bfd_i386_arch ;;
 xscale*)	 targ_archs=bfd_arm_arch ;;
 xtensa*)	 targ_archs=bfd_xtensa_arch ;;
 z80|r800)	 targ_archs=bfd_z80_arch ;;
@@ -562,6 +562,11 @@
     targ_defvec=bfd_elf64_x86_64_vec
     targ_selvecs="bfd_elf32_i386_vec i386linux_vec bfd_efi_app_ia32_vec"
     ;;
+  x86_64-*-mingw64*)
+    targ_defvec=x86_64pe_vec
+    targ_selvecs="x86_64pe_vec x86_64pei_vec x86_64coff_vec bfd_elf64_x86_64_vec"
+    targ_underscore=yes
+    ;;
 #endif
   i[3-7]86-*-lynxos*)
     targ_defvec=bfd_elf32_i386_vec
diff -rNbu binutils-2.17_org/bfd/configure binutils-2.17/bfd/configure
--- binutils-2.17_org/bfd/configure	2006-06-23 20:17:03.000000000 +0200
+++ binutils-2.17/bfd/configure	2006-08-03 16:38:04.000000000 +0200
@@ -4087,7 +4087,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -4114,6 +4114,9 @@
       ;;
     *64-bit*)
       case $host in
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
@@ -13216,6 +13219,7 @@
     i386aout_vec)		tb="$tb i386aout.lo aout32.lo" ;;
     i386bsd_vec)		tb="$tb i386bsd.lo aout32.lo" ;;
     i386coff_vec)		tb="$tb coff-i386.lo cofflink.lo" ;;
+    x86_64coff_vec)		tb="$tb coff-x86_64.lo cofflink.lo"; target_size=64 ;;
     i386dynix_vec)		tb="$tb i386dynix.lo aout32.lo" ;;
     i386freebsd_vec)		tb="$tb i386freebsd.lo aout32.lo" ;;
     i386linux_vec)		tb="$tb i386linux.lo aout32.lo" ;;
@@ -13226,7 +13230,9 @@
     i386netbsd_vec)		tb="$tb i386netbsd.lo aout32.lo" ;;
     i386os9k_vec)		tb="$tb i386os9k.lo aout32.lo" ;;
     i386pe_vec)			tb="$tb pe-i386.lo peigen.lo cofflink.lo" ;;
-    i386pei_vec)		tb="$tb pei-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pe_vec)			tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
+    i386pei_vec)		tb="$tb pei-i386.lo pepigen.lo cofflink.lo" ;;
+    x86_64pei_vec)		tb="$tb pei-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i860coff_vec)		tb="$tb coff-i860.lo cofflink.lo" ;;
     icoff_big_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
     icoff_little_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
diff -rNbu binutils-2.17_org/bfd/configure.in binutils-2.17/bfd/configure.in
--- binutils-2.17_org/bfd/configure.in	2006-06-23 20:17:07.000000000 +0200
+++ binutils-2.17/bfd/configure.in	2006-08-03 16:39:09.000000000 +0200
@@ -729,6 +729,7 @@
     i386aout_vec)		tb="$tb i386aout.lo aout32.lo" ;;
     i386bsd_vec)		tb="$tb i386bsd.lo aout32.lo" ;;
     i386coff_vec)		tb="$tb coff-i386.lo cofflink.lo" ;;
+    x86_64coff_vec)		tb="$tb coff-x86_64.lo cofflink.lo"; target_size=64 ;;
     i386dynix_vec)		tb="$tb i386dynix.lo aout32.lo" ;;
     i386freebsd_vec)		tb="$tb i386freebsd.lo aout32.lo" ;;
     i386linux_vec)		tb="$tb i386linux.lo aout32.lo" ;;
@@ -739,7 +740,9 @@
     i386netbsd_vec)		tb="$tb i386netbsd.lo aout32.lo" ;;
     i386os9k_vec)		tb="$tb i386os9k.lo aout32.lo" ;;
     i386pe_vec)			tb="$tb pe-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pe_vec)			tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i386pei_vec)		tb="$tb pei-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pei_vec)		tb="$tb pei-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i860coff_vec)		tb="$tb coff-i860.lo cofflink.lo" ;;
     icoff_big_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
     icoff_little_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
diff -rNbu binutils-2.17_org/bfd/libpei.h binutils-2.17/bfd/libpei.h
--- binutils-2.17_org/bfd/libpei.h	2005-05-04 17:53:35.000000000 +0200
+++ binutils-2.17/bfd/libpei.h	2006-08-09 10:42:52.000000000 +0200
@@ -204,6 +204,38 @@
 #define PUT_SCNHDR_LNNOPTR H_PUT_32
 #endif
 
+#ifdef COFF_WITH_pex64
+#define GET_OPTHDR_IMAGE_BASE H_GET_64
+#define PUT_OPTHDR_IMAGE_BASE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_RESERVE H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_RESERVE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_COMMIT H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_COMMIT H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_RESERVE H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_RESERVE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_COMMIT H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_COMMIT H_PUT_64
+#define GET_PDATA_ENTRY bfd_get_32
+
+#define _bfd_XX_bfd_copy_private_bfd_data_common	_bfd_pex64_bfd_copy_private_bfd_data_common
+#define _bfd_XX_bfd_copy_private_section_data		_bfd_pex64_bfd_copy_private_section_data
+#define _bfd_XX_get_symbol_info				_bfd_pex64_get_symbol_info
+#define _bfd_XX_only_swap_filehdr_out			_bfd_pex64_only_swap_filehdr_out
+#define _bfd_XX_print_private_bfd_data_common		_bfd_pex64_print_private_bfd_data_common
+#define _bfd_XXi_final_link_postscript			_bfd_pex64i_final_link_postscript
+#define _bfd_XXi_final_link_postscript			_bfd_pex64i_final_link_postscript
+#define _bfd_XXi_only_swap_filehdr_out			_bfd_pex64i_only_swap_filehdr_out
+#define _bfd_XXi_swap_aouthdr_in			_bfd_pex64i_swap_aouthdr_in
+#define _bfd_XXi_swap_aouthdr_out			_bfd_pex64i_swap_aouthdr_out
+#define _bfd_XXi_swap_aux_in				_bfd_pex64i_swap_aux_in
+#define _bfd_XXi_swap_aux_out				_bfd_pex64i_swap_aux_out
+#define _bfd_XXi_swap_lineno_in				_bfd_pex64i_swap_lineno_in
+#define _bfd_XXi_swap_lineno_out			_bfd_pex64i_swap_lineno_out
+#define _bfd_XXi_swap_scnhdr_out			_bfd_pex64i_swap_scnhdr_out
+#define _bfd_XXi_swap_sym_in				_bfd_pex64i_swap_sym_in
+#define _bfd_XXi_swap_sym_out				_bfd_pex64i_swap_sym_out
+
+#else /* !COFF_WITH_pex64 */
 #ifdef COFF_WITH_pep
 
 #define GET_OPTHDR_IMAGE_BASE H_GET_64
@@ -269,6 +301,7 @@
 #define _bfd_XXi_swap_sym_out				_bfd_pei_swap_sym_out
 
 #endif /* !COFF_WITH_pep */
+#endif /* !COFF_WITH_pex64 */
 
 /* Macro: Returns true if the bfd is a PE executable as opposed to a PE object file.  */
 #define bfd_pe_executable_p(abfd) \
diff -rNbu binutils-2.17_org/bfd/pe-x86_64.c binutils-2.17/bfd/pe-x86_64.c
--- binutils-2.17_org/bfd/pe-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/bfd/pe-x86_64.c	2006-08-17 09:06:42.000000000 +0200
@@ -0,0 +1,54 @@
+/* BFD back-end for Intel/AMD x86_64 PECOFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_SYM 		x86_64pe_vec
+#define TARGET_NAME 		"pe-x86-64"
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+#define PCRELOFFSET 		TRUE
+#define TARGET_UNDERSCORE 	'_'
+#define COFF_LONG_SECTION_NAMES
+#define COFF_SUPPORT_GNU_LINKONCE
+#define COFF_LONG_FILENAMES
+
+#define COFF_SECTION_ALIGNMENT_ENTRIES \
+{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
+
+#include "coff-x86_64.c"
diff -rNbu binutils-2.17_org/bfd/peXXigen.c binutils-2.17/bfd/peXXigen.c
--- binutils-2.17_org/bfd/peXXigen.c	2006-01-09 16:58:42.000000000 +0100
+++ binutils-2.17/bfd/peXXigen.c	2006-08-09 11:57:35.000000000 +0200
@@ -52,7 +52,7 @@
    on this code has a chance of getting something accomplished without
    wasting too much time.  */
 
-/* This expands into COFF_WITH_pe or COFF_WITH_pep depending on whether
+/* This expands into COFF_WITH_pe, COFF_WITH_pep, or COFF_WITH_pex64 depending on whether
    we're compiling for straight PE or PE+.  */
 #define COFF_WITH_XX
 
@@ -67,17 +67,21 @@
    within PE/PEI, so we get them from there.  FIXME: The lack of
    variance is an assumption which may prove to be incorrect if new
    PE/PEI targets are created.  */
+#ifdef COFF_WITH_pex64
+# include "coff/x86_64.h"
+#else
 #ifdef COFF_WITH_pep
 # include "coff/ia64.h"
 #else
 # include "coff/i386.h"
 #endif
+#endif
 
 #include "coff/pe.h"
 #include "libcoff.h"
 #include "libpei.h"
 
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
 # undef AOUTSZ
 # define AOUTSZ		PEPAOUTSZ
 # define PEAOUTHDR	PEPAOUTHDR
@@ -398,7 +402,7 @@
   aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry);
   aouthdr_int->text_start =
     GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   aouthdr_int->data_start =
     GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start);
@@ -454,7 +458,7 @@
   if (aouthdr_int->entry)
     {
       aouthdr_int->entry += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_int->entry &= 0xffffffff;
 #endif
     }
@@ -462,12 +466,12 @@
   if (aouthdr_int->tsize)
     {
       aouthdr_int->text_start += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_int->text_start &= 0xffffffff;
 #endif
     }
 
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   if (aouthdr_int->dsize)
     {
@@ -547,7 +551,7 @@
   if (aouthdr_in->tsize)
     {
       aouthdr_in->text_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->text_start &= 0xffffffff;
 #endif
     }
@@ -555,7 +559,7 @@
   if (aouthdr_in->dsize)
     {
       aouthdr_in->data_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->data_start &= 0xffffffff;
 #endif
     }
@@ -563,7 +567,7 @@
   if (aouthdr_in->entry)
     {
       aouthdr_in->entry -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->entry &= 0xffffffff;
 #endif
     }
@@ -660,7 +664,7 @@
   PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
 			  aouthdr_out->standard.text_start);
 
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
 			  aouthdr_out->standard.data_start);
@@ -1261,6 +1265,35 @@
 	    }
 
 	  /* Print HintName vector entries.  */
+#ifdef COFF_WITH_pex64
+	  for (j = 0; j < datasize; j += 8)
+	    {
+			unsigned long member = bfd_get_32(abfd,data+idx+j);
+			unsigned long member_high = bfd_get_32(abfd,data+idx+j+4);
+			if(!member && !member_high) break;
+	      if (member_high & 0x80000000)
+		fprintf (file, "\t%lx%08lx\t %4lx%08lx  <none>",
+			 member_high,member, member_high & 0x7fffffff,member);
+	      else
+		{
+		  int ordinal;
+		  char *member_name;
+
+		  ordinal = bfd_get_16 (abfd, data + member - adj);
+		  member_name = (char *) data + member - adj + 2;
+		  fprintf (file, "\t%04lx\t %4d  %s",member, ordinal, member_name);
+		  }
+
+	      /* If the time stamp is not zero, the import address
+		 table holds actual addresses.  */
+	      if (time_stamp != 0
+		  && first_thunk != 0
+		  && first_thunk != hint_addr)
+		fprintf (file, "\t%04lx",
+			 (long) bfd_get_32 (abfd, ft_data + ft_idx + j));
+	      fprintf (file, "\n");
+	    }
+#else
 	  for (j = 0; j < datasize; j += 4)
 	    {
 	      unsigned long member = bfd_get_32 (abfd, data + idx + j);
@@ -1290,9 +1323,9 @@
 		  && first_thunk != hint_addr)
 		fprintf (file, "\t%04lx",
 			 (long) bfd_get_32 (abfd, ft_data + ft_idx + j));
-
 	      fprintf (file, "\n");
 	    }
+#endif
 
 	  if (ft_allocated)
 	    free (ft_data);
@@ -1533,7 +1566,7 @@
 static bfd_boolean
 pe_print_pdata (bfd * abfd, void * vfile)
 {
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
 # define PDATA_ROW_SIZE	(3*8)
 #else
 # define PDATA_ROW_SIZE	(5*4)
@@ -1559,7 +1592,7 @@
 
   fprintf (file,
 	   _("\nThe Function Table (interpreted .pdata section contents)\n"));
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   fprintf (file,
 	   _(" vma:\t\t\tBegin Address    End Address      Unwind Info\n"));
 #else
@@ -1613,7 +1646,7 @@
       fprintf_vma (file, begin_addr); fputc (' ', file);
       fprintf_vma (file, end_addr); fputc (' ', file);
       fprintf_vma (file, eh_handler);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
       fputc (' ', file);
       fprintf_vma (file, eh_data); fputc (' ', file);
       fprintf_vma (file, prolog_end_addr);
diff -rNbu binutils-2.17_org/bfd/pei-x86_64.c binutils-2.17/bfd/pei-x86_64.c
--- binutils-2.17_org/bfd/pei-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/bfd/pei-x86_64.c	2006-08-17 09:06:59.000000000 +0200
@@ -0,0 +1,55 @@
+/* BFD back-end for Intel 386 PE IMAGE COFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_SYM 		x86_64pei_vec
+#define TARGET_NAME 		"pei-x86-64"
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+#define PCRELOFFSET 		TRUE
+#define TARGET_UNDERSCORE 	'_'
+#define COFF_LONG_SECTION_NAMES
+#define COFF_SUPPORT_GNU_LINKONCE
+#define COFF_LONG_FILENAMES
+
+#define COFF_SECTION_ALIGNMENT_ENTRIES \
+{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
+
+#include "coff-x86_64.c"
diff -rNbu binutils-2.17_org/bfd/peicode.h binutils-2.17/bfd/peicode.h
--- binutils-2.17_org/bfd/peicode.h	2005-05-04 17:53:37.000000000 +0200
+++ binutils-2.17/bfd/peicode.h	2006-08-09 10:54:39.000000000 +0200
@@ -183,8 +183,16 @@
 #ifdef COFF_IMAGE_WITH_PE
 # define coff_swap_filehdr_out _bfd_XXi_only_swap_filehdr_out
 #else
+#ifdef COFF_WITH_pex64
+#define coff_swap_filehdr_out _bfd_pex64_only_swap_filehdr_out
+#else
+#ifdef COFF_WITH_pep
+#define coff_swap_filehdr_out _bfd_pep_only_swap_filehdr_out
+#else
 # define coff_swap_filehdr_out _bfd_pe_only_swap_filehdr_out
 #endif
+#endif
+#endif
 
 static void
 coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
@@ -363,7 +371,6 @@
 #define coff_get_symbol_info _bfd_XX_get_symbol_info
 
 #ifdef COFF_IMAGE_WITH_PE
-\f
 /* Code to handle Microsoft's Image Library Format.
    Also known as LINK6 format.
    Documentation about this format can be found at:
@@ -405,8 +412,13 @@
 					+ NUM_ILF_SECTIONS * 9 \
 					+ STRING_SIZE_SIZE)
 #define SIZEOF_IDATA2		(5 * 4)
+#ifndef COFF_WITH_pex64
 #define SIZEOF_IDATA4		(1 * 4)
 #define SIZEOF_IDATA5		(1 * 4)
+#else
+#define SIZEOF_IDATA4		(2 * 4)
+#define SIZEOF_IDATA5		(2 * 4)
+#endif
 #define SIZEOF_IDATA6		(2 + strlen (symbol_name) + 1 + 1)
 #define SIZEOF_IDATA7		(strlen (source_dll) + 1 + 1)
 #define SIZEOF_ILF_SECTIONS     (NUM_ILF_SECTIONS * sizeof (struct coff_section_tdata))
@@ -655,6 +667,12 @@
     8, 2
   },
 #endif
+#ifdef AMD64MAGIC
+  { AMD64MAGIC,
+  { 0xff,0x25,0x00,0x00,0x00,0x00,0x90,0x90 },
+  8,2
+  },
+#endif
 
 #ifdef  MC68MAGIC
   { MC68MAGIC, { /* XXX fill me in */ }, 0, 0 },
@@ -830,8 +848,15 @@
 	/* XXX - treat as IMPORT_NAME ??? */
 	abort ();
 
+#ifndef COFF_WITH_pex64
       * (unsigned int *) id4->contents = ordinal | 0x80000000;
       * (unsigned int *) id5->contents = ordinal | 0x80000000;
+#else
+      * (unsigned int *) id4->contents = ordinal;
+	  ((unsigned int *) id4->contents)[1] = 0x80000000;
+      * (unsigned int *) id5->contents = ordinal;
+      ((unsigned int *) id5->contents)[1] = 0x80000000;
+#endif
     }
   else
     {
@@ -1070,7 +1095,11 @@
       magic = I386MAGIC;
 #endif
       break;
-
+	case IMAGE_FILE_MACHINE_AMD64:
+#ifdef AMD64MAGIC
+		magic=AMD64MAGIC;
+#endif
+		break;
     case IMAGE_FILE_MACHINE_M68K:
 #ifdef MC68AGIC
       magic = MC68MAGIC;
@@ -1255,7 +1284,6 @@
       bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
-
   /* Here is the hack.  coff_object_p wants to read filhsz bytes to
      pick up the COFF header for PE, see "struct external_PEI_filehdr"
      in include/coff/pe.h.  We adjust so that that will work. */
@@ -1265,7 +1293,6 @@
 	bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
-
   return coff_object_p (abfd);
 }
 
diff -rNbu binutils-2.17_org/bfd/targets.c binutils-2.17/bfd/targets.c
--- binutils-2.17_org/bfd/targets.c	2006-04-05 14:41:57.000000000 +0200
+++ binutils-2.17/bfd/targets.c	2006-08-04 11:57:01.000000000 +0200
@@ -782,6 +782,9 @@
 extern const bfd_target we32kcoff_vec;
 extern const bfd_target z80coff_vec;
 extern const bfd_target z8kcoff_vec;
+extern const bfd_target x86_64pe_vec;
+extern const bfd_target x86_64pei_vec;
+extern const bfd_target x86_64coff_vec;
 
 /* These are always included.  */
 extern const bfd_target srec_vec;
@@ -1019,6 +1022,11 @@
 #if 0
 	&i386dynix_vec,
 #endif
+#ifdef BFD64
+	&x86_64coff_vec,
+	&x86_64pe_vec,
+	&x86_64pei_vec,
+#endif
 	&i386freebsd_vec,
 #if 0
 	/* Since a.out files lack decent magic numbers, no way to recognize
diff -rNbu binutils-2.17_org/binutils/configure binutils-2.17/binutils/configure
--- binutils-2.17_org/binutils/configure	2006-04-06 23:49:29.000000000 +0200
+++ binutils-2.17/binutils/configure	2006-08-08 15:57:53.000000000 +0200
@@ -10722,6 +10722,12 @@
 	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
 	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
 	  ;;
+	x86_64-*-mingw64*)
+  	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MX86_64"
+	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+	  ;;
 	i[3-7]86-*-interix)
 	  BUILD_DLLTOOL='$(DLLTOOL_PROG)'
 	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386"
diff -rNbu binutils-2.17_org/binutils/configure.in binutils-2.17/binutils/configure.in
--- binutils-2.17_org/binutils/configure.in	2006-04-06 23:49:29.000000000 +0200
+++ binutils-2.17/binutils/configure.in	2006-08-08 15:56:56.000000000 +0200
@@ -260,6 +260,14 @@
 	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
 	  ;;
 changequote(,)dnl
+	x86_64-*-mingw64*)
+changequote([,])dnl
+  	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MX86_64"
+	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+	  ;;
+changequote(,)dnl
 	i[3-7]86-*-interix)
 changequote([,])dnl
 	  BUILD_DLLTOOL='$(DLLTOOL_PROG)'
diff -rNbu binutils-2.17_org/binutils/dlltool.c binutils-2.17/binutils/dlltool.c
--- binutils-2.17_org/binutils/dlltool.c	2006-03-09 22:50:53.000000000 +0100
+++ binutils-2.17/binutils/dlltool.c	2006-08-17 09:09:15.000000000 +0200
@@ -261,6 +261,9 @@
 #include "coff/arm.h"
 #include "coff/internal.h"
 #endif
+#ifdef DLLTOOL_MX86_64
+#include "coff/x86_64.h"
+#endif
 
 /* Forward references.  */
 static char *look_for_prog (const char *, const char *, int);
@@ -396,6 +399,10 @@
 static const char *mname = "i386";
 #endif
 
+#ifdef DLLTOOL_MX86_64
+static const char *mname = "i386:x86-64";
+#endif
+
 #ifdef DLLTOOL_PPC
 static const char *mname = "ppc";
 #endif
@@ -629,6 +636,14 @@
     arm_jtab, sizeof (arm_jtab), 8
   }
   ,
+  {
+#define MX86 10
+    "i386:x86-64", ".byte", ".short", ".long", ".asciz", "#",
+    "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
+    "pe-x86-64",bfd_arch_i386,
+    i386_jtab, sizeof (i386_jtab), 2
+  }
+  ,
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 };
 
@@ -752,6 +767,7 @@
     {
     case MARM:
     case M386:
+	case MX86:
     case MPPC:
     case MTHUMB:
     case MARM_INTERWORK:
@@ -776,6 +792,7 @@
     {
     case MARM:
     case M386:
+	case MX86:
     case MPPC:
     case MTHUMB:
     case MARM_INTERWORK:
@@ -809,6 +826,7 @@
     case MARM_EPOC:
       break;
     case M386:
+	case MX86:
       /* Symbol names starting with ? do not have a leading underscore. */
       if (name && *name == '?')
         break;
diff -rNbu binutils-2.17_org/config.guess binutils-2.17/config.guess
--- binutils-2.17_org/config.guess	2006-01-16 18:34:37.000000000 +0100
+++ binutils-2.17/config.guess	2006-07-26 15:22:53.000000000 +0200
@@ -777,6 +777,9 @@
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
 	exit ;;
+    i*:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
     i*:MINGW*:*)
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
diff -rNbu binutils-2.17_org/config.sub binutils-2.17/config.sub
--- binutils-2.17_org/config.sub	2006-01-16 18:34:37.000000000 +0100
+++ binutils-2.17/config.sub	2006-07-26 15:25:35.000000000 +0200
@@ -683,6 +683,10 @@
 		basic_machine=i386-pc
 		os=-mingw32
 		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
 	miniframe)
 		basic_machine=m68000-convergent
 		;;
@@ -1207,7 +1211,7 @@
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 	      | -chorusos* | -chorusrdb* \
 	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
 	      | -uxpv* | -beos* | -mpeix* | -udk* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
diff -rNbu binutils-2.17_org/configure binutils-2.17/configure
--- binutils-2.17_org/configure	2006-04-06 23:49:25.000000000 +0200
+++ binutils-2.17/configure	2006-07-26 15:29:08.000000000 +0200
@@ -1771,6 +1771,8 @@
     ;;
   *-mingw32*)
     ;;
+  *-mingw64*)
+    ;;
   *-interix*)
     host_makefile_frag="config/mh-interix"
     ;;
diff -rNbu binutils-2.17_org/gas/config/obj-coff.h binutils-2.17/gas/config/obj-coff.h
--- binutils-2.17_org/gas/config/obj-coff.h	2006-08-03 15:18:32.000000000 +0200
+++ binutils-2.17/gas/config/obj-coff.h	2006-08-04 09:42:45.000000000 +0200
@@ -57,24 +57,28 @@
 #endif
 
 #ifdef TC_I386
-#ifdef TE_PEP
-#include "coff/x86_64.h"
-#else
+#ifndef TE_PEP
 #include "coff/i386.h"
+#else
+#include "coff/x86_64.h"
 #endif
 
 #ifdef TE_PE
-#ifndef TE_PEP
-#define TARGET_FORMAT "pe-i386"
+#ifdef TE_PEP
+#define TARGET_FORMAT "coff-x86-64"
 #else
-#define TARGET_FORMAT "pe-x86-64"
+#define TARGET_FORMAT "pe-i386"
 #endif
 #endif
 
 #ifndef TARGET_FORMAT
+#ifdef TE_PEP
+#define TARGET_FORMAT "coff-x86-64"
+#else
 #define TARGET_FORMAT "coff-i386"
 #endif
 #endif
+#endif
 
 #ifdef TC_M68K
 #include "coff/m68k.h"
diff -rNbu binutils-2.17_org/gas/config/tc-i386.c binutils-2.17/gas/config/tc-i386.c
--- binutils-2.17_org/gas/config/tc-i386.c	2006-04-07 08:40:57.000000000 +0200
+++ binutils-2.17/gas/config/tc-i386.c	2006-08-14 10:32:38.000000000 +0200
@@ -5469,7 +5469,8 @@
 
 	list = bfd_target_list ();
 	for (l = list; *l != NULL; l++)
-	  if (strcmp (*l, "elf64-x86-64") == 0)
+	  if (strcmp (*l, "elf64-x86-64") == 0 || strcmp(*l,"coff-x86-64")==0 || strcmp(*l,"pe-x86-64")==0 ||
+		  strcmp(*l,"pei-x86-64")==0)
 	    {
 	      default_arch = "x86_64";
 	      break;
diff -rNbu binutils-2.17_org/gas/config/te-pep.h binutils-2.17/gas/config/te-pep.h
--- binutils-2.17_org/gas/config/te-pep.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/gas/config/te-pep.h	2006-08-17 09:11:31.000000000 +0200
@@ -0,0 +1,6 @@
+#define TE_PEP
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+
+#include "te-pe.h"
diff -rNbu binutils-2.17_org/gas/configure binutils-2.17/gas/configure
--- binutils-2.17_org/gas/configure	2006-04-06 23:49:31.000000000 +0200
+++ binutils-2.17/gas/configure	2006-07-20 16:12:04.000000000 +0200
@@ -3922,7 +3922,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -3936,6 +3936,9 @@
         x86_64-*linux*)
           LD="${LD-ld} -m elf_i386"
           ;;
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_i386"
+          ;;
         ppc64-*linux*|powerpc64-*linux*)
           LD="${LD-ld} -m elf32ppclinux"
           ;;
@@ -3952,6 +3955,9 @@
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         ppc*-*linux*|powerpc*-*linux*)
           LD="${LD-ld} -m elf64ppc"
           ;;
diff -rNbu binutils-2.17_org/gas/configure.in binutils-2.17/gas/configure.in
--- binutils-2.17_org/gas/configure.in	2006-04-06 23:49:33.000000000 +0200
+++ binutils-2.17/gas/configure.in	2006-07-20 15:17:11.000000000 +0200
@@ -417,6 +417,19 @@
       ;;
     esac
   ;;
+  x86_64)
+    case ${obj_format} in
+    aout)
+      emulations="$emulations i386coff i386elf"
+      ;;
+    coff)
+      emulations="$emulations i386aout i386elf"
+    ;;
+    elf)
+      emulations="$emulations i386aout i386coff"
+      ;;
+    esac
+  ;;
   esac
 fi
 
diff -rNbu binutils-2.17_org/gas/configure.tgt binutils-2.17/gas/configure.tgt
--- binutils-2.17_org/gas/configure.tgt	2006-04-05 14:41:57.000000000 +0200
+++ binutils-2.17/gas/configure.tgt	2006-08-03 14:15:58.000000000 +0200
@@ -77,7 +77,7 @@
   strongarm*b)		cpu_type=arm endian=big ;;
   strongarm*)		cpu_type=arm endian=little ;;
   v850*)		cpu_type=v850 ;;
-  x86_64)		cpu_type=i386 arch=x86_64;;
+  x86_64*)		cpu_type=i386 arch=x86_64;;
   xscale*be|xscale*b)	cpu_type=arm endian=big ;;
   xscale*)		cpu_type=arm endian=little ;;
   xtensa*)		cpu_type=xtensa arch=xtensa ;;
@@ -87,6 +87,8 @@
 
 # Assign object format.  Set fmt, em, and bfd_gas.
 generic_target=${cpu_type}-$vendor-$os
+echo "$$$$: info: GAS want support target CPU ${generic_target}" >&2;
+
 # Note: This table is alpha-sorted, please try to keep it that way.
 case ${generic_target} in
   alpha-*-*vms*)			fmt=evax ;;
@@ -210,6 +212,7 @@
   i386-*-cygwin*)			fmt=coff em=pe ;;
   i386-*-interix*)			fmt=coff em=interix ;;
   i386-*-mingw32*)			fmt=coff em=pe ;;
+  i386-*-mingw64*)			fmt=coff em=pep ;;
   i386-*-nto-qnx*)			fmt=elf ;;
   i386-*-*nt*)				fmt=coff em=pe ;;
   i386-*-chaos)				fmt=elf ;;
diff -rNbu binutils-2.17_org/include/coff/external.h binutils-2.17/include/coff/external.h
--- binutils-2.17_org/include/coff/external.h	2005-05-10 12:21:09.000000000 +0200
+++ binutils-2.17/include/coff/external.h	2006-08-07 13:08:59.000000000 +0200
@@ -55,6 +55,20 @@
 
 #define AOUTHDRSZ 28
 #define AOUTSZ 28
+
+typedef struct external_aouthdr64
+  {
+    char magic[2];	/* type of file				*/
+    char vstamp[2];	/* version stamp			*/
+    char tsize[4];	/* text size in bytes, padded to FW bdry*/
+    char dsize[4];	/* initialized data "  "		*/
+    char bsize[4];	/* uninitialized data "   "		*/
+    char entry[4];	/* entry pt.				*/
+    char text_start[4];	/* base of text used for this file 	*/
+  }
+AOUTHDR64;
+#define AOUTHDRSZ64	24
+
 #endif
 
 #ifndef DO_NOT_DEFINE_SCNHDR
diff -rNbu binutils-2.17_org/include/coff/internal.h binutils-2.17/include/coff/internal.h
--- binutils-2.17_org/include/coff/internal.h	2006-02-05 12:57:34.000000000 +0100
+++ binutils-2.17/include/coff/internal.h	2006-08-07 12:36:01.000000000 +0200
@@ -604,6 +604,22 @@
   unsigned long r_offset;	/* Used by Alpha ECOFF, SPARC, others */
 };
 
+/* X86-64 relocations */
+#define R_AMD64_ABS 0 /* Reference is absolute, no relocation is necessary */
+#define R_AMD64_DIR64	1 /* 64-bit address (VA) */
+#define R_AMD64_DIR32	2 /* 32-bit address (VA) R_DIR32 */
+#define R_AMD64_IMAGEBASE	 3 /* 32-bit absolute ref w/o base R_IMAGEBASE */
+#define R_AMD64_PCRLONG		 4 /* 32-bit relative address from byte following reloc R_PCRLONG */
+#define R_AMD64_PCRLONG_1		 5 /* 32-bit relative address from byte distance 1 from reloc */
+#define R_AMD64_PCRLONG_2		 6 /* 32-bit relative address from byte distance 2 from reloc */
+#define R_AMD64_PCRLONG_3		 7 /* 32-bit relative address from byte distance 3 from reloc */
+#define R_AMD64_PCRLONG_4		 8 /* 32-bit relative address from byte distance 4 from reloc */
+#define R_AMD64_PCRLONG_5		 9 /* 32-bit relative address from byte distance 5 from reloc */
+#define R_AMD64_SECTION	10 /* Section index */
+#define R_AMD64_SECREL	11 /* 32 bit offset from base of section containing target R_SECREL*/
+#define R_AMD64_SECREL7	12 /* 7 bit unsigned offset from base of section containing target */
+#define R_AMD64_TOKEN	13 /* 32 bit metadata token */
+
 #define R_DIR16 	 1
 #define R_REL24          5
 #define R_DIR32 	 6
diff -rNbu binutils-2.17_org/include/coff/pe.h binutils-2.17/include/coff/pe.h
--- binutils-2.17_org/include/coff/pe.h	2005-05-10 12:21:09.000000000 +0200
+++ binutils-2.17/include/coff/pe.h	2006-08-07 13:08:12.000000000 +0200
@@ -119,6 +119,7 @@
 #define IMAGE_FILE_MACHINE_THUMB             0x01c2
 #define IMAGE_FILE_MACHINE_TRICORE           0x0520
 #define IMAGE_FILE_MACHINE_WCEMIPSV2         0x0169
+#define IMAGE_FILE_MACHINE_AMD64             0x8664  // AMD64 (K8)
 
 #define IMAGE_SUBSYSTEM_UNKNOWN			 0
 #define IMAGE_SUBSYSTEM_NATIVE			 1
@@ -233,7 +234,6 @@
 typedef struct 
 {
   AOUTHDR standard;
-
   /* NT extra fields; see internal.h for descriptions.  */
   char  ImageBase[4];
   char  SectionAlignment[4];
@@ -267,7 +267,7 @@
    of just 4 bytes long.  */
 typedef struct 
 {
-  AOUTHDR standard;
+  AOUTHDR64 standard;
 
   /* NT extra fields; see internal.h for descriptions.  */
   char  ImageBase[8];
@@ -294,7 +294,7 @@
   /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];  */
   char  DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars.  */
 } PEPAOUTHDR;
-#define PEPAOUTSZ	240
+#define PEPAOUTSZ	(AOUTHDRSZ64+196+5*4) /* 240 */
   
 #undef  E_FILNMLEN
 #define E_FILNMLEN	18	/* # characters in a file name.  */
diff -rNbu binutils-2.17_org/include/coff/x86_64.h binutils-2.17/include/coff/x86_64.h
--- binutils-2.17_org/include/coff/x86_64.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/include/coff/x86_64.h	2006-08-17 09:12:23.000000000 +0200
@@ -0,0 +1,67 @@
+/* coff information for AMD 64.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#define L_LNNO_SIZE 2
+#define INCLUDE_COMDAT_FIELDS_IN_AUXENT
+#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
+ 	F_AR32WR	file has byte ordering of an AR32WR machine (e.g. vax).  */
+
+#define F_RELFLG	(0x0001)
+#define F_EXEC		(0x0002)
+#define F_LNNO		(0x0004)
+#define F_LSYMS		(0x0008)
+
+#define AMD64MAGIC	0x8664
+
+#define AMD64BADMAG(x)	( (x).f_magic != AMD64MAGIC)
+#define IMAGE_NT_OPTIONAL_HDR64_MAGIC      0x20b
+
+#define OMAGIC          0404    /* object files, eg as output */
+#define ZMAGIC          IMAGE_NT_OPTIONAL_HDR64_MAGIC    /* demand load format, eg normal ld output 0x10b */
+#define STMAGIC		0401	/* target shlib */
+#define SHMAGIC		0443	/* host   shlib */
+
+/* define some NT default values */
+/*  #define NT_IMAGE_BASE        0x400000 moved to internal.h */
+#define NT_SECTION_ALIGNMENT 0x1000
+#define NT_FILE_ALIGNMENT    0x200
+#define NT_DEF_RESERVE       0x100000
+#define NT_DEF_COMMIT        0x1000
+
+/********************** 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 -rNbu binutils-2.17_org/ld/Makefile.am binutils-2.17/ld/Makefile.am
--- binutils-2.17_org/ld/Makefile.am	2006-06-03 06:45:50.000000000 +0200
+++ binutils-2.17/ld/Makefile.am	2006-08-02 10:30:06.000000000 +0200
@@ -240,6 +240,7 @@
 	ei386nto.o \
 	ei386nw.o \
 	ei386pe.o \
+	ei386pep.o \
 	ei386pe_posix.o \
 	elnk960.o \
 	em32relf.o \
@@ -410,15 +411,16 @@
 
 ALL_EMUL_EXTRA_OFILES = \
 	deffilep.o \
-	pe-dll.o
+	pe-dll.o \
+	pep-dll.o
 
 CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \
 	ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \
-	mri.c ldcref.c pe-dll.c
+	mri.c ldcref.c pe-dll.c pep-dll.c
 
 HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
 	ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
-	ldwrite.h mri.h deffile.h pe-dll.h elf-hints-local.h
+	ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h elf-hints-local.h
 
 GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
 GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
@@ -1069,6 +1071,9 @@
 ei386pe.c: $(srcdir)/emulparams/i386pe.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe "$(tdir_i386pe)"
+ei386pep.c: $(srcdir)/emulparams/i386pep.sh \
+  $(srcdir)/emultempl/pep.em $(srcdir)/scripttempl/pep.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} i386pep "$(tdir_i386pe)"
 ei386pe_posix.c: $(srcdir)/emulparams/i386pe_posix.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe_posix "$(tdir_i386pe_posix)"
@@ -1937,6 +1942,12 @@
   ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
   ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
   $(BFDDIR)/libcoff.h deffile.h pe-dll.h
+pep-dll.o: pep-dll.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h $(INCDIR)/safe-ctype.h \
+  ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
+  ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
+  $(BFDDIR)/libcoff.h deffile.h pep-dll.h
 ldgram.o: ldgram.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
   $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
   $(INCDIR)/bfdlink.h ld.h $(INCDIR)/bin-bugs.h ldexp.h \
diff -rNbu binutils-2.17_org/ld/Makefile.in binutils-2.17/ld/Makefile.in
--- binutils-2.17_org/ld/Makefile.in	2006-06-03 06:45:50.000000000 +0200
+++ binutils-2.17/ld/Makefile.in	2006-08-02 10:31:07.000000000 +0200
@@ -464,6 +464,7 @@
 	ei386nto.o \
 	ei386nw.o \
 	ei386pe.o \
+	ei386pep.o \
 	ei386pe_posix.o \
 	elnk960.o \
 	em32relf.o \
@@ -634,15 +635,16 @@
 
 ALL_EMUL_EXTRA_OFILES = \
 	deffilep.o \
-	pe-dll.o
+	pe-dll.o \
+	pep-dll.o
 
 CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \
 	ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \
-	mri.c ldcref.c pe-dll.c
+	mri.c ldcref.c pe-dll.c pep-dll.c
 
 HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
 	ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
-	ldwrite.h mri.h deffile.h pe-dll.h elf-hints-local.h
+	ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h elf-hints-local.h
 
 GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
 GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
@@ -1880,6 +1882,9 @@
 ei386pe.c: $(srcdir)/emulparams/i386pe.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe "$(tdir_i386pe)"
+ei386pep.c: $(srcdir)/emulparams/i386pep.sh \
+  $(srcdir)/emultempl/pep.em $(srcdir)/scripttempl/pep.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} i386pep "$(tdir_i386pe)"
 ei386pe_posix.c: $(srcdir)/emulparams/i386pe_posix.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe_posix "$(tdir_i386pe_posix)"
@@ -2718,6 +2723,12 @@
   ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
   ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
   $(BFDDIR)/libcoff.h deffile.h pe-dll.h
+pep-dll.o: pep-dll.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h $(INCDIR)/safe-ctype.h \
+  ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
+  ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
+  $(BFDDIR)/libcoff.h deffile.h pep-dll.h
 ldgram.o: ldgram.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
   $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
   $(INCDIR)/bfdlink.h ld.h $(INCDIR)/bin-bugs.h ldexp.h \
diff -rNbu binutils-2.17_org/ld/configure binutils-2.17/ld/configure
--- binutils-2.17_org/ld/configure	2006-04-11 12:36:26.000000000 +0200
+++ binutils-2.17/ld/configure	2006-07-27 10:58:43.000000000 +0200
@@ -3924,7 +3924,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -3951,6 +3951,9 @@
       ;;
     *64-bit*)
       case $host in
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
diff -rNbu binutils-2.17_org/ld/configure.tgt binutils-2.17/ld/configure.tgt
--- binutils-2.17_org/ld/configure.tgt	2006-04-05 14:41:57.000000000 +0200
+++ binutils-2.17/ld/configure.tgt	2006-08-02 10:27:25.000000000 +0200
@@ -155,6 +155,8 @@
 			  targ_extra_emuls="$targ_extra_emuls elf_x86_64"
 			fi
 			tdir_i386linux=${targ_alias}aout ;;
+x86_64-*-mingw64*) targ_emul=i386pep ;
+			targ_extra_ofiles="deffilep.o pep-dll.o" ;;
 x86_64-*-linux-*)	targ_emul=elf_x86_64
 			targ_extra_emuls="elf_i386 i386linux"
 			targ_extra_libpath=elf_i386
diff -rNbu binutils-2.17_org/ld/emulparams/i386pep.sh binutils-2.17/ld/emulparams/i386pep.sh
--- binutils-2.17_org/ld/emulparams/i386pep.sh	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/ld/emulparams/i386pep.sh	2006-07-28 12:43:22.000000000 +0200
@@ -0,0 +1,9 @@
+ARCH="i386:x86-64"
+SCRIPT_NAME=pep
+OUTPUT_FORMAT="pei-x86-64"
+RELOCATEABLE_OUTPUT_FORMAT="pe-x86-64"
+TEMPLATE_NAME=pep
+ENTRY="_mainCRTStartup"
+SUBSYSTEM=PE_DEF_SUBSYSTEM
+INITIAL_SYMBOL_CHAR=\"_\"
+TARGET_PAGE_SIZE=0x1000
diff -rNbu binutils-2.17_org/ld/emultempl/pep.em binutils-2.17/ld/emultempl/pep.em
--- binutils-2.17_org/ld/emultempl/pep.em	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/ld/emultempl/pep.em	2006-08-17 09:16:43.000000000 +0200
@@ -0,0 +1,1748 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+test -z "${ENTRY}" && ENTRY="_mainCRTStartup"
+if [ -z "$MACHINE" ]; then
+  OUTPUT_ARCH=${ARCH}
+else
+  OUTPUT_ARCH=${ARCH}:${MACHINE}
+fi
+rm -f e${EMULATION_NAME}.c
+(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
+cat >>e${EMULATION_NAME}.c <<EOF
+/* This file is part of GLD, the Gnu Linker.
+   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+   */
+
+/* For WINDOWS_XP64 and higher */
+/* The original file generated returned different default scripts depending
+   on whether certain switches were set, but these switches pertain to the
+   Linux system and that particular version of coff.  In the NT case, we
+   only determine if the subsystem is console or windows in order to select
+   the correct entry point by default. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "getopt.h"
+#include "libiberty.h"
+#include "ld.h"
+#include "ldmain.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+#include <ldgram.h>
+#include "ldlex.h"
+#include "ldmisc.h"
+#include "ldctor.h"
+#include "coff/internal.h"
+
+/* FIXME: See bfd/peXXigen.c for why we include an architecture specific
+   header in generic PE code.  */
+#include "coff/x86_64.h"
+#include "coff/pe.h"
+
+/* FIXME: This is a BFD internal header file, and we should not be
+   using it here.  */
+#include "../bfd/libcoff.h"
+
+#undef AOUTSZ
+#define AOUTSZ		PEPAOUTSZ
+#define PEAOUTHDR	PEPAOUTHDR
+
+#include "deffile.h"
+#include "pep-dll.h"
+#include "safe-ctype.h"
+
+/* Permit the emulation parameters to override the default section
+   alignment by setting OVERRIDE_SECTION_ALIGNMENT.  FIXME: This makes
+   it seem that include/coff/internal.h should not define
+   PE_DEF_SECTION_ALIGNMENT.  */
+#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT}
+#undef PE_DEF_SECTION_ALIGNMENT
+#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT}
+#endif
+
+#ifdef TARGET_IS_i386pep
+#define DLL_SUPPORT
+#endif
+
+#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT)
+#define	PE_DEF_SUBSYSTEM		3
+#else
+#undef NT_EXE_IMAGE_BASE
+#undef PE_DEF_SECTION_ALIGNMENT
+#undef PE_DEF_FILE_ALIGNMENT
+#define NT_EXE_IMAGE_BASE		0x00010000
+#define PE_DEF_SECTION_ALIGNMENT	0x00000400
+#define	PE_DEF_SUBSYSTEM		2
+#define PE_DEF_FILE_ALIGNMENT		0x00000200
+#endif
+
+
+static struct internal_extra_pe_aouthdr pep;
+static int dll;
+static flagword real_flags = IMAGE_FILE_LARGE_ADDRESS_AWARE;
+static int support_old_code = 0;
+static char * thumb_entry_symbol = NULL;
+static lang_assignment_statement_type *image_base_statement = 0;
+
+#ifdef DLL_SUPPORT
+static int pep_enable_stdcall_fixup = -1; /* 0=disable 1=enable.  */
+static char *pep_out_def_filename = NULL;
+static char *pep_implib_filename = NULL;
+static int pep_enable_auto_image_base = 0;
+static char *pep_dll_search_prefix = NULL;
+#endif
+
+extern const char *output_filename;
+
+static void
+gld_${EMULATION_NAME}_before_parse (void)
+{
+  ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
+  output_filename = "${EXECUTABLE_NAME:-a.exe}";
+#ifdef DLL_SUPPORT
+  config.dynamic_link = TRUE;
+  config.has_shared = 1;
+  link_info.pei386_auto_import = -1;
+  link_info.pei386_runtime_pseudo_reloc = -1;
+
+#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
+#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
+  lang_default_entry ("WinMainCRTStartup");
+#else
+  lang_default_entry ("_WinMainCRTStartup");
+#endif
+#else
+  lang_default_entry ("${ENTRY}");
+#endif
+#endif
+}
+\f
+/* PE format extra command line options.  */
+
+/* Used for setting flags in the PE header.  */
+#define OPTION_BASE_FILE		(300  + 1)
+#define OPTION_DLL			(OPTION_BASE_FILE + 1)
+#define OPTION_FILE_ALIGNMENT		(OPTION_DLL + 1)
+#define OPTION_IMAGE_BASE		(OPTION_FILE_ALIGNMENT + 1)
+#define OPTION_MAJOR_IMAGE_VERSION	(OPTION_IMAGE_BASE + 1)
+#define OPTION_MAJOR_OS_VERSION		(OPTION_MAJOR_IMAGE_VERSION + 1)
+#define OPTION_MAJOR_SUBSYSTEM_VERSION	(OPTION_MAJOR_OS_VERSION + 1)
+#define OPTION_MINOR_IMAGE_VERSION	(OPTION_MAJOR_SUBSYSTEM_VERSION + 1)
+#define OPTION_MINOR_OS_VERSION		(OPTION_MINOR_IMAGE_VERSION + 1)
+#define OPTION_MINOR_SUBSYSTEM_VERSION	(OPTION_MINOR_OS_VERSION + 1)
+#define OPTION_SECTION_ALIGNMENT	(OPTION_MINOR_SUBSYSTEM_VERSION + 1)
+#define OPTION_STACK			(OPTION_SECTION_ALIGNMENT + 1)
+#define OPTION_SUBSYSTEM		(OPTION_STACK + 1)
+#define OPTION_HEAP			(OPTION_SUBSYSTEM + 1)
+#define OPTION_SUPPORT_OLD_CODE		(OPTION_HEAP + 1)
+#define OPTION_OUT_DEF			(OPTION_SUPPORT_OLD_CODE + 1)
+#define OPTION_EXPORT_ALL		(OPTION_OUT_DEF + 1)
+#define OPTION_EXCLUDE_SYMBOLS		(OPTION_EXPORT_ALL + 1)
+#define OPTION_KILL_ATS			(OPTION_EXCLUDE_SYMBOLS + 1)
+#define OPTION_STDCALL_ALIASES		(OPTION_KILL_ATS + 1)
+#define OPTION_ENABLE_STDCALL_FIXUP	(OPTION_STDCALL_ALIASES + 1)
+#define OPTION_DISABLE_STDCALL_FIXUP	(OPTION_ENABLE_STDCALL_FIXUP + 1)
+#define OPTION_IMPLIB_FILENAME		(OPTION_DISABLE_STDCALL_FIXUP + 1)
+#define OPTION_THUMB_ENTRY		(OPTION_IMPLIB_FILENAME + 1)
+#define OPTION_WARN_DUPLICATE_EXPORTS	(OPTION_THUMB_ENTRY + 1)
+#define OPTION_IMP_COMPAT		(OPTION_WARN_DUPLICATE_EXPORTS + 1)
+#define OPTION_ENABLE_AUTO_IMAGE_BASE	(OPTION_IMP_COMPAT + 1)
+#define OPTION_DISABLE_AUTO_IMAGE_BASE	(OPTION_ENABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_DLL_SEARCH_PREFIX	(OPTION_DISABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_NO_DEFAULT_EXCLUDES	(OPTION_DLL_SEARCH_PREFIX + 1)
+#define OPTION_DLL_ENABLE_AUTO_IMPORT	(OPTION_NO_DEFAULT_EXCLUDES + 1)
+#define OPTION_DLL_DISABLE_AUTO_IMPORT	(OPTION_DLL_ENABLE_AUTO_IMPORT + 1)
+#define OPTION_ENABLE_EXTRA_PE_DEBUG	(OPTION_DLL_DISABLE_AUTO_IMPORT + 1)
+#define OPTION_EXCLUDE_LIBS		(OPTION_ENABLE_EXTRA_PE_DEBUG + 1)
+#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC	\
+					(OPTION_EXCLUDE_LIBS + 1)
+#define OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC	\
+					(OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC + 1)
+
+static void
+gld${EMULATION_NAME}_add_options
+  (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl,
+    struct option **longopts, int nrl ATTRIBUTE_UNUSED,
+    struct option **really_longopts ATTRIBUTE_UNUSED)
+{
+  static const struct option xtra_long[] = {
+    /* PE options */
+    {"base-file", required_argument, NULL, OPTION_BASE_FILE},
+    {"dll", no_argument, NULL, OPTION_DLL},
+    {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
+    {"heap", required_argument, NULL, OPTION_HEAP},
+    {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
+    {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
+    {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
+    {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},
+    {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION},
+    {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION},
+    {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION},
+    {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT},
+    {"stack", required_argument, NULL, OPTION_STACK},
+    {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
+    {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
+    {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
+#ifdef DLL_SUPPORT
+    /* getopt allows abbreviations, so we do this to stop it from treating -o
+       as an abbreviation for this option */
+    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
+    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
+    {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
+    {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
+    {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
+    {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
+    {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
+    {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
+    {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
+    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
+    {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
+    /* getopt() allows abbreviations, so we do this to stop it from
+       treating -c as an abbreviation for these --compat-implib.  */
+    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
+    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
+    {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE},
+    {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE},
+    {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX},
+    {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
+    {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT},
+    {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT},
+    {"enable-extra-pep-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG},
+    {"enable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC},
+    {"disable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC},
+#endif
+    {NULL, no_argument, NULL, 0}
+  };
+
+  *longopts = (struct option *)
+    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
+  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
+
+/* PE/WIN32; added routines to get the subsystem type, heap and/or stack
+   parameters which may be input from the command line.  */
+
+typedef struct
+{
+  void *ptr;
+  int size;
+  int value;
+  char *symbol;
+  int inited;
+} definfo;
+
+#define D(field,symbol,def)  {&pep.field,sizeof(pep.field), def, symbol,0}
+
+static definfo init[] =
+{
+  /* imagebase must be first */
+#define IMAGEBASEOFF 0
+  D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE),
+#define DLLOFF 1
+  {&dll, sizeof(dll), 0, "__dll__", 0},
+#define MSIMAGEBASEOFF	2
+  D(ImageBase,"__ImageBase", NT_EXE_IMAGE_BASE),
+  D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT),
+  D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT),
+  D(MajorOperatingSystemVersion,"__major_os_version__", 4),
+  D(MinorOperatingSystemVersion,"__minor_os_version__", 0),
+  D(MajorImageVersion,"__major_image_version__", 0),
+  D(MinorImageVersion,"__minor_image_version__", 0),
+  D(MajorSubsystemVersion,"__major_subsystem_version__", 5),
+  D(MinorSubsystemVersion,"__minor_subsystem_version__", 2),
+  D(Subsystem,"__subsystem__", ${SUBSYSTEM}),
+  D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000),
+  D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
+  D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
+  D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000),
+  D(LoaderFlags,"__loader_flags__", 0x0),
+  { NULL, 0, 0, NULL, 0 }
+};
+
+
+static void
+gld_${EMULATION_NAME}_list_options (FILE *file)
+{
+  fprintf (file, _("  --base_file <basefile>             Generate a base file for relocatable DLLs\n"));
+  fprintf (file, _("  --dll                              Set image base to the default for DLLs\n"));
+  fprintf (file, _("  --file-alignment <size>            Set file alignment\n"));
+  fprintf (file, _("  --heap <size>                      Set initial size of the heap\n"));
+  fprintf (file, _("  --image-base <address>             Set start address of the executable\n"));
+  fprintf (file, _("  --major-image-version <number>     Set version number of the executable\n"));
+  fprintf (file, _("  --major-os-version <number>        Set minimum required OS version\n"));
+  fprintf (file, _("  --major-subsystem-version <number> Set minimum required OS subsystem version\n"));
+  fprintf (file, _("  --minor-image-version <number>     Set revision number of the executable\n"));
+  fprintf (file, _("  --minor-os-version <number>        Set minimum required OS revision\n"));
+  fprintf (file, _("  --minor-subsystem-version <number> Set minimum required OS subsystem revision\n"));
+  fprintf (file, _("  --section-alignment <size>         Set section alignment\n"));
+  fprintf (file, _("  --stack <size>                     Set size of the initial stack\n"));
+  fprintf (file, _("  --subsystem <name>[:<version>]     Set required OS subsystem [& version]\n"));
+  fprintf (file, _("  --support-old-code                 Support interworking with old code\n"));
+  fprintf (file, _("  --thumb-entry=<symbol>             Set the entry point to be Thumb <symbol>\n"));
+#ifdef DLL_SUPPORT
+  fprintf (file, _("  --add-stdcall-alias                Export symbols with and without @nn\n"));
+  fprintf (file, _("  --disable-stdcall-fixup            Don't link _sym to _sym@nn\n"));
+  fprintf (file, _("  --enable-stdcall-fixup             Link _sym to _sym@nn without warnings\n"));
+  fprintf (file, _("  --exclude-symbols sym,sym,...      Exclude symbols from automatic export\n"));
+  fprintf (file, _("  --exclude-libs lib,lib,...         Exclude libraries from automatic export\n"));
+  fprintf (file, _("  --export-all-symbols               Automatically export all globals to DLL\n"));
+  fprintf (file, _("  --kill-at                          Remove @nn from exported symbols\n"));
+  fprintf (file, _("  --out-implib <file>                Generate import library\n"));
+  fprintf (file, _("  --output-def <file>                Generate a .DEF file for the built DLL\n"));
+  fprintf (file, _("  --warn-duplicate-exports           Warn about duplicate exports.\n"));
+  fprintf (file, _("  --compat-implib                    Create backward compatible import libs;\n\
+                                       create __imp_<SYMBOL> as well.\n"));
+  fprintf (file, _("  --enable-auto-image-base           Automatically choose image base for DLLs\n\
+                                       unless user specifies one\n"));
+  fprintf (file, _("  --disable-auto-image-base          Do not auto-choose image base. (default)\n"));
+  fprintf (file, _("  --dll-search-prefix=<string>       When linking dynamically to a dll without\n\
+                                       an importlib, use <string><basename>.dll\n\
+                                       in preference to lib<basename>.dll \n"));
+  fprintf (file, _("  --enable-auto-import               Do sophistcated linking of _sym to\n\
+                                       __imp_sym for DATA references\n"));
+  fprintf (file, _("  --disable-auto-import              Do not auto-import DATA items from DLLs\n"));
+  fprintf (file, _("  --enable-runtime-pseudo-reloc      Work around auto-import limitations by\n\
+                                       adding pseudo-relocations resolved at\n\
+                                       runtime.\n"));
+  fprintf (file, _("  --disable-runtime-pseudo-reloc     Do not add runtime pseudo-relocations for\n\
+                                       auto-imported DATA.\n"));
+  fprintf (file, _("  --enable-extra-pep-debug            Enable verbose debug output when building\n\
+                                       or linking to DLLs (esp. auto-import)\n"));
+#endif
+}
+
+
+static void
+set_pep_name (char *name, long val)
+{
+  int i;
+
+  /* Find the name and set it.  */
+  for (i = 0; init[i].ptr; i++)
+    {
+      if (strcmp (name, init[i].symbol) == 0)
+	{
+	  init[i].value = val;
+	  init[i].inited = 1;
+	  return;
+	}
+    }
+  abort ();
+}
+
+
+static void
+set_pep_subsystem (void)
+{
+  const char *sver;
+  const char *entry;
+  const char *initial_symbol_char;
+  char *end;
+  int len;
+  int i;
+  int subsystem;
+  unsigned long temp_subsystem;
+  static const struct
+    {
+      const char *name;
+      const int value;
+      const char *entry;
+    }
+  v[] =
+    {
+      { "native",  1, "NtProcessStartup" },
+      { "windows", 2, "WinMainCRTStartup" },
+      { "console", 3, "mainCRTStartup" },
+      { "posix",   7, "__PosixProcessStartup"},
+      { "wince",   9, "_WinMainCRTStartup" },
+      { "xbox",   14, "mainCRTStartup" },
+      { NULL, 0, NULL }
+    };
+  /* Entry point name for arbitrary subsystem numbers.  */
+  static const char default_entry[] = "mainCRTStartup";
+
+  /* Check for the presence of a version number.  */
+  sver = strchr (optarg, ':');
+  if (sver == NULL)
+    len = strlen (optarg);
+  else
+    {
+      len = sver - optarg;
+      set_pep_name ("__major_subsystem_version__",
+		   strtoul (sver + 1, &end, 0));
+      if (*end == '.')
+	set_pep_name ("__minor_subsystem_version__",
+		     strtoul (end + 1, &end, 0));
+      if (*end != '\0')
+	einfo (_("%P: warning: bad version number in -subsystem option\n"));
+    }
+
+  /* Check for numeric subsystem.  */
+  temp_subsystem = strtoul (optarg, & end, 0);
+  if ((*end == ':' || *end == '\0') && (temp_subsystem < 65536))
+    {
+      /* Search list for a numeric match to use its entry point.  */
+      for (i = 0; v[i].name; i++)
+	if (v[i].value == (int) temp_subsystem)
+	  break;
+
+      /* If no match, use the default.  */
+      if (v[i].name != NULL)
+	entry = v[i].entry;
+      else
+	entry = default_entry;
+
+      /* Use this subsystem.  */
+      subsystem = (int) temp_subsystem;
+    }
+  else
+    {
+      /* Search for subsystem by name.  */
+      for (i = 0; v[i].name; i++)
+	if (strncmp (optarg, v[i].name, len) == 0
+	    && v[i].name[len] == '\0')
+	  break;
+
+      if (v[i].name == NULL)
+	{
+	  einfo (_("%P%F: invalid subsystem type %s\n"), optarg);
+	  return;
+	}
+
+      entry = v[i].entry;
+      subsystem = v[i].value;
+    }
+
+  set_pep_name ("__subsystem__", subsystem);
+
+  initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
+  if (*initial_symbol_char != '\0')
+    {
+      char *alc_entry;
+
+      /* lang_default_entry expects its argument to be permanently
+	 allocated, so we don't free this string.  */
+      alc_entry = xmalloc (strlen (initial_symbol_char)
+			   + strlen (entry)
+			   + 1);
+      strcpy (alc_entry, initial_symbol_char);
+      strcat (alc_entry, entry);
+      entry = alc_entry;
+    }
+
+  lang_default_entry (entry);
+
+  return;
+}
+
+
+static void
+set_pep_value (char *name)
+{
+  char *end;
+
+  set_pep_name (name,  strtoul (optarg, &end, 0));
+
+  if (end == optarg)
+    einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg);
+
+  optarg = end;
+}
+
+
+static void
+set_pep_stack_heap (char *resname, char *comname)
+{
+  set_pep_value (resname);
+
+  if (*optarg == ',')
+    {
+      optarg++;
+      set_pep_value (comname);
+    }
+  else if (*optarg)
+    einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg);
+}
+
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+  switch (optc)
+    {
+    default:
+      return FALSE;
+
+    case OPTION_BASE_FILE:
+      link_info.base_file = fopen (optarg, FOPEN_WB);
+      if (link_info.base_file == NULL)
+	{
+	  /* xgettext:c-format */
+	  fprintf (stderr, _("%s: Can't open base file %s\n"),
+		   program_name, optarg);
+	  xexit (1);
+	}
+      break;
+
+      /* PE options.  */
+    case OPTION_HEAP:
+      set_pep_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__");
+      break;
+    case OPTION_STACK:
+      set_pep_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__");
+      break;
+    case OPTION_SUBSYSTEM:
+      set_pep_subsystem ();
+      break;
+    case OPTION_MAJOR_OS_VERSION:
+      set_pep_value ("__major_os_version__");
+      break;
+    case OPTION_MINOR_OS_VERSION:
+      set_pep_value ("__minor_os_version__");
+      break;
+    case OPTION_MAJOR_SUBSYSTEM_VERSION:
+      set_pep_value ("__major_subsystem_version__");
+      break;
+    case OPTION_MINOR_SUBSYSTEM_VERSION:
+      set_pep_value ("__minor_subsystem_version__");
+      break;
+    case OPTION_MAJOR_IMAGE_VERSION:
+      set_pep_value ("__major_image_version__");
+      break;
+    case OPTION_MINOR_IMAGE_VERSION:
+      set_pep_value ("__minor_image_version__");
+      break;
+    case OPTION_FILE_ALIGNMENT:
+      set_pep_value ("__file_alignment__");
+      break;
+    case OPTION_SECTION_ALIGNMENT:
+      set_pep_value ("__section_alignment__");
+      break;
+    case OPTION_DLL:
+      set_pep_name ("__dll__", 1);
+      break;
+    case OPTION_IMAGE_BASE:
+      set_pep_value ("__image_base__");
+      break;
+    case OPTION_SUPPORT_OLD_CODE:
+      support_old_code = 1;
+      break;
+    case OPTION_THUMB_ENTRY:
+      thumb_entry_symbol = optarg;
+      break;
+#ifdef DLL_SUPPORT
+    case OPTION_OUT_DEF:
+      pep_out_def_filename = xstrdup (optarg);
+      break;
+    case OPTION_EXPORT_ALL:
+      pep_dll_export_everything = 1;
+      break;
+    case OPTION_EXCLUDE_SYMBOLS:
+      pep_dll_add_excludes (optarg, 0);
+      break;
+    case OPTION_EXCLUDE_LIBS:
+      pep_dll_add_excludes (optarg, 1);
+      break;
+    case OPTION_KILL_ATS:
+      pep_dll_kill_ats = 1;
+      break;
+    case OPTION_STDCALL_ALIASES:
+      pep_dll_stdcall_aliases = 1;
+      break;
+    case OPTION_ENABLE_STDCALL_FIXUP:
+      pep_enable_stdcall_fixup = 1;
+      break;
+    case OPTION_DISABLE_STDCALL_FIXUP:
+      pep_enable_stdcall_fixup = 0;
+      break;
+    case OPTION_IMPLIB_FILENAME:
+      pep_implib_filename = xstrdup (optarg);
+      break;
+    case OPTION_WARN_DUPLICATE_EXPORTS:
+      pep_dll_warn_dup_exports = 1;
+      break;
+    case OPTION_IMP_COMPAT:
+      pep_dll_compat_implib = 1;
+      break;
+    case OPTION_ENABLE_AUTO_IMAGE_BASE:
+      pep_enable_auto_image_base = 1;
+      break;
+    case OPTION_DISABLE_AUTO_IMAGE_BASE:
+      pep_enable_auto_image_base = 0;
+      break;
+    case OPTION_DLL_SEARCH_PREFIX:
+      pep_dll_search_prefix = xstrdup (optarg);
+      break;
+    case OPTION_NO_DEFAULT_EXCLUDES:
+      pep_dll_do_default_excludes = 0;
+      break;
+    case OPTION_DLL_ENABLE_AUTO_IMPORT:
+      link_info.pei386_auto_import = 1;
+      break;
+    case OPTION_DLL_DISABLE_AUTO_IMPORT:
+      link_info.pei386_auto_import = 0;
+      break;
+    case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC:
+      link_info.pei386_runtime_pseudo_reloc = 1;
+      break;
+    case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC:
+      link_info.pei386_runtime_pseudo_reloc = 0;
+      break;
+    case OPTION_ENABLE_EXTRA_PE_DEBUG:
+      pep_dll_extra_pe_debug = 1;
+      break;
+#endif
+    }
+  return TRUE;
+}
+\f
+
+#ifdef DLL_SUPPORT
+static unsigned long
+strhash (const char *str)
+{
+  const unsigned char *s;
+  unsigned long hash;
+  unsigned int c;
+  unsigned int len;
+
+  hash = 0;
+  len = 0;
+  s = (const unsigned char *) str;
+  while ((c = *s++) != '\0')
+    {
+      hash += c + (c << 17);
+      hash ^= hash >> 2;
+      ++len;
+    }
+  hash += len + (len << 17);
+  hash ^= hash >> 2;
+
+  return hash;
+}
+
+/* Use the output file to create a image base for relocatable DLLs.  */
+
+static unsigned long
+compute_dll_image_base (const char *ofile)
+{
+  unsigned long hash = strhash (ofile);
+  return 0x61300000 + ((hash << 16) & 0x0FFC0000);
+}
+#endif
+
+/* Assign values to the special symbols before the linker script is
+   read.  */
+
+static void
+gld_${EMULATION_NAME}_set_symbols (void)
+{
+  /* Run through and invent symbols for all the
+     names and insert the defaults.  */
+  int j;
+  lang_statement_list_type *save;
+
+  if (!init[IMAGEBASEOFF].inited)
+    {
+      if (link_info.relocatable)
+	init[IMAGEBASEOFF].value = 0;
+      else if (init[DLLOFF].value || (link_info.shared && !link_info.pie))
+#ifdef DLL_SUPPORT
+	init[IMAGEBASEOFF].value = (pep_enable_auto_image_base) ?
+	  compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE;
+#else
+	init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE;
+#endif
+      else
+	init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE;
+	init[MSIMAGEBASEOFF].value=init[IMAGEBASEOFF].value;
+    }
+
+  /* Don't do any symbol assignments if this is a relocatable link.  */
+  if (link_info.relocatable)
+    return;
+
+  /* Glue the assignments into the abs section.  */
+  save = stat_ptr;
+
+  stat_ptr = &(abs_output_section->children);
+
+  for (j = 0; init[j].ptr; j++)
+    {
+      long val = init[j].value;
+      lang_assignment_statement_type *rv;
+      rv = lang_add_assignment (exp_assop ('=', init[j].symbol,
+					   exp_intop (val)));
+      if (init[j].size == sizeof (short))
+	*(short *) init[j].ptr = val;
+      else if (init[j].size == sizeof (int))
+	*(int *) init[j].ptr = val;
+      else if (init[j].size == sizeof (long))
+	*(long *) init[j].ptr = val;
+      /* This might be a long long or other special type.  */
+      else if (init[j].size == sizeof (bfd_vma))
+	*(bfd_vma *) init[j].ptr = val;
+      else	abort ();
+      if (j == IMAGEBASEOFF)
+	image_base_statement = rv;
+    }
+	/* Restore the pointer.  */
+  stat_ptr = save;
+
+  if (pep.FileAlignment >
+      pep.SectionAlignment)
+    {
+      einfo (_("%P: warning, file alignment > section alignment.\n"));
+    }
+}
+
+/* This is called after the linker script and the command line options
+   have been read.  */
+
+static void
+gld_${EMULATION_NAME}_after_parse (void)
+{
+  /* The Windows libraries are designed for the linker to treat the
+     entry point as an undefined symbol.  Otherwise, the .obj that
+     defines mainCRTStartup is brought in because it is the first
+     encountered in libc.lib and it has other symbols in it which will
+     be pulled in by the link process.  To avoid this, we act as
+     though the user specified -u with the entry point symbol.
+
+     This function is called after the linker script and command line
+     options have been read, so at this point we know the right entry
+     point.  This function is called before the input files are
+     opened, so registering the symbol as undefined will make a
+     difference.  */
+
+  if (! link_info.relocatable && entry_symbol.name != NULL)
+    ldlang_add_undef (entry_symbol.name);
+}
+
+/* pep-dll.c directly accesses pep_data_import_dll,
+   so it must be defined outside of #ifdef DLL_SUPPORT.
+   Note - this variable is deliberately not initialised.
+   This allows it to be treated as a common varaible, and only
+   exist in one incarnation in a multiple target enabled linker.  */
+char * pep_data_import_dll;
+
+#ifdef DLL_SUPPORT
+static struct bfd_link_hash_entry *pep_undef_found_sym;
+
+static bfd_boolean
+pep_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
+{
+  int sl;
+  char *string = inf;
+
+  sl = strlen (string);
+  if (h->type == bfd_link_hash_defined
+      && strncmp (h->root.string, string, sl) == 0
+      && h->root.string[sl] == '@')
+    {
+      pep_undef_found_sym = h;
+      return FALSE;
+    }
+  return TRUE;
+}
+
+static void
+pep_fixup_stdcalls (void)
+{
+  static int gave_warning_message = 0;
+  struct bfd_link_hash_entry *undef, *sym;
+
+  if (pep_dll_extra_pe_debug)
+    printf ("%s\n", __FUNCTION__);
+
+  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
+    if (undef->type == bfd_link_hash_undefined)
+      {
+	char* at = strchr (undef->root.string, '@');
+	int lead_at = (*undef->root.string == '@');
+	/* For now, don't try to fixup fastcall symbols.  */
+
+	if (at && !lead_at)
+	  {
+	    /* The symbol is a stdcall symbol, so let's look for a
+	       cdecl symbol with the same name and resolve to that.  */
+	    char *cname = xstrdup (undef->root.string /* + lead_at */);
+	    at = strchr (cname, '@');
+	    *at = 0;
+	    sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1);
+
+	    if (sym && sym->type == bfd_link_hash_defined)
+	      {
+		undef->type = bfd_link_hash_defined;
+		undef->u.def.value = sym->u.def.value;
+		undef->u.def.section = sym->u.def.section;
+
+		if (pep_enable_stdcall_fixup == -1)
+		  {
+		    einfo (_("Warning: resolving %s by linking to %s\n"),
+			   undef->root.string, cname);
+		    if (! gave_warning_message)
+		      {
+			gave_warning_message = 1;
+			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
+			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
+		      }
+		  }
+	      }
+	  }
+	else
+	  {
+	    /* The symbol is a cdecl symbol, so we look for stdcall
+	       symbols - which means scanning the whole symbol table.  */
+	    pep_undef_found_sym = 0;
+	    bfd_link_hash_traverse (link_info.hash, pep_undef_cdecl_match,
+				    (char *) undef->root.string);
+	    sym = pep_undef_found_sym;
+	    if (sym)
+	      {
+		undef->type = bfd_link_hash_defined;
+		undef->u.def.value = sym->u.def.value;
+		undef->u.def.section = sym->u.def.section;
+
+		if (pep_enable_stdcall_fixup == -1)
+		  {
+		    einfo (_("Warning: resolving %s by linking to %s\n"),
+			   undef->root.string, sym->root.string);
+		    if (! gave_warning_message)
+		      {
+			gave_warning_message = 1;
+			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
+			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
+		      }
+		  }
+	      }
+	  }
+      }
+}
+
+static int
+make_import_fixup (arelent *rel, asection *s)
+{
+  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
+  char addend[4];
+
+  if (pep_dll_extra_pe_debug)
+    printf ("arelent: %s@%#lx: add=%li\n", sym->name,
+	    (long) rel->address, (long) rel->addend);
+
+  if (! bfd_get_section_contents (s->owner, s, addend, rel->address, sizeof (addend)))
+    einfo (_("%C: Cannot get section contents - auto-import exception\n"),
+	   s->owner, s, rel->address);
+
+  pep_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend));
+
+  return 1;
+}
+
+static void
+pep_find_data_imports (void)
+{
+  struct bfd_link_hash_entry *undef, *sym;
+
+  if (link_info.pei386_auto_import == 0)
+    return;
+
+  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
+    {
+      if (undef->type == bfd_link_hash_undefined)
+	{
+	  /* C++ symbols are *long*.  */
+	  char buf[4096];
+
+	  if (pep_dll_extra_pe_debug)
+	    printf ("%s:%s\n", __FUNCTION__, undef->root.string);
+
+	  sprintf (buf, "__imp_%s", undef->root.string);
+
+	  sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
+
+	  if (sym && sym->type == bfd_link_hash_defined)
+	    {
+	      bfd *b = sym->u.def.section->owner;
+	      asymbol **symbols;
+	      int nsyms, symsize, i;
+
+	      if (link_info.pei386_auto_import == -1)
+		info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
+			  undef->root.string, buf);
+
+	      symsize = bfd_get_symtab_upper_bound (b);
+	      symbols = (asymbol **) xmalloc (symsize);
+	      nsyms = bfd_canonicalize_symtab (b, symbols);
+
+	      for (i = 0; i < nsyms; i++)
+		{
+		  if (memcmp (symbols[i]->name, "__head_",
+			      sizeof ("__head_") - 1))
+		    continue;
+
+		  if (pep_dll_extra_pe_debug)
+		    printf ("->%s\n", symbols[i]->name);
+
+		  pep_data_import_dll = (char*) (symbols[i]->name +
+						sizeof ("__head_") - 1);
+		  break;
+		}
+
+	      pep_walk_relocs_of_symbol (&link_info, undef->root.string,
+					make_import_fixup);
+
+	      /* Let's differentiate it somehow from defined.  */
+	      undef->type = bfd_link_hash_defweak;
+	      /* We replace original name with __imp_ prefixed, this
+		 1) may trash memory 2) leads to duplicate symbol generation.
+		 Still, IMHO it's better than having name poluted.  */
+	      undef->root.string = sym->root.string;
+	      undef->u.def.value = sym->u.def.value;
+	      undef->u.def.section = sym->u.def.section;
+	    }
+	}
+    }
+}
+
+static bfd_boolean
+pr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
+{
+  if (pep_dll_extra_pe_debug)
+    printf ("+%s\n", h->string);
+
+  return TRUE;
+}
+#endif /* DLL_SUPPORT */
+
+
+static void
+gld_${EMULATION_NAME}_after_open (void)
+{
+#ifdef DLL_SUPPORT
+  if (pep_dll_extra_pe_debug)
+    {
+      bfd *a;
+      struct bfd_link_hash_entry *sym;
+
+      printf ("%s()\n", __FUNCTION__);
+
+      for (sym = link_info.hash->undefs; sym; sym=sym->u.undef.next)
+	printf ("-%s\n", sym->root.string);
+      bfd_hash_traverse (&link_info.hash->table, pr_sym, NULL);
+
+      for (a = link_info.input_bfds; a; a = a->link_next)
+	printf ("*%s\n",a->filename);
+    }
+#endif
+
+  /* Pass the wacky PE command line options into the output bfd.
+     FIXME: This should be done via a function, rather than by
+     including an internal BFD header.  */
+
+  if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0)
+    einfo (_("%F%P: PE operations on non PE file.\n"));
+
+  pe_data (output_bfd)->pe_opthdr = pep;
+  pe_data (output_bfd)->dll = init[DLLOFF].value;
+  pe_data (output_bfd)->real_flags |= real_flags;
+
+#ifdef DLL_SUPPORT
+  if (pep_enable_stdcall_fixup) /* -1=warn or 1=disable */
+    pep_fixup_stdcalls ();
+
+  pep_process_import_defs (output_bfd, & link_info);
+
+  pep_find_data_imports ();
+
+#ifndef TARGET_IS_i386pep
+  if (link_info.shared)
+#else
+  if (!link_info.relocatable)
+#endif
+    pep_dll_build_sections (output_bfd, &link_info);
+
+#ifndef TARGET_IS_i386pep
+  else
+    pep_exe_build_sections (output_bfd, &link_info);
+#endif
+#endif
+
+  {
+    /* This next chunk of code tries to detect the case where you have
+       two import libraries for the same DLL (specifically,
+       symbolically linking libm.a and libc.a in cygwin to
+       libcygwin.a).  In those cases, it's possible for function
+       thunks from the second implib to be used but without the
+       head/tail objects, causing an improper import table.  We detect
+       those cases and rename the "other" import libraries to match
+       the one the head/tail come from, so that the linker will sort
+       things nicely and produce a valid import table.  */
+
+    LANG_FOR_EACH_INPUT_STATEMENT (is)
+      {
+	if (is->the_bfd->my_archive)
+	  {
+	    int idata2 = 0, reloc_count=0, is_imp = 0;
+	    asection *sec;
+
+	    /* See if this is an import library thunk.  */
+	    for (sec = is->the_bfd->sections; sec; sec = sec->next)
+	      {
+		if (strcmp (sec->name, ".idata\$2") == 0)
+		  idata2 = 1;
+		if (strncmp (sec->name, ".idata\$", 7) == 0)
+		  is_imp = 1;
+		reloc_count += sec->reloc_count;
+	      }
+
+	    if (is_imp && !idata2 && reloc_count)
+	      {
+		/* It is, look for the reference to head and see if it's
+		   from our own library.  */
+		for (sec = is->the_bfd->sections; sec; sec = sec->next)
+		  {
+		    int i;
+		    long symsize;
+		    long relsize;
+		    asymbol **symbols;
+		    arelent **relocs;
+		    int nrelocs;
+
+		    symsize = bfd_get_symtab_upper_bound (is->the_bfd);
+		    if (symsize < 1)
+		      break;
+		    relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
+		    if (relsize < 1)
+		      break;
+
+		    symbols = (asymbol **) xmalloc (symsize);
+		    symsize = bfd_canonicalize_symtab (is->the_bfd, symbols);
+		    if (symsize < 0)
+		      {
+			einfo ("%X%P: unable to process symbols: %E");
+			return;
+		      }
+
+		    relocs = (arelent **) xmalloc ((size_t) relsize);
+		    nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec,
+						      relocs, symbols);
+		    if (nrelocs < 0)
+		      {
+			free (relocs);
+			einfo ("%X%P: unable to process relocs: %E");
+			return;
+		      }
+
+		    for (i = 0; i < nrelocs; i++)
+		      {
+			struct bfd_symbol *s;
+			struct bfd_link_hash_entry * blhe;
+			char *other_bfd_filename;
+			char *n;
+
+			s = (relocs[i]->sym_ptr_ptr)[0];
+
+			if (s->flags & BSF_LOCAL)
+			  continue;
+
+			/* Thunk section with reloc to another bfd.  */
+			blhe = bfd_link_hash_lookup (link_info.hash,
+						     s->name,
+						     FALSE, FALSE, TRUE);
+
+			if (blhe == NULL
+			    || blhe->type != bfd_link_hash_defined)
+			  continue;
+
+			other_bfd_filename
+			  = blhe->u.def.section->owner->my_archive
+			    ? bfd_get_filename (blhe->u.def.section->owner->my_archive)
+			    : bfd_get_filename (blhe->u.def.section->owner);
+
+			if (strcmp (bfd_get_filename (is->the_bfd->my_archive),
+				    other_bfd_filename) == 0)
+			  continue;
+
+			/* Rename this implib to match the other one.  */
+			n = xmalloc (strlen (other_bfd_filename) + 1);
+			strcpy (n, other_bfd_filename);
+			is->the_bfd->my_archive->filename = n;
+		      }
+
+		    free (relocs);
+		    /* Note - we do not free the symbols,
+		       they are now cached in the BFD.  */
+		  }
+	      }
+	  }
+      }
+  }
+
+  {
+    int is_ms_arch = 0;
+    bfd *cur_arch = 0;
+    lang_input_statement_type *is2;
+    lang_input_statement_type *is3;
+
+    /* Careful - this is a shell script.  Watch those dollar signs! */
+    /* Microsoft import libraries have every member named the same,
+       and not in the right order for us to link them correctly.  We
+       must detect these and rename the members so that they'll link
+       correctly.  There are three types of objects: the head, the
+       thunks, and the sentinel(s).  The head is easy; it's the one
+       with idata2.  We assume that the sentinels won't have relocs,
+       and the thunks will.  It's easier than checking the symbol
+       table for external references.  */
+    LANG_FOR_EACH_INPUT_STATEMENT (is)
+      {
+	if (is->the_bfd->my_archive)
+	  {
+	    char *pnt;
+	    bfd *arch = is->the_bfd->my_archive;
+
+	    if (cur_arch != arch)
+	      {
+		cur_arch = arch;
+		is_ms_arch = 1;
+
+		for (is3 = is;
+		     is3 && is3->the_bfd->my_archive == arch;
+		     is3 = (lang_input_statement_type *) is3->next)
+		  {
+		    /* A MS dynamic import library can also contain static
+		       members, so look for the first element with a .dll
+		       extension, and use that for the remainder of the
+		       comparisons.  */
+		    pnt = strrchr (is3->the_bfd->filename, '.');
+		    if (pnt != NULL && strcmp (pnt, ".dll") == 0)
+		      break;
+		  }
+
+		if (is3 == NULL)
+		  is_ms_arch = 0;
+		else
+		  {
+		    /* OK, found one.  Now look to see if the remaining
+		       (dynamic import) members use the same name.  */
+		    for (is2 = is;
+			 is2 && is2->the_bfd->my_archive == arch;
+			 is2 = (lang_input_statement_type *) is2->next)
+		      {
+			/* Skip static members, ie anything with a .obj
+			   extension.  */
+			pnt = strrchr (is2->the_bfd->filename, '.');
+			if (pnt != NULL && strcmp (pnt, ".obj") == 0)
+			  continue;
+
+			if (strcmp (is3->the_bfd->filename,
+				    is2->the_bfd->filename))
+			  {
+			    is_ms_arch = 0;
+			    break;
+			  }
+		      }
+		  }
+	      }
+
+	    /* This fragment might have come from an .obj file in a Microsoft
+	       import, and not an actual import record. If this is the case,
+	       then leave the filename alone.  */
+	    pnt = strrchr (is->the_bfd->filename, '.');
+
+	    if (is_ms_arch && (strcmp (pnt, ".dll") == 0))
+	      {
+		int idata2 = 0, reloc_count=0;
+		asection *sec;
+		char *new_name, seq;
+
+		for (sec = is->the_bfd->sections; sec; sec = sec->next)
+		  {
+		    if (strcmp (sec->name, ".idata\$2") == 0)
+		      idata2 = 1;
+		    reloc_count += sec->reloc_count;
+		  }
+
+		if (idata2) /* .idata2 is the TOC */
+		  seq = 'a';
+		else if (reloc_count > 0) /* thunks */
+		  seq = 'b';
+		else /* sentinel */
+		  seq = 'c';
+
+		new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
+		sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
+		is->the_bfd->filename = new_name;
+
+		new_name = xmalloc (strlen (is->filename) + 3);
+		sprintf (new_name, "%s.%c", is->filename, seq);
+		is->filename = new_name;
+	      }
+	  }
+      }
+  }
+}
+
+static void
+gld_${EMULATION_NAME}_before_allocation (void)
+{
+  before_allocation_default ();
+}
+
+#ifdef DLL_SUPPORT
+/* This is called when an input file isn't recognized as a BFD.  We
+   check here for .DEF files and pull them in automatically.  */
+
+static int
+saw_option (char *option)
+{
+  int i;
+
+  for (i = 0; init[i].ptr; i++)
+    if (strcmp (init[i].symbol, option) == 0)
+      return init[i].inited;
+  return 0;
+}
+#endif /* DLL_SUPPORT */
+
+static bfd_boolean
+gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
+{
+#ifdef DLL_SUPPORT
+  const char *ext = entry->filename + strlen (entry->filename) - 4;
+
+  if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0)
+    {
+      pep_def_file = def_file_parse (entry->filename, pep_def_file);
+
+      if (pep_def_file)
+	{
+	  int i, buflen=0, len;
+	  char *buf;
+
+	  for (i = 0; i < pep_def_file->num_exports; i++)
+	    {
+	      len = strlen (pep_def_file->exports[i].internal_name);
+	      if (buflen < len + 2)
+		buflen = len + 2;
+	    }
+
+	  buf = (char *) xmalloc (buflen);
+
+	  for (i = 0; i < pep_def_file->num_exports; i++)
+	    {
+	      struct bfd_link_hash_entry *h;
+
+	      sprintf (buf, "_%s", pep_def_file->exports[i].internal_name);
+
+	      h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE);
+	      if (h == (struct bfd_link_hash_entry *) NULL)
+		einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
+	      if (h->type == bfd_link_hash_new)
+		{
+		  h->type = bfd_link_hash_undefined;
+		  h->u.undef.abfd = NULL;
+		  bfd_link_add_undef (link_info.hash, h);
+		}
+	    }
+	  free (buf);
+
+	  /* def_file_print (stdout, pep_def_file); */
+	  if (pep_def_file->is_dll == 1)
+	    link_info.shared = 1;
+
+	  if (pep_def_file->base_address != (bfd_vma)(-1))
+	    {
+	      pep.ImageBase =
+		pe_data (output_bfd)->pe_opthdr.ImageBase =
+		init[IMAGEBASEOFF].value = pep_def_file->base_address;
+	      init[IMAGEBASEOFF].inited = 1;
+	      if (image_base_statement)
+		image_base_statement->exp =
+		  exp_assop ('=', "__image_base__", exp_intop (pep.ImageBase));
+	    }
+
+	  if (pep_def_file->stack_reserve != -1
+	      && ! saw_option ("__size_of_stack_reserve__"))
+	    {
+	      pep.SizeOfStackReserve = pep_def_file->stack_reserve;
+	      if (pep_def_file->stack_commit != -1)
+		pep.SizeOfStackCommit = pep_def_file->stack_commit;
+	    }
+	  if (pep_def_file->heap_reserve != -1
+	      && ! saw_option ("__size_of_heap_reserve__"))
+	    {
+	      pep.SizeOfHeapReserve = pep_def_file->heap_reserve;
+	      if (pep_def_file->heap_commit != -1)
+		pep.SizeOfHeapCommit = pep_def_file->heap_commit;
+	    }
+	  return TRUE;
+	}
+    }
+#endif
+  return FALSE;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
+{
+#ifdef DLL_SUPPORT
+#ifdef TARGET_IS_i386pep
+  pep_dll_id_target ("pei-x86-64");
+#endif
+  if (bfd_get_format (entry->the_bfd) == bfd_object)
+    {
+      char fbuf[LD_PATHMAX + 1];
+      const char *ext;
+
+      if (REALPATH (entry->filename, fbuf) == NULL)
+	strncpy (fbuf, entry->filename, sizeof (fbuf));
+
+      ext = fbuf + strlen (fbuf) - 4;
+
+      if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0)
+	return pep_implied_import_dll (fbuf);
+    }
+#endif
+  return FALSE;
+}
+
+static void
+gld_${EMULATION_NAME}_finish (void)
+{
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe)
+  struct bfd_link_hash_entry * h;
+
+  if (thumb_entry_symbol != NULL)
+    {
+      h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
+				FALSE, FALSE, TRUE);
+
+      if (h != (struct bfd_link_hash_entry *) NULL
+	  && (h->type == bfd_link_hash_defined
+	      || h->type == bfd_link_hash_defweak)
+	  && h->u.def.section->output_section != NULL)
+	{
+	  static char buffer[32];
+	  bfd_vma val;
+
+	  /* Special procesing is required for a Thumb entry symbol.  The
+	     bottom bit of its address must be set.  */
+	  val = (h->u.def.value
+		 + bfd_get_section_vma (output_bfd,
+					h->u.def.section->output_section)
+		 + h->u.def.section->output_offset);
+
+	  val |= 1;
+
+	  /* Now convert this value into a string and store it in entry_symbol
+	     where the lang_finish() function will pick it up.  */
+	  buffer[0] = '0';
+	  buffer[1] = 'x';
+
+	  sprintf_vma (buffer + 2, val);
+
+	  if (entry_symbol.name != NULL && entry_from_cmdline)
+	    einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
+		   thumb_entry_symbol, entry_symbol.name);
+	  entry_symbol.name = buffer;
+	}
+      else
+	einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
+    }
+#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) */
+
+  finish_default ();
+
+#ifdef DLL_SUPPORT
+  if (link_info.shared
+    || (!link_info.relocatable && pep_def_file->num_exports != 0)
+    )
+    {
+      pep_dll_fill_sections (output_bfd, &link_info);
+      if (pep_implib_filename)
+	pep_dll_generate_implib (pep_def_file, pep_implib_filename);
+    }
+
+  if (pep_out_def_filename)
+    pep_dll_generate_def_file (pep_out_def_filename);
+#endif /* DLL_SUPPORT */
+
+  /* I don't know where .idata gets set as code, but it shouldn't be.  */
+  {
+    asection *asec = bfd_get_section_by_name (output_bfd, ".idata");
+
+    if (asec)
+      {
+	asec->flags &= ~SEC_CODE;
+	asec->flags |= SEC_DATA;
+      }
+  }
+}
+
+\f
+/* Place an orphan section.
+
+   We use this to put sections in a reasonable place in the file, and
+   to ensure that they are aligned as required.
+
+   We handle grouped sections here as well.  A section named .foo$nn
+   goes into the output section .foo.  All grouped sections are sorted
+   by name.
+
+   Grouped sections for the default sections are handled by the
+   default linker script using wildcards, and are sorted by
+   sort_sections.  */
+
+static bfd_boolean
+gld_${EMULATION_NAME}_place_orphan (asection *s)
+{
+  const char *secname;
+  const char *orig_secname;
+  char *dollar = NULL;
+  lang_output_section_statement_type *os;
+  lang_statement_list_type add_child;
+
+  secname = bfd_get_section_name (s->owner, s);
+
+  /* Look through the script to see where to place this section.  */
+  orig_secname = secname;
+  if (!link_info.relocatable
+      && (dollar = strchr (secname, '$')) != NULL)
+    {
+      size_t len = dollar - orig_secname;
+      char *newname = xmalloc (len + 1);
+      memcpy (newname, orig_secname, len);
+      newname[len] = '\0';
+      secname = newname;
+    }
+
+  os = lang_output_section_find (secname);
+
+  lang_list_init (&add_child);
+
+  if (os != NULL
+      && (os->bfd_section == NULL
+	  || os->bfd_section->flags == 0
+	  || ((s->flags ^ os->bfd_section->flags)
+	      & (SEC_LOAD | SEC_ALLOC)) == 0))
+    {
+      /* We already have an output section statement with this
+	 name, and its bfd section, if any, has compatible flags.
+	 If the section already exists but does not have any flags set,
+	 then it has been created by the linker, probably as a result of
+	 a --section-start command line switch.  */
+      lang_add_section (&add_child, s, os);
+    }
+  else
+    {
+      static struct orphan_save hold[] =
+	{
+	  { ".text",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
+	    0, 0, 0, 0 },
+	  { ".rdata",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+	    0, 0, 0, 0 },
+	  { ".data",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
+	    0, 0, 0, 0 },
+	  { ".bss",
+	    SEC_ALLOC,
+	    0, 0, 0, 0 }
+	};
+      enum orphan_save_index
+	{
+	  orphan_text = 0,
+	  orphan_rodata,
+	  orphan_data,
+	  orphan_bss
+	};
+      static int orphan_init_done = 0;
+      struct orphan_save *place;
+      lang_output_section_statement_type *after;
+      etree_type *address;
+
+      if (!orphan_init_done)
+	{
+	  struct orphan_save *ho;
+	  for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
+	    if (ho->name != NULL)
+	      {
+		ho->os = lang_output_section_find (ho->name);
+		if (ho->os != NULL && ho->os->flags == 0)
+		  ho->os->flags = ho->flags;
+	      }
+	  orphan_init_done = 1;
+	}
+
+      /* Try to put the new output section in a reasonable place based
+	 on the section name and section flags.  */
+
+      place = NULL;
+      if ((s->flags & SEC_ALLOC) == 0)
+	;
+      else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+	place = &hold[orphan_bss];
+      else if ((s->flags & SEC_READONLY) == 0)
+	place = &hold[orphan_data];
+      else if ((s->flags & SEC_CODE) == 0)
+	place = &hold[orphan_rodata];
+      else
+	place = &hold[orphan_text];
+
+      after = NULL;
+      if (place != NULL)
+	{
+	  if (place->os == NULL)
+	    place->os = lang_output_section_find (place->name);
+	  after = place->os;
+	  if (after == NULL)
+	    after = lang_output_section_find_by_flags (s, &place->os, NULL);
+	  if (after == NULL)
+	    /* *ABS* is always the first output section statement.  */
+	    after = (&lang_output_section_statement.head
+		     ->output_section_statement);
+	}
+
+      /* Choose a unique name for the section.  This will be needed if the
+	 same section name appears in the input file with different
+	 loadable or allocatable characteristics.  */
+      if (bfd_get_section_by_name (output_bfd, secname) != NULL)
+	{
+	  static int count = 1;
+	  secname = bfd_get_unique_section_name (output_bfd, secname, &count);
+	  if (secname == NULL)
+	    einfo ("%F%P: place_orphan failed: %E\n");
+	}
+
+      /* All sections in an executable must be aligned to a page boundary.  */
+      address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
+      os = lang_insert_orphan (s, secname, after, place, address, &add_child);
+    }
+
+  {
+    lang_statement_union_type **pl = &os->children.head;
+
+    if (dollar != NULL)
+      {
+	bfd_boolean found_dollar;
+
+	/* The section name has a '$'.  Sort it with the other '$'
+	   sections.  */
+	found_dollar = FALSE;
+	for ( ; *pl != NULL; pl = &(*pl)->header.next)
+	  {
+	    lang_input_section_type *ls;
+	    const char *lname;
+
+	    if ((*pl)->header.type != lang_input_section_enum)
+	      continue;
+
+	    ls = &(*pl)->input_section;
+
+	    lname = bfd_get_section_name (ls->section->owner, ls->section);
+	    if (strchr (lname, '$') == NULL)
+	      {
+		if (found_dollar)
+		  break;
+	      }
+	    else
+	      {
+		found_dollar = TRUE;
+		if (strcmp (orig_secname, lname) < 0)
+		  break;
+	      }
+	  }
+      }
+
+    if (add_child.head != NULL)
+      {
+	add_child.head->header.next = *pl;
+	*pl = add_child.head;
+      }
+  }
+
+  return TRUE;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_open_dynamic_archive
+  (const char *arch ATTRIBUTE_UNUSED, search_dirs_type *search,
+   lang_input_statement_type *entry)
+{
+  const char * filename;
+  char * string;
+
+  if (! entry->is_archive)
+    return FALSE;
+
+  filename = entry->filename;
+
+  string = (char *) xmalloc (strlen (search->name)
+			     + strlen (filename)
+			     + sizeof "/lib.a.dll"
+#ifdef DLL_SUPPORT
+			     + (pep_dll_search_prefix ? strlen (pep_dll_search_prefix) : 0)
+#endif
+			     + 1);
+
+  /* Try "libfoo.dll.a" first (preferred explicit import library for dll's.  */
+  sprintf (string, "%s/lib%s.dll.a", search->name, filename);
+
+  if (! ldfile_try_open_bfd (string, entry))
+    {
+      /* Try "foo.dll.a" next (alternate explicit import library for dll's.  */
+      sprintf (string, "%s/%s.dll.a", search->name, filename);
+      if (! ldfile_try_open_bfd (string, entry))
+	{
+	  /* Try libfoo.a next. Normally, this would be interpreted as a static
+	     library, but it *could* be an import library. For backwards compatibility,
+	     libfoo.a needs to ==precede== libfoo.dll and foo.dll in the search,
+	     or sometimes errors occur when building legacy packages.
+
+	     Putting libfoo.a here means that in a failure case (i.e. the library
+	     -lfoo is not found) we will search for libfoo.a twice before
+	     giving up -- once here, and once when searching for a "static" lib.
+	     for a "static" lib.  */
+	  /* Try "libfoo.a" (import lib, or static lib, but must
+	     take precedence over dll's).  */
+	  sprintf (string, "%s/lib%s.a", search->name, filename);
+	  if (! ldfile_try_open_bfd (string, entry))
+	    {
+#ifdef DLL_SUPPORT
+	      if (pep_dll_search_prefix)
+		{
+		  /* Try "<prefix>foo.dll" (preferred dll name, if specified).  */
+		  sprintf (string, "%s/%s%s.dll", search->name, pep_dll_search_prefix, filename);
+		  if (! ldfile_try_open_bfd (string, entry))
+		    {
+		      /* Try "libfoo.dll" (default preferred dll name).  */
+		      sprintf (string, "%s/lib%s.dll", search->name, filename);
+		      if (! ldfile_try_open_bfd (string, entry))
+			{
+			  /* Finally, try "foo.dll" (alternate dll name).  */
+			  sprintf (string, "%s/%s.dll", search->name, filename);
+			  if (! ldfile_try_open_bfd (string, entry))
+			    {
+			      free (string);
+			      return FALSE;
+			    }
+			}
+		    }
+		}
+	      else /* pep_dll_search_prefix not specified.  */
+#endif
+		{
+		  /* Try "libfoo.dll" (preferred dll name).  */
+		  sprintf (string, "%s/lib%s.dll", search->name, filename);
+		  if (! ldfile_try_open_bfd (string, entry))
+		    {
+		      /* Finally, try "foo.dll" (alternate dll name).  */
+		      sprintf (string, "%s/%s.dll", search->name, filename);
+		      if (! ldfile_try_open_bfd (string, entry))
+			{
+			  free (string);
+			  return FALSE;
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+  entry->filename = string;
+
+  return TRUE;
+}
+
+static int
+gld_${EMULATION_NAME}_find_potential_libraries
+  (char *name, lang_input_statement_type *entry)
+{
+  return ldfile_open_file_search (name, entry, "", ".lib");
+}
+\f
+static char *
+gld_${EMULATION_NAME}_get_script (int *isfile)
+EOF
+# Scripts compiled in.
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+  *isfile = 0;
+
+  if (link_info.relocatable && config.build_constructors)
+    return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu			>> e${EMULATION_NAME}.c
+echo '  ; else if (link_info.relocatable) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr			>> e${EMULATION_NAME}.c
+echo '  ; else if (!config.text_read_only) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn			>> e${EMULATION_NAME}.c
+echo '  ; else if (!config.magic_demand_paged) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn			>> e${EMULATION_NAME}.c
+echo '  ; else return'					>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x			>> e${EMULATION_NAME}.c
+echo '; }'						>> e${EMULATION_NAME}.c
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+  gld_${EMULATION_NAME}_before_parse,
+  syslib_default,
+  hll_default,
+  gld_${EMULATION_NAME}_after_parse,
+  gld_${EMULATION_NAME}_after_open,
+  after_allocation_default,
+  set_output_arch_default,
+  ldemul_default_target,
+  gld_${EMULATION_NAME}_before_allocation,
+  gld_${EMULATION_NAME}_get_script,
+  "${EMULATION_NAME}",
+  "${OUTPUT_FORMAT}",
+  gld_${EMULATION_NAME}_finish,
+  NULL, /* Create output section statements.  */
+  gld_${EMULATION_NAME}_open_dynamic_archive,
+  gld_${EMULATION_NAME}_place_orphan,
+  gld_${EMULATION_NAME}_set_symbols,
+  NULL, /* parse_args */
+  gld${EMULATION_NAME}_add_options,
+  gld${EMULATION_NAME}_handle_option,
+  gld_${EMULATION_NAME}_unrecognized_file,
+  gld_${EMULATION_NAME}_list_options,
+  gld_${EMULATION_NAME}_recognized_file,
+  gld_${EMULATION_NAME}_find_potential_libraries,
+  NULL	/* new_vers_pattern.  */
+};
+EOF
diff -rNbu binutils-2.17_org/ld/pep-dll.c binutils-2.17/ld/pep-dll.c
--- binutils-2.17_org/ld/pep-dll.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/ld/pep-dll.c	2006-08-17 09:13:17.000000000 +0200
@@ -0,0 +1,2687 @@
+/* Routines to help build PEPI-format DLLs (Win64 etc)
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libiberty.h"
+#include "safe-ctype.h"
+
+#include <time.h>
+
+#include "ld.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldwrite.h"
+#include "ldmisc.h"
+#include <ldgram.h>
+#include "ldmain.h"
+#include "ldfile.h"
+#include "ldemul.h"
+#include "coff/internal.h"
+#include "../bfd/libcoff.h"
+#include "deffile.h"
+#include "pep-dll.h"
+
+#undef AOUTSZ
+#define AOUTSZ		PEPAOUTSZ
+#define PEAOUTHDR	PEPAOUTHDR
+
+/*  This file turns a regular Windows PE image into a DLL.  Because of
+    the complexity of this operation, it has been broken down into a
+    number of separate modules which are all called by the main function
+    at the end of this file.  This function is not re-entrant and is
+    normally only called once, so static variables are used to reduce
+    the number of parameters and return values required.
+
+    See also: ld/emultempl/pep.em.  */
+
+/*  Auto-import feature by Paul Sokolovsky
+
+    Quick facts:
+
+    1. With this feature on, DLL clients can import variables from DLL
+    without any concern from their side (for example, without any source
+    code modifications).
+
+    2. This is done completely in bounds of the PE specification (to be fair,
+    there's a place where it pokes nose out of, but in practice it works).
+    So, resulting module can be used with any other PE compiler/linker.
+
+    3. Auto-import is fully compatible with standard import method and they
+    can be mixed together.
+
+    4. Overheads: space: 8 bytes per imported symbol, plus 20 for each
+    reference to it; load time: negligible; virtual/physical memory: should be
+    less than effect of DLL relocation, and I sincerely hope it doesn't affect
+    DLL sharability (too much).
+
+    Idea
+
+    The obvious and only way to get rid of dllimport insanity is to make client
+    access variable directly in the DLL, bypassing extra dereference. I.e.,
+    whenever client contains something like
+
+    mov dll_var,%eax,
+
+    address of dll_var in the command should be relocated to point into loaded
+    DLL. The aim is to make OS loader do so, and than make ld help with that.
+    Import section of PE made following way: there's a vector of structures
+    each describing imports from particular DLL. Each such structure points
+    to two other parallel vectors: one holding imported names, and one which
+    will hold address of corresponding imported name. So, the solution is
+    de-vectorize these structures, making import locations be sparse and
+    pointing directly into code. Before continuing, it is worth a note that,
+    while authors strives to make PE act ELF-like, there're some other people
+    make ELF act PE-like: elfvector, ;-) .
+
+    Implementation
+
+    For each reference of data symbol to be imported from DLL (to set of which
+    belong symbols with name <sym>, if __imp_<sym> is found in implib), the
+    import fixup entry is generated. That entry is of type
+    IMAGE_IMPORT_DESCRIPTOR and stored in .idata$3 subsection. Each
+    fixup entry contains pointer to symbol's address within .text section
+    (marked with __fuN_<sym> symbol, where N is integer), pointer to DLL name
+    (so, DLL name is referenced by multiple entries), and pointer to symbol
+    name thunk. Symbol name thunk is singleton vector (__nm_th_<symbol>)
+    pointing to IMAGE_IMPORT_BY_NAME structure (__nm_<symbol>) directly
+    containing imported name. Here comes that "om the edge" problem mentioned
+    above: PE specification rambles that name vector (OriginalFirstThunk)
+    should run in parallel with addresses vector (FirstThunk), i.e. that they
+    should have same number of elements and terminated with zero. We violate
+    this, since FirstThunk points directly into machine code. But in practice,
+    OS loader implemented the sane way: it goes thru OriginalFirstThunk and
+    puts addresses to FirstThunk, not something else. It once again should be
+    noted that dll and symbol name structures are reused across fixup entries
+    and should be there anyway to support standard import stuff, so sustained
+    overhead is 20 bytes per reference. Other question is whether having several
+    IMAGE_IMPORT_DESCRIPTORS for the same DLL is possible. Answer is yes, it is
+    done even by native compiler/linker (libth32's functions are in fact reside
+    in windows9x kernel32.dll, so if you use it, you have two
+    IMAGE_IMPORT_DESCRIPTORS for kernel32.dll). Yet other question is whether
+    referencing the same PE structures several times is valid. The answer is why
+    not, prohibiting that (detecting violation) would require more work on
+    behalf of loader than not doing it.
+
+    See also: ld/emultempl/pe.em.  */
+
+static void add_bfd_to_link (bfd *, const char *, struct bfd_link_info *);
+
+/* For emultempl/pe.em.  */
+
+def_file * pep_def_file = 0;
+int pep_dll_export_everything = 0;
+int pep_dll_do_default_excludes = 1;
+int pep_dll_kill_ats = 0;
+int pep_dll_stdcall_aliases = 0;
+int pep_dll_warn_dup_exports = 0;
+int pep_dll_compat_implib = 0;
+int pep_dll_extra_pe_debug = 0;
+
+/* Static variables and types.  */
+
+static bfd_vma image_base;
+static bfd *filler_bfd;
+static struct bfd_section *edata_s, *reloc_s;
+static unsigned char *edata_d, *reloc_d;
+static size_t edata_sz, reloc_sz;
+static int runtime_pseudo_relocs_created = 0;
+
+typedef struct
+  {
+    char *target_name;
+    char *object_target;
+    unsigned int imagebase_reloc;
+    int pep_arch;
+    int bfd_arch;
+    int underscored;
+  }
+pep_details_type;
+
+typedef struct
+  {
+    char *name;
+    int len;
+  }
+autofilter_entry_type;
+
+#define PE_ARCH_i386	1
+#define PE_ARCH_sh	2
+#define PE_ARCH_mips	3
+#define PE_ARCH_arm	4
+#define PE_ARCH_arm_epoc 5
+
+static pep_details_type pep_detail_list[] =
+{
+  {
+    "pei-x86-64",
+    "pe-x86-64",
+    3 /* R_IMAGEBASE */,
+    PE_ARCH_i386,
+    bfd_arch_i386,
+    1
+  },
+  { NULL, NULL, 0, 0, 0, 0 }
+};
+
+static pep_details_type *pep_details;
+
+static autofilter_entry_type autofilter_symbollist[] =
+{
+  { "DllMain@12", 10 },
+  { "DllEntryPoint@0", 15 },
+  { "DllMainCRTStartup@12", 20 },
+  { "_cygwin_dll_entry@12", 20 },
+  { "_cygwin_crt0_common@8", 21 },
+  { "_cygwin_noncygwin_dll_entry@12", 30 },
+  { "impure_ptr", 10 },
+  { "_pei386_runtime_relocator", 25 },
+  { "do_pseudo_reloc", 15 },
+  { "cygwin_crt0", 11 },
+  { NULL, 0 }
+};
+
+/* Do not specify library suffix explicitly, to allow for dllized versions.  */
+static autofilter_entry_type autofilter_liblist[] =
+{
+  { "libcygwin", 9 },
+  { "libgcc", 6 },
+  { "libstdc++", 9 },
+  { "libmingw32", 10 },
+  { "libmingwex", 10 },
+  { "libg2c", 6 },
+  { "libsupc++", 9 },
+  { "libobjc", 7 },
+  { "libgcj", 6 },
+  { NULL, 0 }
+};
+
+static autofilter_entry_type autofilter_objlist[] =
+{
+  { "crt0.o", 6 },
+  { "crt1.o", 6 },
+  { "crt2.o", 6 },
+  { "dllcrt1.o", 9 },
+  { "dllcrt2.o", 9 },
+  { "gcrt0.o", 7 },
+  { "gcrt1.o", 7 },
+  { "gcrt2.o", 7 },
+  { "crtbegin.o", 10 },
+  { "crtend.o", 8 },
+  { NULL, 0 }
+};
+
+static autofilter_entry_type autofilter_symbolprefixlist[] =
+{
+  /* { "__imp_", 6 }, */
+  /* Do __imp_ explicitly to save time.  */
+  { "__rtti_", 7 },
+  /* Don't re-export auto-imported symbols.  */
+  { "_nm_", 4 },
+  { "__builtin_", 10 },
+  /* Don't export symbols specifying internal DLL layout.  */
+  { "_head_", 6 },
+  { "_fmode", 6 },
+  { "_impure_ptr", 11 },
+  { "cygwin_attach_dll", 17 },
+  { "cygwin_premain0", 15 },
+  { "cygwin_premain1", 15 },
+  { "cygwin_premain2", 15 },
+  { "cygwin_premain3", 15 },
+  { "environ", 7 },
+  { NULL, 0 }
+};
+
+static autofilter_entry_type autofilter_symbolsuffixlist[] =
+{
+  { "_iname", 6 },
+  { NULL, 0 }
+};
+
+#define U(str) (pep_details->underscored ? "_" str : str)
+
+void
+pep_dll_id_target (const char *target)
+{
+  int i;
+
+  for (i = 0; pep_detail_list[i].target_name; i++)
+    if (strcmp (pep_detail_list[i].target_name, target) == 0
+	|| strcmp (pep_detail_list[i].object_target, target) == 0)
+      {
+	pep_details = pep_detail_list + i;
+	return;
+      }
+  einfo (_("%XUnsupported PEI architecture: %s\n"), target);
+  exit (1);
+}
+
+/* Helper functions for qsort.  Relocs must be sorted so that we can write
+   them out by pages.  */
+
+typedef struct
+  {
+    bfd_vma vma;
+    char type;
+    short extra;
+  }
+reloc_data_type;
+
+static int
+reloc_sort (const void *va, const void *vb)
+{
+  bfd_vma a = ((const reloc_data_type *) va)->vma;
+  bfd_vma b = ((const reloc_data_type *) vb)->vma;
+
+  return (a > b) ? 1 : ((a < b) ? -1 : 0);
+}
+
+static int
+pep_export_sort (const void *va, const void *vb)
+{
+  const def_file_export *a = va;
+  const def_file_export *b = vb;
+
+  return strcmp (a->name, b->name);
+}
+
+/* Read and process the .DEF file.  */
+
+/* These correspond to the entries in pep_def_file->exports[].  I use
+   exported_symbol_sections[i] to tag whether or not the symbol was
+   defined, since we can't export symbols we don't have.  */
+
+static bfd_vma *exported_symbol_offsets;
+static struct bfd_section **exported_symbol_sections;
+static int export_table_size;
+static int count_exported;
+static int count_exported_byname;
+static int count_with_ordinals;
+static const char *dll_name;
+static int min_ordinal, max_ordinal;
+static int *exported_symbols;
+
+typedef struct exclude_list_struct
+  {
+    char *string;
+    struct exclude_list_struct *next;
+    int type;
+  }
+exclude_list_struct;
+
+static struct exclude_list_struct *excludes = 0;
+
+void
+pep_dll_add_excludes (const char *new_excludes, const int type)
+{
+  char *local_copy;
+  char *exclude_string;
+
+  local_copy = xstrdup (new_excludes);
+
+  exclude_string = strtok (local_copy, ",:");
+  for (; exclude_string; exclude_string = strtok (NULL, ",:"))
+    {
+      struct exclude_list_struct *new_exclude;
+
+      new_exclude = xmalloc (sizeof (struct exclude_list_struct));
+      new_exclude->string = xmalloc (strlen (exclude_string) + 1);
+      strcpy (new_exclude->string, exclude_string);
+      new_exclude->type = type;
+      new_exclude->next = excludes;
+      excludes = new_exclude;
+    }
+
+  free (local_copy);
+}
+
+
+/* abfd is a bfd containing n (or NULL)
+   It can be used for contextual checks.  */
+
+static int
+auto_export (bfd *abfd, def_file *d, const char *n)
+{
+  int i;
+  struct exclude_list_struct *ex;
+  autofilter_entry_type *afptr;
+  const char * libname = 0;
+  if (abfd && abfd->my_archive)
+    libname = lbasename (abfd->my_archive->filename);
+
+  /* We should not re-export imported stuff.  */
+  if (strncmp (n, "_imp_", 5) == 0)
+    return 0;
+
+  for (i = 0; i < d->num_exports; i++)
+    if (strcmp (d->exports[i].name, n) == 0)
+      return 0;
+
+  if (pep_dll_do_default_excludes)
+    {
+      const char * p;
+      int    len;
+
+      if (pep_dll_extra_pe_debug)
+	printf ("considering exporting: %s, abfd=%p, abfd->my_arc=%p\n",
+		n, abfd, abfd->my_archive);
+
+      /* First of all, make context checks:
+	 Don't export anything from standard libs.  */
+      if (libname)
+	{
+	  afptr = autofilter_liblist;
+
+	  while (afptr->name)
+	    {
+	      if (strncmp (libname, afptr->name, afptr->len) == 0 )
+		return 0;
+	      afptr++;
+	    }
+	}
+
+      /* Next, exclude symbols from certain startup objects.  */
+
+      if (abfd && (p = lbasename (abfd->filename)))
+	{
+	  afptr = autofilter_objlist;
+	  while (afptr->name)
+	    {
+	      if (strcmp (p, afptr->name) == 0)
+		return 0;
+	      afptr++;
+	    }
+	}
+
+      /* Don't try to blindly exclude all symbols
+	 that begin with '__'; this was tried and
+	 it is too restrictive.  */
+
+      /* Then, exclude specific symbols.  */
+      afptr = autofilter_symbollist;
+      while (afptr->name)
+	{
+	  if (strcmp (n, afptr->name) == 0)
+	    return 0;
+
+	  afptr++;
+	}
+
+      /* Next, exclude symbols starting with ...  */
+      afptr = autofilter_symbolprefixlist;
+      while (afptr->name)
+	{
+	  if (strncmp (n, afptr->name, afptr->len) == 0)
+	    return 0;
+
+	  afptr++;
+	}
+
+      /* Finally, exclude symbols ending with ...  */
+      len = strlen (n);
+      afptr = autofilter_symbolsuffixlist;
+      while (afptr->name)
+	{
+	  if ((len >= afptr->len)
+	      /* Add 1 to insure match with trailing '\0'.  */
+	      && strncmp (n + len - afptr->len, afptr->name,
+			  afptr->len + 1) == 0)
+	    return 0;
+
+	  afptr++;
+	}
+    }
+
+  for (ex = excludes; ex; ex = ex->next)
+    {
+      if (ex->type == 1) /* exclude-libs */
+	{
+	  if (libname
+	      && ((strcmp (libname, ex->string) == 0)
+		   || (strcasecmp ("ALL", ex->string) == 0)))
+	    return 0;
+	}
+      else if (strcmp (n, ex->string) == 0)
+	return 0;
+    }
+
+  return 1;
+}
+
+static void
+process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
+{
+  int i, j;
+  struct bfd_link_hash_entry *blhe;
+  bfd *b;
+  struct bfd_section *s;
+  def_file_export *e = 0;
+
+  if (!pep_def_file)
+    pep_def_file = def_file_empty ();
+
+  /* First, run around to all the objects looking for the .drectve
+     sections, and push those into the def file too.  */
+  for (b = info->input_bfds; b; b = b->link_next)
+    {
+      s = bfd_get_section_by_name (b, ".drectve");
+      if (s)
+	{
+	  long size = s->size;
+	  char *buf = xmalloc (size);
+
+	  bfd_get_section_contents (b, s, buf, 0, size);
+	  def_file_add_directive (pep_def_file, buf, size);
+	  free (buf);
+	}
+    }
+
+  /* If we are not building a DLL, when there are no exports
+     we do not build an export table at all.  */
+  if (!pep_dll_export_everything && pep_def_file->num_exports == 0
+      && info->executable)
+    return;
+
+  /* Now, maybe export everything else the default way.  */
+  if (pep_dll_export_everything || pep_def_file->num_exports == 0)
+    {
+      for (b = info->input_bfds; b; b = b->link_next)
+	{
+	  asymbol **symbols;
+	  int nsyms, symsize;
+
+	  symsize = bfd_get_symtab_upper_bound (b);
+	  symbols = xmalloc (symsize);
+	  nsyms = bfd_canonicalize_symtab (b, symbols);
+
+	  for (j = 0; j < nsyms; j++)
+	    {
+	      /* We should export symbols which are either global or not
+		 anything at all.  (.bss data is the latter)
+		 We should not export undefined symbols.  */
+	      if (symbols[j]->section != &bfd_und_section
+		  && ((symbols[j]->flags & BSF_GLOBAL)
+		      || (symbols[j]->flags == BFD_FORT_COMM_DEFAULT_VALUE)))
+		{
+		  const char *sn = symbols[j]->name;
+
+		  /* We should not re-export imported stuff.  */
+		  {
+		    char *name = xmalloc (strlen (sn) + 2 + 6);
+		    sprintf (name, "%s%s", U("_imp_"), sn);
+			printf("*** Export Sym:%s\n",name);
+		    blhe = bfd_link_hash_lookup (info->hash, name,
+						 FALSE, FALSE, FALSE);
+		    free (name);
+
+		    if (blhe && blhe->type == bfd_link_hash_defined)
+		      continue;
+		  }
+
+		  if (*sn == '_')
+		    sn++;
+
+		  if (auto_export (b, pep_def_file, sn))
+		    {
+		      def_file_export *p;
+		      p=def_file_add_export (pep_def_file, sn, 0, -1);
+		      /* Fill data flag properly, from dlltool.c.  */
+		      p->flag_data = !(symbols[j]->flags & BSF_FUNCTION);
+		    }
+		}
+	    }
+	}
+    }
+
+#undef NE
+#define NE pep_def_file->num_exports
+
+  /* Canonicalize the export list.  */
+  if (pep_dll_kill_ats)
+    {
+      for (i = 0; i < NE; i++)
+	{
+	  if (strchr (pep_def_file->exports[i].name, '@'))
+	    {
+	      /* This will preserve internal_name, which may have been
+		 pointing to the same memory as name, or might not
+		 have.  */
+	      int lead_at = (*pep_def_file->exports[i].name == '@');
+	      char *tmp = xstrdup (pep_def_file->exports[i].name + lead_at);
+	      char *tmp_at = strchr (tmp, '@');
+
+	      if (tmp_at)
+	        *tmp_at = 0;
+	      else
+	        einfo (_("%XCannot export %s: invalid export name\n"),
+		       pep_def_file->exports[i].name);
+	      pep_def_file->exports[i].name = tmp;
+	    }
+	}
+    }
+
+  if (pep_dll_stdcall_aliases)
+    {
+      for (i = 0; i < NE; i++)
+	{
+	  if (strchr (pep_def_file->exports[i].name, '@'))
+	    {
+	      int lead_at = (*pep_def_file->exports[i].name == '@');
+	      char *tmp = xstrdup (pep_def_file->exports[i].name + lead_at);
+
+	      *(strchr (tmp, '@')) = 0;
+	      if (auto_export (NULL, pep_def_file, tmp))
+		def_file_add_export (pep_def_file, tmp,
+				     pep_def_file->exports[i].internal_name,
+				     -1);
+	      else
+		free (tmp);
+	    }
+	}
+    }
+
+  /* Convenience, but watch out for it changing.  */
+  e = pep_def_file->exports;
+
+  exported_symbol_offsets = xmalloc (NE * sizeof (bfd_vma));
+  exported_symbol_sections = xmalloc (NE * sizeof (struct bfd_section *));
+
+  memset (exported_symbol_sections, 0, NE * sizeof (struct bfd_section *));
+  max_ordinal = 0;
+  min_ordinal = 65536;
+  count_exported = 0;
+  count_exported_byname = 0;
+  count_with_ordinals = 0;
+
+  qsort (pep_def_file->exports, NE, sizeof (pep_def_file->exports[0]),
+	 pep_export_sort);
+  for (i = 0, j = 0; i < NE; i++)
+    {
+      if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0)
+	{
+	  /* This is a duplicate.  */
+	  if (e[j - 1].ordinal != -1
+	      && e[i].ordinal != -1
+	      && e[j - 1].ordinal != e[i].ordinal)
+	    {
+	      if (pep_dll_warn_dup_exports)
+		/* xgettext:c-format */
+		einfo (_("%XError, duplicate EXPORT with ordinals: %s (%d vs %d)\n"),
+		       e[j - 1].name, e[j - 1].ordinal, e[i].ordinal);
+	    }
+	  else
+	    {
+	      if (pep_dll_warn_dup_exports)
+		/* xgettext:c-format */
+		einfo (_("Warning, duplicate EXPORT: %s\n"),
+		       e[j - 1].name);
+	    }
+
+	  if (e[i].ordinal != -1)
+	    e[j - 1].ordinal = e[i].ordinal;
+	  e[j - 1].flag_private |= e[i].flag_private;
+	  e[j - 1].flag_constant |= e[i].flag_constant;
+	  e[j - 1].flag_noname |= e[i].flag_noname;
+	  e[j - 1].flag_data |= e[i].flag_data;
+	}
+      else
+	{
+	  if (i != j)
+	    e[j] = e[i];
+	  j++;
+	}
+    }
+  pep_def_file->num_exports = j;	/* == NE */
+
+  for (i = 0; i < NE; i++)
+    {
+      char *name;
+
+      /* Check for forward exports */
+      if (strchr (pep_def_file->exports[i].internal_name, '.'))
+	{
+	  count_exported++;
+	  if (!pep_def_file->exports[i].flag_noname)
+	    count_exported_byname++;
+
+	  pep_def_file->exports[i].flag_forward = 1;
+
+	  if (pep_def_file->exports[i].ordinal != -1)
+	    {
+	      if (max_ordinal < pep_def_file->exports[i].ordinal)
+		max_ordinal = pep_def_file->exports[i].ordinal;
+	      if (min_ordinal > pep_def_file->exports[i].ordinal)
+		min_ordinal = pep_def_file->exports[i].ordinal;
+	      count_with_ordinals++;
+	    }
+
+	  continue;
+	}
+
+      name = xmalloc (strlen (pep_def_file->exports[i].internal_name) + 2);
+      if (pep_details->underscored
+ 	  && (*pep_def_file->exports[i].internal_name != '@'))
+	{
+	  *name = '_';
+	  strcpy (name + 1, pep_def_file->exports[i].internal_name);
+	}
+      else
+	strcpy (name, pep_def_file->exports[i].internal_name);
+
+      blhe = bfd_link_hash_lookup (info->hash,
+				   name,
+				   FALSE, FALSE, TRUE);
+
+      if (blhe
+	  && (blhe->type == bfd_link_hash_defined
+	      || (blhe->type == bfd_link_hash_common)))
+	{
+	  count_exported++;
+	  if (!pep_def_file->exports[i].flag_noname)
+	    count_exported_byname++;
+
+	  /* Only fill in the sections. The actual offsets are computed
+	     in fill_exported_offsets() after common symbols are laid
+	     out.  */
+	  if (blhe->type == bfd_link_hash_defined)
+	    exported_symbol_sections[i] = blhe->u.def.section;
+	  else
+	    exported_symbol_sections[i] = blhe->u.c.p->section;
+
+	  if (pep_def_file->exports[i].ordinal != -1)
+	    {
+	      if (max_ordinal < pep_def_file->exports[i].ordinal)
+		max_ordinal = pep_def_file->exports[i].ordinal;
+	      if (min_ordinal > pep_def_file->exports[i].ordinal)
+		min_ordinal = pep_def_file->exports[i].ordinal;
+	      count_with_ordinals++;
+	    }
+	}
+      else if (blhe && blhe->type == bfd_link_hash_undefined)
+	{
+	  /* xgettext:c-format */
+	  einfo (_("%XCannot export %s: symbol not defined\n"),
+		 pep_def_file->exports[i].internal_name);
+	}
+      else if (blhe)
+	{
+	  /* xgettext:c-format */
+	  einfo (_("%XCannot export %s: symbol wrong type (%d vs %d)\n"),
+		 pep_def_file->exports[i].internal_name,
+		 blhe->type, bfd_link_hash_defined);
+	}
+      else
+	{
+	  /* xgettext:c-format */
+	  einfo (_("%XCannot export %s: symbol not found\n"),
+		 pep_def_file->exports[i].internal_name);
+	}
+      free (name);
+    }
+}
+
+/* Build the bfd that will contain .edata and .reloc sections.  */
+
+static void
+build_filler_bfd (int include_edata)
+{
+  lang_input_statement_type *filler_file;
+  filler_file = lang_add_input_file ("dll stuff",
+				     lang_input_file_is_fake_enum,
+				     NULL);
+  filler_file->the_bfd = filler_bfd = bfd_create ("dll stuff", output_bfd);
+  if (filler_bfd == NULL
+      || !bfd_set_arch_mach (filler_bfd,
+			     bfd_get_arch (output_bfd),
+			     bfd_get_mach (output_bfd)))
+    {
+      einfo ("%X%P: can not create BFD: %E\n");
+      return;
+    }
+
+  if (include_edata)
+    {
+      edata_s = bfd_make_section_old_way (filler_bfd, ".edata");
+      if (edata_s == NULL
+	  || !bfd_set_section_flags (filler_bfd, edata_s,
+				     (SEC_HAS_CONTENTS
+				      | SEC_ALLOC
+				      | SEC_LOAD
+				      | SEC_KEEP
+				      | SEC_IN_MEMORY)))
+	{
+	  einfo ("%X%P: can not create .edata section: %E\n");
+	  return;
+	}
+      bfd_set_section_size (filler_bfd, edata_s, edata_sz);
+    }
+
+  reloc_s = bfd_make_section_old_way (filler_bfd, ".reloc");
+  if (reloc_s == NULL
+      || !bfd_set_section_flags (filler_bfd, reloc_s,
+				 (SEC_HAS_CONTENTS
+				  | SEC_ALLOC
+				  | SEC_LOAD
+				  | SEC_KEEP
+				  | SEC_IN_MEMORY)))
+    {
+      einfo ("%X%P: can not create .reloc section: %E\n");
+      return;
+    }
+
+  bfd_set_section_size (filler_bfd, reloc_s, 0);
+
+  ldlang_add_file (filler_file);
+}
+
+/* Gather all the exported symbols and build the .edata section.  */
+
+static void
+generate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  int i, next_ordinal;
+  int name_table_size = 0;
+  const char *dlnp;
+
+  /* First, we need to know how many exported symbols there are,
+     and what the range of ordinals is.  */
+  if (pep_def_file->name)
+    dll_name = pep_def_file->name;
+  else
+    {
+      dll_name = abfd->filename;
+
+      for (dlnp = dll_name; *dlnp; dlnp++)
+	if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':')
+	  dll_name = dlnp + 1;
+    }
+
+  if (count_with_ordinals && max_ordinal > count_exported)
+    {
+      if (min_ordinal > max_ordinal - count_exported + 1)
+	min_ordinal = max_ordinal - count_exported + 1;
+    }
+  else
+    {
+      min_ordinal = 1;
+      max_ordinal = count_exported;
+    }
+
+  export_table_size = max_ordinal - min_ordinal + 1;
+  exported_symbols = xmalloc (export_table_size * sizeof (int));
+  for (i = 0; i < export_table_size; i++)
+    exported_symbols[i] = -1;
+
+  /* Now we need to assign ordinals to those that don't have them.  */
+  for (i = 0; i < NE; i++)
+    {
+      if (exported_symbol_sections[i] ||
+          pep_def_file->exports[i].flag_forward)
+	{
+	  if (pep_def_file->exports[i].ordinal != -1)
+	    {
+	      int ei = pep_def_file->exports[i].ordinal - min_ordinal;
+	      int pi = exported_symbols[ei];
+
+	      if (pi != -1)
+		{
+		  /* xgettext:c-format */
+		  einfo (_("%XError, ordinal used twice: %d (%s vs %s)\n"),
+			 pep_def_file->exports[i].ordinal,
+			 pep_def_file->exports[i].name,
+			 pep_def_file->exports[pi].name);
+		}
+	      exported_symbols[ei] = i;
+	    }
+	  name_table_size += strlen (pep_def_file->exports[i].name) + 1;
+	}
+
+      /* Reserve space for the forward name. */
+      if (pep_def_file->exports[i].flag_forward)
+	{
+	  name_table_size += strlen (pep_def_file->exports[i].internal_name) + 1;
+	}
+    }
+
+  next_ordinal = min_ordinal;
+  for (i = 0; i < NE; i++)
+    if ((exported_symbol_sections[i] ||
+         pep_def_file->exports[i].flag_forward) &&
+        pep_def_file->exports[i].ordinal == -1)
+      {
+	while (exported_symbols[next_ordinal - min_ordinal] != -1)
+	  next_ordinal++;
+
+	exported_symbols[next_ordinal - min_ordinal] = i;
+	pep_def_file->exports[i].ordinal = next_ordinal;
+      }
+
+  /* OK, now we can allocate some memory.  */
+  edata_sz = (40				/* directory */
+	      + 4 * export_table_size		/* addresses */
+	      + 4 * count_exported_byname	/* name ptrs */
+	      + 2 * count_exported_byname	/* ordinals */
+	      + name_table_size + strlen (dll_name) + 1);
+}
+
+/* Fill the exported symbol offsets. The preliminary work has already
+   been done in process_def_file().  */
+
+static void
+fill_exported_offsets (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
+{
+  int i;
+  struct bfd_link_hash_entry *blhe;
+
+  for (i = 0; i < pep_def_file->num_exports; i++)
+    {
+      char *name;
+
+      name = xmalloc (strlen (pep_def_file->exports[i].internal_name) + 2);
+      if (pep_details->underscored
+ 	  && *pep_def_file->exports[i].internal_name != '@')
+	{
+	  *name = '_';
+	  strcpy (name + 1, pep_def_file->exports[i].internal_name);
+	}
+      else
+	strcpy (name, pep_def_file->exports[i].internal_name);
+
+      blhe = bfd_link_hash_lookup (info->hash,
+				   name,
+				   FALSE, FALSE, TRUE);
+
+      if (blhe && blhe->type == bfd_link_hash_defined)
+	exported_symbol_offsets[i] = blhe->u.def.value;
+
+      free (name);
+    }
+}
+
+static void
+fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  int s, hint;
+  unsigned char *edirectory;
+  unsigned char *eaddresses;
+  unsigned char *enameptrs;
+  unsigned char *eordinals;
+  char *enamestr;
+  time_t now;
+
+  time (&now);
+
+  edata_d = xmalloc (edata_sz);
+
+  /* Note use of array pointer math here.  */
+  edirectory = edata_d;
+  eaddresses = edata_d + 40;
+  enameptrs = eaddresses + 4 * export_table_size;
+  eordinals = enameptrs + 4 * count_exported_byname;
+  enamestr = (char *) eordinals + 2 * count_exported_byname;
+
+#define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) \
+		   + edata_s->output_section->vma - image_base)
+
+  memset (edata_d, 0, edata_sz);
+  bfd_put_32 (abfd, now, edata_d + 4);
+  if (pep_def_file->version_major != -1)
+    {
+      bfd_put_16 (abfd, pep_def_file->version_major, edata_d + 8);
+      bfd_put_16 (abfd, pep_def_file->version_minor, edata_d + 10);
+    }
+
+  bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12);
+  strcpy (enamestr, dll_name);
+  enamestr += strlen (enamestr) + 1;
+  bfd_put_32 (abfd, min_ordinal, edata_d + 16);
+  bfd_put_32 (abfd, export_table_size, edata_d + 20);
+  bfd_put_32 (abfd, count_exported_byname, edata_d + 24);
+  bfd_put_32 (abfd, ERVA (eaddresses), edata_d + 28);
+  bfd_put_32 (abfd, ERVA (enameptrs), edata_d + 32);
+  bfd_put_32 (abfd, ERVA (eordinals), edata_d + 36);
+
+  fill_exported_offsets (abfd, info);
+
+  /* Ok, now for the filling in part.
+     Scan alphabetically - ie the ordering in the exports[] table,
+     rather than by ordinal - the ordering in the exported_symbol[]
+     table.  See dlltool.c and:
+        http://sources.redhat.com/ml/binutils/2003-04/msg00379.html
+     for more information.  */
+  hint = 0;
+  for (s = 0; s < NE; s++)
+    {
+      struct bfd_section *ssec = exported_symbol_sections[s];
+      if (pep_def_file->exports[s].ordinal != -1 &&
+          (pep_def_file->exports[s].flag_forward || ssec != NULL))
+	{
+	  int ord = pep_def_file->exports[s].ordinal;
+
+	  if (pep_def_file->exports[s].flag_forward)
+	    {
+	      bfd_put_32 (abfd, ERVA (enamestr),
+		          eaddresses + 4 * (ord - min_ordinal));
+
+	      strcpy (enamestr, pep_def_file->exports[s].internal_name);
+	      enamestr += strlen (pep_def_file->exports[s].internal_name) + 1;
+	    }
+	  else
+	    {
+	      unsigned long srva = (exported_symbol_offsets[s]
+				    + ssec->output_section->vma
+				    + ssec->output_offset);
+
+	      bfd_put_32 (abfd, srva - image_base,
+		          eaddresses + 4 * (ord - min_ordinal));
+	    }
+
+	  if (!pep_def_file->exports[s].flag_noname)
+	    {
+	      char *ename = pep_def_file->exports[s].name;
+
+	      bfd_put_32 (abfd, ERVA (enamestr), enameptrs);
+	      enameptrs += 4;
+	      strcpy (enamestr, ename);
+	      enamestr += strlen (enamestr) + 1;
+	      bfd_put_16 (abfd, ord - min_ordinal, eordinals);
+	      eordinals += 2;
+	      pep_def_file->exports[s].hint = hint++;
+	    }
+	}
+    }
+}
+
+
+static struct bfd_section *current_sec;
+
+void
+pep_walk_relocs_of_symbol (struct bfd_link_info *info,
+			  const char *name,
+			  int (*cb) (arelent *, asection *))
+{
+  bfd *b;
+  asection *s;
+
+  for (b = info->input_bfds; b; b = b->link_next)
+    {
+      asymbol **symbols;
+      int nsyms, symsize;
+
+      symsize = bfd_get_symtab_upper_bound (b);
+      symbols = xmalloc (symsize);
+      nsyms   = bfd_canonicalize_symtab (b, symbols);
+
+      for (s = b->sections; s; s = s->next)
+	{
+	  arelent **relocs;
+	  int relsize, nrelocs, i;
+	  int flags = bfd_get_section_flags (b, s);
+
+	  /* Skip discarded linkonce sections.  */
+	  if (flags & SEC_LINK_ONCE
+	      && s->output_section == bfd_abs_section_ptr)
+	    continue;
+
+	  current_sec = s;
+
+	  relsize = bfd_get_reloc_upper_bound (b, s);
+	  relocs = xmalloc (relsize);
+	  nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
+
+	  for (i = 0; i < nrelocs; i++)
+	    {
+	      struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
+
+	      if (!strcmp (name, sym->name))
+		cb (relocs[i], s);
+	    }
+
+	  free (relocs);
+
+	  /* Warning: the allocated symbols are remembered in BFD and reused
+	     later, so don't free them! */
+	  /* free (symbols); */
+	}
+    }
+}
+
+/* Gather all the relocations and build the .reloc section.  */
+
+static void
+generate_reloc (bfd *abfd, struct bfd_link_info *info)
+{
+
+  /* For .reloc stuff.  */
+  reloc_data_type *reloc_data;
+  int total_relocs = 0;
+  int i;
+  unsigned long sec_page = (unsigned long) -1;
+  unsigned long page_ptr, page_count;
+  int bi;
+  bfd *b;
+  struct bfd_section *s;
+
+  total_relocs = 0;
+  for (b = info->input_bfds; b; b = b->link_next)
+    for (s = b->sections; s; s = s->next)
+      total_relocs += s->reloc_count;
+
+  reloc_data = xmalloc (total_relocs * sizeof (reloc_data_type));
+
+  total_relocs = 0;
+  bi = 0;
+  for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next)
+    {
+      arelent **relocs;
+      int relsize, nrelocs, i;
+
+      for (s = b->sections; s; s = s->next)
+	{
+	  unsigned long sec_vma = s->output_section->vma + s->output_offset;
+	  asymbol **symbols;
+	  int nsyms, symsize;
+
+	  /* If it's not loaded, we don't need to relocate it this way.  */
+	  if (!(s->output_section->flags & SEC_LOAD))
+	    continue;
+
+	  /* I don't know why there would be a reloc for these, but I've
+	     seen it happen - DJ  */
+	  if (s->output_section == &bfd_abs_section)
+	    continue;
+
+	  if (s->output_section->vma == 0)
+	    {
+	      /* Huh?  Shouldn't happen, but punt if it does.  */
+	      einfo ("DJ: zero vma section reloc detected: `%s' #%d f=%d\n",
+		     s->output_section->name, s->output_section->index,
+		     s->output_section->flags);
+	      continue;
+	    }
+
+	  symsize = bfd_get_symtab_upper_bound (b);
+	  symbols = xmalloc (symsize);
+	  nsyms = bfd_canonicalize_symtab (b, symbols);
+
+	  relsize = bfd_get_reloc_upper_bound (b, s);
+	  relocs = xmalloc (relsize);
+	  nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
+
+	  for (i = 0; i < nrelocs; i++)
+	    {
+	      if (pep_dll_extra_pe_debug)
+		{
+		  struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
+		  printf ("rel: %s\n", sym->name);
+		}
+	      if (!relocs[i]->howto->pc_relative
+		  && relocs[i]->howto->type != pep_details->imagebase_reloc)
+		{
+		  bfd_vma sym_vma;
+		  struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
+
+		  sym_vma = (relocs[i]->addend
+			     + sym->value
+			     + sym->section->vma
+			     + sym->section->output_offset
+			     + sym->section->output_section->vma);
+		  reloc_data[total_relocs].vma = sec_vma + relocs[i]->address;
+
+#define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift)
+
+		  switch BITS_AND_SHIFT (relocs[i]->howto->bitsize,
+					 relocs[i]->howto->rightshift)
+		    {
+		    case BITS_AND_SHIFT (32, 0):
+		      reloc_data[total_relocs].type = 3;
+		      total_relocs++;
+		      break;
+		    case BITS_AND_SHIFT (16, 0):
+		      reloc_data[total_relocs].type = 2;
+		      total_relocs++;
+		      break;
+		    case BITS_AND_SHIFT (16, 16):
+		      reloc_data[total_relocs].type = 4;
+		      /* FIXME: we can't know the symbol's right value
+			 yet, but we probably can safely assume that
+			 CE will relocate us in 64k blocks, so leaving
+			 it zero is safe.  */
+		      reloc_data[total_relocs].extra = 0;
+		      total_relocs++;
+		      break;
+		    case BITS_AND_SHIFT (26, 2):
+		      reloc_data[total_relocs].type = 5;
+		      total_relocs++;
+		      break;
+		    case BITS_AND_SHIFT (24, 2):
+		      /* FIXME: 0 is ARM_26D, it is defined in bfd/coff-arm.c
+			 Those ARM_xxx definitions should go in proper
+			 header someday.  */
+		      if (relocs[i]->howto->type == 0
+			  /* Older GNU linkers used 5 instead of 0 for this reloc.  */
+			  || relocs[i]->howto->type == 5)
+			/* This is an ARM_26D reloc, which is an ARM_26 reloc
+			   that has already been fully processed during a
+			   previous link stage, so ignore it here.  */
+			break;
+		      /* Fall through.  */
+		    default:
+		      /* xgettext:c-format */
+		      einfo (_("%XError: %d-bit reloc in dll\n"),
+			     relocs[i]->howto->bitsize);
+		      break;
+		    }
+		}
+	    }
+	  free (relocs);
+	  /* Warning: the allocated symbols are remembered in BFD and
+	     reused later, so don't free them!  */
+	}
+    }
+
+  /* At this point, we have total_relocs relocation addresses in
+     reloc_addresses, which are all suitable for the .reloc section.
+     We must now create the new sections.  */
+  qsort (reloc_data, total_relocs, sizeof (*reloc_data), reloc_sort);
+
+  for (i = 0; i < total_relocs; i++)
+    {
+      unsigned long this_page = (reloc_data[i].vma >> 12);
+
+      if (this_page != sec_page)
+	{
+	  reloc_sz = (reloc_sz + 3) & ~3;	/* 4-byte align.  */
+	  reloc_sz += 8;
+	  sec_page = this_page;
+	}
+
+      reloc_sz += 2;
+
+      if (reloc_data[i].type == 4)
+	reloc_sz += 2;
+    }
+
+  reloc_sz = (reloc_sz + 3) & ~3;	/* 4-byte align.  */
+  reloc_d = xmalloc (reloc_sz);
+  sec_page = (unsigned long) -1;
+  reloc_sz = 0;
+  page_ptr = (unsigned long) -1;
+  page_count = 0;
+
+  for (i = 0; i < total_relocs; i++)
+    {
+      unsigned long rva = reloc_data[i].vma - image_base;
+      unsigned long this_page = (rva & ~0xfff);
+
+      if (this_page != sec_page)
+	{
+	  while (reloc_sz & 3)
+	    reloc_d[reloc_sz++] = 0;
+
+	  if (page_ptr != (unsigned long) -1)
+	    bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
+
+	  bfd_put_32 (abfd, this_page, reloc_d + reloc_sz);
+	  page_ptr = reloc_sz;
+	  reloc_sz += 8;
+	  sec_page = this_page;
+	  page_count = 0;
+	}
+
+      bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12),
+		  reloc_d + reloc_sz);
+      reloc_sz += 2;
+
+      if (reloc_data[i].type == 4)
+	{
+	  bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);
+	  reloc_sz += 2;
+	}
+
+      page_count++;
+    }
+
+  while (reloc_sz & 3)
+    reloc_d[reloc_sz++] = 0;
+
+  if (page_ptr != (unsigned long) -1)
+    bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
+
+  while (reloc_sz < reloc_s->size)
+    reloc_d[reloc_sz++] = 0;
+}
+
+/* Given the exiting def_file structure, print out a .DEF file that
+   corresponds to it.  */
+
+static void
+quoteput (char *s, FILE *f, int needs_quotes)
+{
+  char *cp;
+
+  for (cp = s; *cp; cp++)
+    if (*cp == '\''
+	|| *cp == '"'
+	|| *cp == '\\'
+	|| ISSPACE (*cp)
+	|| *cp == ','
+	|| *cp == ';')
+      needs_quotes = 1;
+
+  if (needs_quotes)
+    {
+      putc ('"', f);
+
+      while (*s)
+	{
+	  if (*s == '"' || *s == '\\')
+	    putc ('\\', f);
+
+	  putc (*s, f);
+	  s++;
+	}
+
+      putc ('"', f);
+    }
+  else
+    fputs (s, f);
+}
+
+void
+pep_dll_generate_def_file (const char *pep_out_def_filename)
+{
+  int i;
+  FILE *out = fopen (pep_out_def_filename, "w");
+
+  if (out == NULL)
+    /* xgettext:c-format */
+    einfo (_("%s: Can't open output def file %s\n"),
+	   program_name, pep_out_def_filename);
+
+  if (pep_def_file)
+    {
+      if (pep_def_file->name)
+	{
+	  if (pep_def_file->is_dll)
+	    fprintf (out, "LIBRARY ");
+	  else
+	    fprintf (out, "NAME ");
+
+	  quoteput (pep_def_file->name, out, 1);
+
+	  if (pe_data (output_bfd)->pe_opthdr.ImageBase)
+	    fprintf (out, " BASE=0x%lx",
+		     (unsigned long) pe_data (output_bfd)->pe_opthdr.ImageBase);
+	  fprintf (out, "\n");
+	}
+
+      if (pep_def_file->description)
+	{
+	  fprintf (out, "DESCRIPTION ");
+	  quoteput (pep_def_file->description, out, 1);
+	  fprintf (out, "\n");
+	}
+
+      if (pep_def_file->version_minor != -1)
+	fprintf (out, "VERSION %d.%d\n", pep_def_file->version_major,
+		 pep_def_file->version_minor);
+      else if (pep_def_file->version_major != -1)
+	fprintf (out, "VERSION %d\n", pep_def_file->version_major);
+
+      if (pep_def_file->stack_reserve != -1 || pep_def_file->heap_reserve != -1)
+	fprintf (out, "\n");
+
+      if (pep_def_file->stack_commit != -1)
+	fprintf (out, "STACKSIZE 0x%x,0x%x\n",
+		 pep_def_file->stack_reserve, pep_def_file->stack_commit);
+      else if (pep_def_file->stack_reserve != -1)
+	fprintf (out, "STACKSIZE 0x%x\n", pep_def_file->stack_reserve);
+
+      if (pep_def_file->heap_commit != -1)
+	fprintf (out, "HEAPSIZE 0x%x,0x%x\n",
+		 pep_def_file->heap_reserve, pep_def_file->heap_commit);
+      else if (pep_def_file->heap_reserve != -1)
+	fprintf (out, "HEAPSIZE 0x%x\n", pep_def_file->heap_reserve);
+
+      if (pep_def_file->num_section_defs > 0)
+	{
+	  fprintf (out, "\nSECTIONS\n\n");
+
+	  for (i = 0; i < pep_def_file->num_section_defs; i++)
+	    {
+	      fprintf (out, "    ");
+	      quoteput (pep_def_file->section_defs[i].name, out, 0);
+
+	      if (pep_def_file->section_defs[i].class)
+		{
+		  fprintf (out, " CLASS ");
+		  quoteput (pep_def_file->section_defs[i].class, out, 0);
+		}
+
+	      if (pep_def_file->section_defs[i].flag_read)
+		fprintf (out, " READ");
+
+	      if (pep_def_file->section_defs[i].flag_write)
+		fprintf (out, " WRITE");
+
+	      if (pep_def_file->section_defs[i].flag_execute)
+		fprintf (out, " EXECUTE");
+
+	      if (pep_def_file->section_defs[i].flag_shared)
+		fprintf (out, " SHARED");
+
+	      fprintf (out, "\n");
+	    }
+	}
+
+      if (pep_def_file->num_exports > 0)
+	{
+	  fprintf (out, "EXPORTS\n");
+
+	  for (i = 0; i < pep_def_file->num_exports; i++)
+	    {
+	      def_file_export *e = pep_def_file->exports + i;
+	      fprintf (out, "    ");
+	      quoteput (e->name, out, 0);
+
+	      if (e->internal_name && strcmp (e->internal_name, e->name))
+		{
+		  fprintf (out, " = ");
+		  quoteput (e->internal_name, out, 0);
+		}
+
+	      if (e->ordinal != -1)
+		fprintf (out, " @%d", e->ordinal);
+
+	      if (e->flag_private)
+		fprintf (out, " PRIVATE");
+
+	      if (e->flag_constant)
+		fprintf (out, " CONSTANT");
+
+	      if (e->flag_noname)
+		fprintf (out, " NONAME");
+
+	      if (e->flag_data)
+		fprintf (out, " DATA");
+
+	      fprintf (out, "\n");
+	    }
+	}
+
+      if (pep_def_file->num_imports > 0)
+	{
+	  fprintf (out, "\nIMPORTS\n\n");
+
+	  for (i = 0; i < pep_def_file->num_imports; i++)
+	    {
+	      def_file_import *im = pep_def_file->imports + i;
+	      fprintf (out, "    ");
+
+	      if (im->internal_name
+		  && (!im->name || strcmp (im->internal_name, im->name)))
+		{
+		  quoteput (im->internal_name, out, 0);
+		  fprintf (out, " = ");
+		}
+
+	      quoteput (im->module->name, out, 0);
+	      fprintf (out, ".");
+
+	      if (im->name)
+		quoteput (im->name, out, 0);
+	      else
+		fprintf (out, "%d", im->ordinal);
+
+	      fprintf (out, "\n");
+	    }
+	}
+    }
+  else
+    fprintf (out, _("; no contents available\n"));
+
+  if (fclose (out) == EOF)
+    /* xgettext:c-format */
+    einfo (_("%P: Error closing file `%s'\n"), pep_out_def_filename);
+}
+
+/* Generate the import library.  */
+
+static asymbol **symtab;
+static int symptr;
+static int tmp_seq;
+static const char *dll_filename;
+static char *dll_symname;
+
+#define UNDSEC (asection *) &bfd_und_section
+
+static asection *
+quick_section (bfd *abfd, const char *name, int flags, int align)
+{
+  asection *sec;
+  asymbol *sym;
+
+  sec = bfd_make_section_old_way (abfd, name);
+  bfd_set_section_flags (abfd, sec, flags | SEC_ALLOC | SEC_LOAD | SEC_KEEP);
+  bfd_set_section_alignment (abfd, sec, align);
+  /* Remember to undo this before trying to link internally!  */
+  sec->output_section = sec;
+
+  sym = bfd_make_empty_symbol (abfd);
+  symtab[symptr++] = sym;
+  sym->name = sec->name;
+  sym->section = sec;
+  sym->flags = BSF_LOCAL;
+  sym->value = 0;
+
+  return sec;
+}
+
+static void
+quick_symbol (bfd *abfd,
+	      const char *n1,
+	      const char *n2,
+	      const char *n3,
+	      asection *sec,
+	      int flags,
+	      int addr)
+{
+  asymbol *sym;
+  char *name = xmalloc (strlen (n1) + strlen (n2) + strlen (n3) + 1);
+
+  strcpy (name, n1);
+  strcat (name, n2);
+  strcat (name, n3);
+  printf("*** Quick Sym:%s sec:%p addr:%d\n",name,sec,addr);
+  sym = bfd_make_empty_symbol (abfd);
+  sym->name = name;
+  sym->section = sec;
+  sym->flags = flags;
+  sym->value = addr;
+  symtab[symptr++] = sym;
+}
+
+static arelent *reltab = 0;
+static int relcount = 0, relsize = 0;
+
+static void
+quick_reloc (bfd *abfd, int address, int which_howto, int symidx)
+{
+  if (relcount >= relsize - 1)
+    {
+      relsize += 10;
+      if (reltab)
+	reltab = xrealloc (reltab, relsize * sizeof (arelent));
+      else
+	reltab = xmalloc (relsize * sizeof (arelent));
+    }
+  reltab[relcount].address = address;
+  reltab[relcount].addend = 0;
+  reltab[relcount].howto = bfd_reloc_type_lookup (abfd, which_howto);
+  reltab[relcount].sym_ptr_ptr = symtab + symidx;
+  relcount++;
+}
+
+static void
+save_relocs (asection *sec)
+{
+  int i;
+
+  sec->relocation = reltab;
+  sec->reloc_count = relcount;
+  sec->orelocation = xmalloc ((relcount + 1) * sizeof (arelent *));
+  for (i = 0; i < relcount; i++)
+    sec->orelocation[i] = sec->relocation + i;
+  sec->orelocation[relcount] = 0;
+  sec->flags |= SEC_RELOC;
+  reltab = 0;
+  relcount = relsize = 0;
+}
+
+/*	.section	.idata$2
+ 	.global		__head_my_dll
+   __head_my_dll:
+ 	.rva		hname
+ 	.long		0
+ 	.long		0
+ 	.rva		__my_dll_iname
+ 	.rva		fthunk
+
+ 	.section	.idata$5
+ 	.long		0
+ 	.long		0
+   fthunk:
+
+ 	.section	.idata$4
+ 	.long		0
+ 	.long		0
+   hname:                              */
+
+static bfd *
+make_head (bfd *parent)
+{
+  asection *id2, *id5, *id4;
+  unsigned char *d2, *d5, *d4;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "d%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (6 * sizeof (asymbol *));
+  id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2);
+  id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
+  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
+  quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0);
+  quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
+
+  /* OK, pay attention here.  I got confused myself looking back at
+     it.  We create a four-byte section to mark the beginning of the
+     list, and we include an offset of 4 in the section, so that the
+     pointer to the list points to the *end* of this section, which is
+     the start of the list of sections from other objects.  */
+
+  bfd_set_section_size (abfd, id2, 20);
+  d2 = xmalloc (20);
+  id2->contents = d2;
+  memset (d2, 0, 20);
+  d2[0] = d2[16] = 4; /* Reloc addend.  */
+  quick_reloc (abfd,  0, BFD_RELOC_RVA, 2);
+  quick_reloc (abfd, 12, BFD_RELOC_RVA, 4);
+  quick_reloc (abfd, 16, BFD_RELOC_RVA, 1);
+  save_relocs (id2);
+
+  bfd_set_section_size (abfd, id5, 8);
+  d5 = xmalloc (8);
+  id5->contents = d5;
+  memset (d5, 0, 8);
+
+  bfd_set_section_size (abfd, id4, 8);
+  d4 = xmalloc (8);
+  id4->contents = d4;
+  memset (d4, 0, 8);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, id2, d2, 0, 20);
+  bfd_set_section_contents (abfd, id5, d5, 0, 8);
+  bfd_set_section_contents (abfd, id4, d4, 0, 8);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+/*	.section	.idata$4
+ 	.long		0
+  	.long		0
+	.section	.idata$5
+ 	.long		0
+ 	.long		0
+ 	.section	idata$7
+ 	.global		__my_dll_iname
+  __my_dll_iname:
+ 	.asciz		"my.dll"       */
+
+static bfd *
+make_tail (bfd *parent)
+{
+  asection *id4, *id5, *id7;
+  unsigned char *d4, *d5, *d7;
+  int len;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "d%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (5 * sizeof (asymbol *));
+  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
+  id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
+  id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
+  quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0);
+
+  bfd_set_section_size (abfd, id4, 8);
+  d4 = xmalloc (8);
+  id4->contents = d4;
+  memset (d4, 0, 8);
+
+  bfd_set_section_size (abfd, id5, 8);
+  d5 = xmalloc (8);
+  id5->contents = d5;
+  memset (d5, 0, 8);
+
+  len = strlen (dll_filename) + 1;
+  if (len & 1)
+    len++;
+  bfd_set_section_size (abfd, id7, len);
+  d7 = xmalloc (len);
+  id7->contents = d7;
+  strcpy ((char *) d7, dll_filename);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, id4, d4, 0, 8);
+  bfd_set_section_contents (abfd, id5, d5, 0, 8);
+  bfd_set_section_contents (abfd, id7, d7, 0, len);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+/*	.text
+ 	.global		_function
+ 	.global		___imp_function
+ 	.global		__imp__function
+  _function:
+ 	jmp		*__imp__function:
+
+ 	.section	idata$7
+ 	.long		__head_my_dll
+
+ 	.section	.idata$5
+  ___imp_function:
+  __imp__function:
+  iat?
+  	.section	.idata$4
+  iat?
+ 	.section	.idata$6
+  ID<ordinal>:
+ 	.short		<hint>
+ 	.asciz		"function" xlate? (add underscore, kill at)  */
+
+static unsigned char jmp_ix86_bytes[] =
+{
+  0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
+};
+
+static bfd *
+make_one (def_file_export *exp, bfd *parent)
+{
+  asection *tx, *id7, *id5, *id4, *id6;
+  unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL;
+  int len;
+  char *oname;
+  bfd *abfd;
+  unsigned char *jmp_bytes = NULL;
+  int jmp_byte_count = 0;
+
+  switch (pep_details->pep_arch)
+    {
+    case PE_ARCH_i386:
+      jmp_bytes = jmp_ix86_bytes;
+      jmp_byte_count = sizeof (jmp_ix86_bytes);
+      break;
+    default:
+      abort ();
+    }
+
+  oname = xmalloc (20);
+  sprintf (oname, "d%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (11 * sizeof (asymbol *));
+  tx  = quick_section (abfd, ".text",    SEC_CODE|SEC_HAS_CONTENTS, 2);
+  id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
+  id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
+  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
+  id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2);
+
+  if  (*exp->internal_name == '@')
+    {
+      quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
+		    BSF_GLOBAL, 0);
+      if (! exp->flag_data)
+	quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0);
+      quick_symbol (abfd, U ("_imp_"), exp->internal_name, "", id5,
+		    BSF_GLOBAL, 0);
+      /* Fastcall applies only to functions,
+	 so no need for auto-import symbol.  */
+    }
+  else
+    {
+      quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
+		    BSF_GLOBAL, 0);
+      if (! exp->flag_data)
+	quick_symbol (abfd, U (""), exp->internal_name, "", tx,
+		      BSF_GLOBAL, 0);
+      quick_symbol (abfd, U ("_imp__"), exp->internal_name, "", id5,
+		    BSF_GLOBAL, 0);
+      /* Symbol to reference ord/name of imported
+	 data symbol, used to implement auto-import.  */
+      if (exp->flag_data)
+	quick_symbol (abfd, U("_nm__"), exp->internal_name, "", id6,
+		      BSF_GLOBAL,0);
+    }
+  if (pep_dll_compat_implib)
+    quick_symbol (abfd, U ("__imp_"), exp->internal_name, "", id5,
+		  BSF_GLOBAL, 0);
+    //quick_symbol (abfd, U ("_imp"), exp->internal_name, "", id5,
+	//	  BSF_GLOBAL, 0); $$$$
+
+  if (! exp->flag_data)
+    {
+      bfd_set_section_size (abfd, tx, jmp_byte_count);
+      td = xmalloc (jmp_byte_count);
+      tx->contents = td;
+      memcpy (td, jmp_bytes, jmp_byte_count);
+
+      switch (pep_details->pep_arch)
+	{
+	case PE_ARCH_i386:
+	  quick_reloc (abfd, 2, BFD_RELOC_32, 2);
+	  break;
+	case PE_ARCH_sh:
+	  quick_reloc (abfd, 8, BFD_RELOC_32, 2);
+	  break;
+	case PE_ARCH_mips:
+	  quick_reloc (abfd, 0, BFD_RELOC_HI16_S, 2);
+	  quick_reloc (abfd, 0, BFD_RELOC_LO16, 0); /* MIPS_R_PAIR */
+	  quick_reloc (abfd, 4, BFD_RELOC_LO16, 2);
+	  break;
+	default:
+	  abort ();
+	}
+      save_relocs (tx);
+    }
+
+  bfd_set_section_size (abfd, id7, 4);
+  d7 = xmalloc (4);
+  id7->contents = d7;
+  memset (d7, 0, 4);
+  quick_reloc (abfd, 0, BFD_RELOC_RVA, 5);
+  save_relocs (id7);
+
+  bfd_set_section_size (abfd, id5, 8);
+  d5 = xmalloc (8);
+  id5->contents = d5;
+  memset (d5, 0, 8);
+
+  if (exp->flag_noname)
+    {
+      d5[0] = exp->ordinal;
+      d5[1] = exp->ordinal >> 8;
+      d5[7] = 0x80;
+    }
+  else
+    {
+      quick_reloc (abfd, 0, BFD_RELOC_RVA, 4);
+      save_relocs (id5);
+    }
+
+  bfd_set_section_size (abfd, id4, 8);
+  d4 = xmalloc (8);
+  id4->contents = d4;
+  memset (d4, 0, 8);
+
+  if (exp->flag_noname)
+    {
+      d4[0] = exp->ordinal;
+      d4[1] = exp->ordinal >> 8;
+      d4[7] = 0x80;
+    }
+  else
+    {
+      quick_reloc (abfd, 0, BFD_RELOC_RVA, 4);
+      save_relocs (id4);
+    }
+
+  if (exp->flag_noname)
+    {
+      len = 0;
+      bfd_set_section_size (abfd, id6, 0);
+    }
+  else
+    {
+      len = strlen (exp->name) + 3;
+      if (len & 1)
+	len++;
+      bfd_set_section_size (abfd, id6, len);
+      d6 = xmalloc (len);
+      id6->contents = d6;
+      memset (d6, 0, len);
+      d6[0] = exp->hint & 0xff;
+      d6[1] = exp->hint >> 8;
+      strcpy ((char *) d6 + 2, exp->name);
+    }
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count);
+  bfd_set_section_contents (abfd, id7, d7, 0, 4);
+  bfd_set_section_contents (abfd, id5, d5, 0, 8);
+  bfd_set_section_contents (abfd, id4, d4, 0, 8);
+  if (!exp->flag_noname)
+    bfd_set_section_contents (abfd, id6, d6, 0, len);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+static bfd *
+make_singleton_name_thunk (const char *import, bfd *parent)
+{
+  /* Name thunks go to idata$4.  */
+  asection *id4;
+  unsigned char *d4;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "nmth%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (3 * sizeof (asymbol *));
+  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
+  quick_symbol (abfd, U ("_nm_thnk_"), import, "", id4, BSF_GLOBAL, 0);
+  quick_symbol (abfd, U ("_nm_"), import, "", UNDSEC, BSF_GLOBAL, 0);
+
+  bfd_set_section_size (abfd, id4, 8);
+  d4 = xmalloc (8);
+  id4->contents = d4;
+  memset (d4, 0, 8);
+  quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);
+  save_relocs (id4);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, id4, d4, 0, 8);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+static char *
+make_import_fixup_mark (arelent *rel)
+{
+  /* We convert reloc to symbol, for later reference.  */
+  static int counter;
+  static char *fixup_name = NULL;
+  static size_t buffer_len = 0;
+
+  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
+
+  bfd *abfd = bfd_asymbol_bfd (sym);
+  struct bfd_link_hash_entry *bh;
+
+  if (!fixup_name)
+    {
+      fixup_name = xmalloc (384);
+      buffer_len = 384;
+    }
+
+  if (strlen (sym->name) + 25 > buffer_len)
+  /* Assume 25 chars for "__fu" + counter + "_".  If counter is
+     bigger than 20 digits long, we've got worse problems than
+     overflowing this buffer...  */
+    {
+      free (fixup_name);
+      /* New buffer size is length of symbol, plus 25, but
+	 then rounded up to the nearest multiple of 128.  */
+      buffer_len = ((strlen (sym->name) + 25) + 127) & ~127;
+      fixup_name = xmalloc (buffer_len);
+    }
+
+  sprintf (fixup_name, "__fu%d_%s", counter++, sym->name);
+
+  bh = NULL;
+  bfd_coff_link_add_one_symbol (&link_info, abfd, fixup_name, BSF_GLOBAL,
+				current_sec, /* sym->section, */
+				rel->address, NULL, TRUE, FALSE, &bh);
+
+  if (0)
+    {
+      struct coff_link_hash_entry *myh;
+
+      myh = (struct coff_link_hash_entry *) bh;
+      printf ("type:%d\n", myh->type);
+      printf ("%s\n", myh->root.u.def.section->name);
+    }
+
+  return fixup_name;
+}
+
+/*	.section	.idata$3
+  	.rva		__nm_thnk_SYM (singleton thunk with name of func)
+ 	.long		0
+ 	.long		0
+ 	.rva		__my_dll_iname (name of dll)
+ 	.rva		__fuNN_SYM (pointer to reference (address) in text)  */
+
+static bfd *
+make_import_fixup_entry (const char *name,
+			 const char *fixup_name,
+			 const char *dll_symname,
+			 bfd *parent)
+{
+  asection *id3;
+  unsigned char *d3;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "fu%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (6 * sizeof (asymbol *));
+  id3 = quick_section (abfd, ".idata$3", SEC_HAS_CONTENTS, 2);
+
+  quick_symbol (abfd, U ("_nm_thnk_"), name, "", UNDSEC, BSF_GLOBAL, 0);
+  quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
+  quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
+
+  bfd_set_section_size (abfd, id3, 20);
+  d3 = xmalloc (20);
+  id3->contents = d3;
+  memset (d3, 0, 20);
+
+  quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
+  quick_reloc (abfd, 12, BFD_RELOC_RVA, 2);
+  quick_reloc (abfd, 16, BFD_RELOC_RVA, 3);
+  save_relocs (id3);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, id3, d3, 0, 20);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+/*	.section	.rdata_runtime_pseudo_reloc
+ 	.long		addend
+ 	.rva		__fuNN_SYM (pointer to reference (address) in text)  */
+
+static bfd *
+make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED,
+			   const char *fixup_name,
+			   int addend,
+			   bfd *parent)
+{
+  asection *rt_rel;
+  unsigned char *rt_rel_d;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "rtr%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (2 * sizeof (asymbol *));
+  rt_rel = quick_section (abfd, ".rdata_runtime_pseudo_reloc",
+			  SEC_HAS_CONTENTS, 2);
+
+  quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
+
+  bfd_set_section_size (abfd, rt_rel, 8);
+  rt_rel_d = xmalloc (8);
+  rt_rel->contents = rt_rel_d;
+  memset (rt_rel_d, 0, 8);
+  bfd_put_32 (abfd, addend, rt_rel_d);
+
+  quick_reloc (abfd, 4, BFD_RELOC_RVA, 1);
+  save_relocs (rt_rel);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, 8);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+/*	.section	.rdata
+ 	.rva		__pei386_runtime_relocator  */
+
+static bfd *
+pep_create_runtime_relocator_reference (bfd *parent)
+{
+  asection *extern_rt_rel;
+  unsigned char *extern_rt_rel_d;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "ertr%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (2 * sizeof (asymbol *));
+  extern_rt_rel = quick_section (abfd, ".rdata", SEC_HAS_CONTENTS, 2);
+
+  quick_symbol (abfd, "", "__pei386_runtime_relocator", "", UNDSEC,
+		BSF_NO_FLAGS, 0);
+
+  bfd_set_section_size (abfd, extern_rt_rel, 4);
+  extern_rt_rel_d = xmalloc (4);
+  extern_rt_rel->contents = extern_rt_rel_d;
+
+  quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
+  save_relocs (extern_rt_rel);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, extern_rt_rel, extern_rt_rel_d, 0, 4);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+void
+pep_create_import_fixup (arelent *rel, asection *s, int addend)
+{
+  char buf[300];
+  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
+  struct bfd_link_hash_entry *name_thunk_sym;
+  const char *name = sym->name;
+  char *fixup_name = make_import_fixup_mark (rel);
+  bfd *b;
+
+  sprintf (buf, U ("_nm_thnk_%s"), name);
+
+  name_thunk_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
+
+  if (!name_thunk_sym || name_thunk_sym->type != bfd_link_hash_defined)
+    {
+      bfd *b = make_singleton_name_thunk (name, output_bfd);
+      add_bfd_to_link (b, b->filename, &link_info);
+
+      /* If we ever use autoimport, we have to cast text section writable.  */
+      config.text_read_only = FALSE;
+      output_bfd->flags &= ~WP_TEXT;   
+    }
+
+  if (addend == 0 || link_info.pei386_runtime_pseudo_reloc)
+    {
+      extern char * pep_data_import_dll;
+      char * dll_symname = pep_data_import_dll ? pep_data_import_dll : "unknown";
+
+      b = make_import_fixup_entry (name, fixup_name, dll_symname, output_bfd);
+      add_bfd_to_link (b, b->filename, &link_info);
+    }
+
+  if (addend != 0)
+    {
+      if (link_info.pei386_runtime_pseudo_reloc)
+	{
+	  if (pep_dll_extra_pe_debug)
+	    printf ("creating runtime pseudo-reloc entry for %s (addend=%d)\n",
+		   fixup_name, addend);
+	  b = make_runtime_pseudo_reloc (name, fixup_name, addend, output_bfd);
+	  add_bfd_to_link (b, b->filename, &link_info);
+
+	  if (runtime_pseudo_relocs_created == 0)
+	    {
+	      b = pep_create_runtime_relocator_reference (output_bfd);
+	      add_bfd_to_link (b, b->filename, &link_info);
+	    }
+	  runtime_pseudo_relocs_created++;
+	}
+      else
+	{
+	  einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"),
+		 s->owner, s, rel->address, sym->name);
+	  einfo ("%X");
+	}
+    }
+}
+
+
+void
+pep_dll_generate_implib (def_file *def, const char *impfilename)
+{
+  int i;
+  bfd *ar_head;
+  bfd *ar_tail;
+  bfd *outarch;
+  bfd *head = 0;
+
+  dll_filename = (def->name) ? def->name : dll_name;
+  dll_symname = xstrdup (dll_filename);
+  for (i = 0; dll_symname[i]; i++)
+    if (!ISALNUM (dll_symname[i]))
+      dll_symname[i] = '_';
+
+  unlink_if_ordinary (impfilename);
+
+  outarch = bfd_openw (impfilename, 0);
+
+  if (!outarch)
+    {
+      /* xgettext:c-format */
+      einfo (_("%XCan't open .lib file: %s\n"), impfilename);
+      return;
+    }
+
+  /* xgettext:c-format */
+  info_msg (_("Creating library file: %s\n"), impfilename);
+ 
+  bfd_set_format (outarch, bfd_archive);
+  outarch->has_armap = 1;
+
+  /* Work out a reasonable size of things to put onto one line.  */
+  ar_head = make_head (outarch);
+
+  for (i = 0; i < def->num_exports; i++)
+    {
+      /* The import library doesn't know about the internal name.  */
+      char *internal = def->exports[i].internal_name;
+      bfd *n;
+
+      /* Don't add PRIVATE entries to import lib.  */ 	
+      if (pep_def_file->exports[i].flag_private)
+	continue;
+      def->exports[i].internal_name = def->exports[i].name;
+      n = make_one (def->exports + i, outarch);
+      n->next = head;
+      head = n;
+      def->exports[i].internal_name = internal;
+    }
+
+  ar_tail = make_tail (outarch);
+
+  if (ar_head == NULL || ar_tail == NULL)
+    return;
+
+  /* Now stick them all into the archive.  */
+  ar_head->next = head;
+  ar_tail->next = ar_head;
+  head = ar_tail;
+
+  if (! bfd_set_archive_head (outarch, head))
+    einfo ("%Xbfd_set_archive_head: %E\n");
+
+  if (! bfd_close (outarch))
+    einfo ("%Xbfd_close %s: %E\n", impfilename);
+
+  while (head != NULL)
+    {
+      bfd *n = head->next;
+      bfd_close (head);
+      head = n;
+    }
+}
+
+static void
+add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *link_info)
+{
+  lang_input_statement_type *fake_file;
+
+  fake_file = lang_add_input_file (name,
+				   lang_input_file_is_fake_enum,
+				   NULL);
+  fake_file->the_bfd = abfd;
+  ldlang_add_file (fake_file);
+
+  if (!bfd_link_add_symbols (abfd, link_info))
+    einfo ("%Xaddsym %s: %E\n", name);
+}
+
+void
+pep_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
+{
+  def_file_module *module;
+
+  pep_dll_id_target (bfd_get_target (output_bfd));
+
+  if (!pep_def_file)
+    return;
+
+  for (module = pep_def_file->modules; module; module = module->next)
+    {
+      int i, do_this_dll;
+
+      dll_filename = module->name;
+      dll_symname = xstrdup (module->name);
+      for (i = 0; dll_symname[i]; i++)
+	if (!ISALNUM (dll_symname[i]))
+	  dll_symname[i] = '_';
+
+      do_this_dll = 0;
+
+      for (i = 0; i < pep_def_file->num_imports; i++)
+	if (pep_def_file->imports[i].module == module)
+	  {
+	    def_file_export exp;
+	    struct bfd_link_hash_entry *blhe;
+	    int lead_at = (*pep_def_file->imports[i].internal_name == '@');
+	    /* See if we need this import.  */
+	    size_t len = strlen (pep_def_file->imports[i].internal_name);
+	    char *name = xmalloc (len + 2 + 6);
+
+ 	    if (lead_at)
+	      sprintf (name, "%s%s", "",
+		       pep_def_file->imports[i].internal_name);
+	    else
+	      sprintf (name, "%s%s",U (""),
+		       pep_def_file->imports[i].internal_name);
+
+	    blhe = bfd_link_hash_lookup (link_info->hash, name,
+					 FALSE, FALSE, FALSE);
+
+	    if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
+	      {
+		if (lead_at)
+		  sprintf (name, "%s%s", U ("_imp_"),
+			   pep_def_file->imports[i].internal_name);
+		else
+		  sprintf (name, "%s%s", U ("_imp__"),
+			   pep_def_file->imports[i].internal_name);
+
+		blhe = bfd_link_hash_lookup (link_info->hash, name,
+					     FALSE, FALSE, FALSE);
+	      }
+	    free (name);
+
+	    if (blhe && blhe->type == bfd_link_hash_undefined)
+	      {
+		bfd *one;
+		/* We do.  */
+		if (!do_this_dll)
+		  {
+		    bfd *ar_head = make_head (output_bfd);
+		    add_bfd_to_link (ar_head, ar_head->filename, link_info);
+		    do_this_dll = 1;
+		  }
+		exp.internal_name = pep_def_file->imports[i].internal_name;
+		exp.name = pep_def_file->imports[i].name;
+		exp.ordinal = pep_def_file->imports[i].ordinal;
+		exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
+		exp.flag_private = 0;
+		exp.flag_constant = 0;
+		exp.flag_data = pep_def_file->imports[i].data;
+		exp.flag_noname = exp.name ? 0 : 1;
+		one = make_one (&exp, output_bfd);
+		add_bfd_to_link (one, one->filename, link_info);
+	      }
+	  }
+      if (do_this_dll)
+	{
+	  bfd *ar_tail = make_tail (output_bfd);
+	  add_bfd_to_link (ar_tail, ar_tail->filename, link_info);
+	}
+
+      free (dll_symname);
+    }
+}
+
+/* We were handed a *.DLL file.  Parse it and turn it into a set of
+   IMPORTS directives in the def file.  Return TRUE if the file was
+   handled, FALSE if not.  */
+
+static unsigned int
+pep_get16 (bfd *abfd, int where)
+{
+  unsigned char b[2];
+
+  bfd_seek (abfd, (file_ptr) where, SEEK_SET);
+  bfd_bread (b, (bfd_size_type) 2, abfd);
+  return b[0] + (b[1] << 8);
+}
+
+static unsigned int
+pep_get32 (bfd *abfd, int where)
+{
+  unsigned char b[4];
+
+  bfd_seek (abfd, (file_ptr) where, SEEK_SET);
+  bfd_bread (b, (bfd_size_type) 4, abfd);
+  return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
+}
+
+static unsigned int
+pep_as32 (void *ptr)
+{
+  unsigned char *b = ptr;
+
+  return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
+}
+
+bfd_boolean
+pep_implied_import_dll (const char *filename)
+{
+  bfd *dll;
+  unsigned long pep_header_offset, opthdr_ofs, num_entries, i;
+  unsigned long export_rva, export_size, nsections, secptr, expptr;
+  unsigned long exp_funcbase;
+  unsigned char *expdata;
+  char *erva;
+  unsigned long name_rvas, ordinals, nexp, ordbase;
+  const char *dll_name;
+  /* Initialization with start > end guarantees that is_data
+     will not be set by mistake, and avoids compiler warning.  */
+  unsigned long data_start = 1;
+  unsigned long data_end = 0;
+  unsigned long rdata_start = 1;
+  unsigned long rdata_end = 0;
+  unsigned long bss_start = 1;
+  unsigned long bss_end = 0;
+
+  /* No, I can't use bfd here.  kernel32.dll puts its export table in
+     the middle of the .rdata section.  */
+  dll = bfd_openr (filename, pep_details->target_name);
+  if (!dll)
+    {
+      einfo ("%Xopen %s: %E\n", filename);
+      return FALSE;
+    }
+
+  /* PEI dlls seem to be bfd_objects.  */
+  if (!bfd_check_format (dll, bfd_object))
+    {
+      einfo ("%X%s: this doesn't appear to be a DLL\n", filename);
+      return FALSE;
+    }
+
+  /* Get pe_header, optional header and numbers of export entries.  */
+  pep_header_offset = pep_get32 (dll, 0x3c);
+  opthdr_ofs = pep_header_offset + 4 + 20; // Magic of opt header
+  num_entries = pep_get32 (dll, opthdr_ofs + 92 +4*4); //  &NumberOfRvaAndSizes
+
+  if (pep_dll_extra_pe_debug)
+	  printf ("%s: Export num_entries %ld\n", __FUNCTION__,num_entries);
+
+  if (num_entries < 1) /* No exports.  */
+    return FALSE;
+
+  export_rva = pep_get32 (dll, opthdr_ofs + 96+4*4);
+  export_size = pep_get32 (dll, opthdr_ofs + 100+4*4);
+  nsections = pep_get16 (dll, pep_header_offset + 4 + 2);
+  secptr = (pep_header_offset + 4 + 20 +
+	    pep_get16 (dll, pep_header_offset + 4 + 16));
+  expptr = 0;
+
+  /* Get the rva and size of the export section.  */
+  for (i = 0; i < nsections; i++)
+    {
+      char sname[8];
+      unsigned long secptr1 = secptr + 40 * i;
+      unsigned long vaddr = pep_get32 (dll, secptr1 + 12);
+      unsigned long vsize = pep_get32 (dll, secptr1 + 16);
+      unsigned long fptr = pep_get32 (dll, secptr1 + 20);
+
+      bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
+      bfd_bread (sname, (bfd_size_type) 8, dll);
+
+      if (vaddr <= export_rva && vaddr + vsize > export_rva)
+	{
+	  expptr = fptr + (export_rva - vaddr);
+	  if (export_rva + export_size > vaddr + vsize)
+	    export_size = vsize - (export_rva - vaddr);
+	  break;
+	}
+    }
+
+  /* Scan sections and store the base and size of the
+     data and bss segments in data/base_start/end.  */
+  for (i = 0; i < nsections; i++)
+    {
+      unsigned long secptr1 = secptr + 40 * i;
+      unsigned long vsize = pep_get32 (dll, secptr1 + 8);
+      unsigned long vaddr = pep_get32 (dll, secptr1 + 12);
+      unsigned long flags = pep_get32 (dll, secptr1 + 36);
+      char sec_name[9];
+
+      sec_name[8] = '\0';
+      bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
+      bfd_bread (sec_name, (bfd_size_type) 8, dll);
+
+      if (strcmp(sec_name,".data") == 0)
+	{
+	  data_start = vaddr;
+	  data_end = vaddr + vsize;
+
+	  if (pep_dll_extra_pe_debug)
+	    printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
+		    __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
+	}
+      else if (strcmp(sec_name,".rdata") == 0)
+	{
+	  rdata_start = vaddr;
+	  rdata_end = vaddr + vsize;
+
+	  if (pep_dll_extra_pe_debug)
+	    printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
+		    __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
+	}
+      else if (strcmp (sec_name,".bss") == 0)
+	{
+	  bss_start = vaddr;
+	  bss_end = vaddr + vsize;
+
+	  if (pep_dll_extra_pe_debug)
+	    printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
+		    __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
+	}
+    }
+
+  if (pep_dll_extra_pe_debug)
+	  printf ("%s: Export size:%lu offset:0x%lx\n",
+		__FUNCTION__,export_size,(file_ptr)expptr);
+  expdata = xmalloc (export_size);
+  bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
+  bfd_bread (expdata, (bfd_size_type) export_size, dll);
+  erva = (char *) expdata - export_rva;
+
+  if (pep_def_file == 0)
+    pep_def_file = def_file_empty ();
+
+  nexp = pep_as32 (expdata + 24);
+  name_rvas = pep_as32 (expdata + 32);
+  ordinals = pep_as32 (expdata + 36);
+  ordbase = pep_as32 (expdata + 16);
+  exp_funcbase = pep_as32 (expdata + 28);
+  if (pep_dll_extra_pe_debug)
+	  printf ("%s: nexp:%lu namerva:0x%lx ord:%lu ordbase:%lu fb=0x%lx\n",
+	    __FUNCTION__,nexp,name_rvas,ordinals,ordbase,exp_funcbase);
+
+  /* Use internal dll name instead of filename
+     to enable symbolic dll linking.  */
+  dll_name = erva + pep_as32 (expdata + 12);
+
+  /* Check to see if the dll has already been added to
+     the definition list and if so return without error.
+     This avoids multiple symbol definitions.  */
+  if (def_get_module (pep_def_file, dll_name))
+    {
+      if (pep_dll_extra_pe_debug)
+	printf ("%s is already loaded\n", dll_name);
+      return TRUE;
+    }
+
+  /* Iterate through the list of symbols.  */
+  for (i = 0; i < nexp; i++)
+    {
+      /* Pointer to the names vector.  */
+      unsigned long name_rva = pep_as32 (erva + name_rvas + i * 4);
+      def_file_import *imp;
+      /* Pointer to the function address vector.  */
+      unsigned long func_rva = pep_as32 (erva + exp_funcbase + i * 4);
+      int is_data = 0;
+
+      /* Skip unwanted symbols, which are
+	 exported in buggy auto-import releases.  */
+      if (strncmp (erva + name_rva, "_nm_", 4) != 0)
+ 	{
+ 	  /* is_data is true if the address is in the data, rdata or bss
+	     segment.  */
+ 	  is_data =
+	    (func_rva >= data_start && func_rva < data_end)
+	    || (func_rva >= rdata_start && func_rva < rdata_end)
+	    || (func_rva >= bss_start && func_rva < bss_end);
+
+	  imp = def_file_add_import (pep_def_file, erva + name_rva,
+				     dll_name, i, 0);
+ 	  /* Mark symbol type.  */
+ 	  imp->data = is_data;
+
+ 	  if (pep_dll_extra_pe_debug)
+	    printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
+		    __FUNCTION__, dll_name, erva + name_rva,
+		    func_rva, is_data ? "(data)" : "");
+ 	}
+    }
+
+  return TRUE;
+}
+
+/* These are the main functions, called from the emulation.  The first
+   is called after the bfds are read, so we can guess at how much space
+   we need.  The second is called after everything is placed, so we
+   can put the right values in place.  */
+
+void
+pep_dll_build_sections (bfd *abfd, struct bfd_link_info *info)
+{
+  pep_dll_id_target (bfd_get_target (abfd));
+  process_def_file (abfd, info);
+
+  if (pep_def_file->num_exports == 0 && !info->shared)
+    return;
+
+  generate_edata (abfd, info);
+  build_filler_bfd (1);
+}
+
+void
+pep_exe_build_sections (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  pep_dll_id_target (bfd_get_target (abfd));
+  build_filler_bfd (0);
+}
+
+void
+pep_dll_fill_sections (bfd *abfd, struct bfd_link_info *info)
+{
+  pep_dll_id_target (bfd_get_target (abfd));
+  image_base = pe_data (abfd)->pe_opthdr.ImageBase;
+
+  generate_reloc (abfd, info);
+  if (reloc_sz > 0)
+    {
+      bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
+
+      /* Resize the sections.  */
+      lang_reset_memory_regions ();
+      lang_size_sections (NULL, TRUE);
+
+      /* Redo special stuff.  */
+      ldemul_after_allocation ();
+
+      /* Do the assignments again.  */
+      lang_do_assignments ();
+    }
+
+  fill_edata (abfd, info);
+
+  if (info->shared && !info->pie)
+    pe_data (abfd)->dll = 1;
+
+  edata_s->contents = edata_d;
+  reloc_s->contents = reloc_d;
+}
+
+void
+pep_exe_fill_sections (bfd *abfd, struct bfd_link_info *info)
+{
+  pep_dll_id_target (bfd_get_target (abfd));
+  image_base = pe_data (abfd)->pe_opthdr.ImageBase;
+
+  generate_reloc (abfd, info);
+  if (reloc_sz > 0)
+    {
+      bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
+
+      /* Resize the sections.  */
+      lang_reset_memory_regions ();
+      lang_size_sections (NULL, TRUE);
+
+      /* Redo special stuff.  */
+      ldemul_after_allocation ();
+
+      /* Do the assignments again.  */
+      lang_do_assignments ();
+    }
+  reloc_s->contents = reloc_d;
+}
diff -rNbu binutils-2.17_org/ld/pep-dll.h binutils-2.17/ld/pep-dll.h
--- binutils-2.17_org/ld/pep-dll.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/ld/pep-dll.h	2006-08-17 09:13:35.000000000 +0200
@@ -0,0 +1,64 @@
+/* pep-dll.h: Header file for routines used to build Windows DLLs.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#ifndef PEP_DLL_H
+#define PEP_DLL_H
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "deffile.h"
+
+extern def_file *pep_def_file;
+extern int pep_dll_export_everything;
+extern int pep_dll_do_default_excludes;
+extern int pep_dll_kill_ats;
+extern int pep_dll_stdcall_aliases;
+extern int pep_dll_warn_dup_exports;
+extern int pep_dll_compat_implib;
+extern int pep_dll_extra_pe_debug;
+
+extern void pep_dll_id_target
+  (const char *);
+extern void pep_dll_add_excludes
+  (const char *, const int);
+extern void pep_dll_generate_def_file
+  (const char *);
+extern void pep_dll_generate_implib
+  (def_file *, const char *);
+extern void pep_process_import_defs
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean pep_implied_import_dll
+  (const char *);
+extern void pep_dll_build_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_exe_build_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_dll_fill_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_exe_fill_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_walk_relocs_of_symbol
+  (struct bfd_link_info *, const char *, int (*) (arelent *, asection *));
+extern void pep_create_import_fixup
+  (arelent * rel, asection *, int);
+#endif /* PE_DLL_H */
diff -rNbu binutils-2.17_org/ld/po/POTFILES.in binutils-2.17/ld/po/POTFILES.in
--- binutils-2.17_org/ld/po/POTFILES.in	2006-04-16 20:21:51.000000000 +0200
+++ binutils-2.17/ld/po/POTFILES.in	2006-08-02 13:44:47.000000000 +0200
@@ -28,3 +28,5 @@
 mri.h
 pe-dll.c
 pe-dll.h
+pep-dll.c
+pep-dll.h
diff -rNbu binutils-2.17_org/ld/scripttempl/pep.sc binutils-2.17/ld/scripttempl/pep.sc
--- binutils-2.17_org/ld/scripttempl/pep.sc	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/ld/scripttempl/pep.sc	2006-07-28 14:12:22.000000000 +0200
@@ -0,0 +1,272 @@
+# Linker script for PE.
+
+if test -z "${RELOCATEABLE_OUTPUT_FORMAT}"; then
+  RELOCATEABLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+fi
+
+# We can't easily and portably get an unquoted $ in a shell
+# substitution, so we do this instead.
+# Sorting of the .foo$* sections is required by the definition of
+# grouped sections in PE.
+# Sorting of the file names in R_IDATA is required by the
+# current implementation of dlltool (this could probably be changed to
+# use grouped sections instead).
+if test "${RELOCATING}"; then
+  R_TEXT='*(SORT(.text$*))'
+  R_DATA='*(SORT(.data$*))'
+  R_RDATA='*(SORT(.rdata$*))'
+  R_IDATA='
+    SORT(*)(.idata$2)
+    SORT(*)(.idata$3)
+    /* These zeroes mark the end of the import list.  */
+    LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
+    SORT(*)(.idata$4)
+    SORT(*)(.idata$5)
+    SORT(*)(.idata$6)
+    SORT(*)(.idata$7)'
+  R_CRT_XC='*(SORT(.CRT$XC*))  /* C initialization */'
+  R_CRT_XI='*(SORT(.CRT$XI*))  /* C++ initialization */'
+  R_CRT_XL='*(SORT(.CRT$XL*))  /* TLS callbacks */'
+  R_CRT_XP='*(SORT(.CRT$XP*))  /* Pre-termination */'
+  R_CRT_XT='*(SORT(.CRT$XT*))  /* Termination */'
+  R_TLS='
+    *(.tls)
+    *(.tls$)
+    *(SORT(.tls$*))'
+  R_RSRC='*(SORT(.rsrc$*))'
+else
+  R_TEXT=
+  R_DATA=
+  R_RDATA=
+  R_IDATA=
+  R_CRT=
+  R_RSRC=
+fi
+
+cat <<EOF
+${RELOCATING+OUTPUT_FORMAT(${OUTPUT_FORMAT})}
+${RELOCATING-OUTPUT_FORMAT(${RELOCATEABLE_OUTPUT_FORMAT})}
+${OUTPUT_ARCH+OUTPUT_ARCH(${OUTPUT_ARCH})}
+
+${LIB_SEARCH_DIRS}
+
+SECTIONS
+{
+  ${RELOCATING+/* Make the virtual address and file offset synced if the alignment is}
+  ${RELOCATING+   lower than the target page size. */}
+  ${RELOCATING+. = SIZEOF_HEADERS;}
+  ${RELOCATING+. = ALIGN(__section_alignment__);}
+  .text ${RELOCATING+ __image_base__ + ( __section_alignment__ < ${TARGET_PAGE_SIZE} ? . : __section_alignment__ )} : 
+  {
+    ${RELOCATING+ *(.init)}
+    *(.text)
+    ${R_TEXT}
+    *(.glue_7t)
+    *(.glue_7)
+    ${CONSTRUCTING+ ___CTOR_LIST__ = .; __CTOR_LIST__ = . ; 
+			LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*));  LONG (0); }
+    ${CONSTRUCTING+ ___DTOR_LIST__ = .; __DTOR_LIST__ = . ; 
+			LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*));  LONG (0); }
+    ${RELOCATING+ *(.fini)}
+    /* ??? Why is .gcc_exc here?  */
+    ${RELOCATING+ *(.gcc_exc)}
+    ${RELOCATING+PROVIDE (etext = .);}
+    *(.gcc_except_table)
+  }
+
+  /* The Cygwin32 library uses a section to avoid copying certain data
+     on fork.  This used to be named ".data$nocopy".  The linker used
+     to include this between __data_start__ and __data_end__, but that
+     breaks building the cygwin32 dll.  Instead, we name the section
+     ".data_cygwin_nocopy" and explictly include it after __data_end__. */
+
+  .data ${RELOCATING+BLOCK(__section_alignment__)} : 
+  {
+    ${RELOCATING+__data_start__ = . ;}
+    *(.data)
+    *(.data2)
+    ${R_DATA}
+    *(.jcr)
+    ${RELOCATING+__data_end__ = . ;}
+    ${RELOCATING+*(.data_cygwin_nocopy)}
+  }
+
+  .rdata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.rdata)
+    ${R_RDATA}
+    *(.eh_frame)
+    ${RELOCATING+___RUNTIME_PSEUDO_RELOC_LIST__ = .;}
+    ${RELOCATING+__RUNTIME_PSEUDO_RELOC_LIST__ = .;}
+    *(.rdata_runtime_pseudo_reloc)
+    ${RELOCATING+___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;}
+    ${RELOCATING+__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;}
+  }
+
+  .pdata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.pdata)
+  }
+
+  .bss ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    ${RELOCATING+__bss_start__ = . ;}
+    *(.bss)
+    *(COMMON)
+    ${RELOCATING+__bss_end__ = . ;}
+  }
+
+  .edata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.edata)
+  }
+
+  /DISCARD/ :
+  {
+    *(.debug\$S)
+    *(.debug\$T)
+    *(.debug\$F)
+    *(.drectve)
+  }
+
+  .idata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    /* This cannot currently be handled with grouped sections.
+	See pep.em:sort_sections.  */
+    ${R_IDATA}
+  }
+  .CRT ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    ${RELOCATING+___crt_xc_start__ = . ;}
+    ${R_CRT_XC}
+    ${RELOCATING+___crt_xc_end__ = . ;}
+    ${RELOCATING+___crt_xi_start__ = . ;}
+    ${R_CRT_XI}
+    ${RELOCATING+___crt_xi_end__ = . ;}
+    ${RELOCATING+___crt_xl_start__ = . ;}
+    ${R_CRT_XL}
+    /* ___crt_xl_end__ is defined in the TLS Directory support code */
+    ${RELOCATING+___crt_xp_start__ = . ;}
+    ${R_CRT_XP}
+    ${RELOCATING+___crt_xp_end__ = . ;}
+    ${RELOCATING+___crt_xt_start__ = . ;}
+    ${R_CRT_XT}
+    ${RELOCATING+___crt_xt_end__ = . ;}
+  }
+
+  .tls ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    ${RELOCATING+___tls_start__ = . ;}
+    ${R_TLS}
+    ${RELOCATING+___tls_end__ = . ;}
+  }
+
+  .endjunk ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    /* end is deprecated, don't use it */
+    ${RELOCATING+PROVIDE (end = .);}
+    ${RELOCATING+PROVIDE ( _end = .);}
+    ${RELOCATING+ __end__ = .;}
+  }
+
+  .rsrc ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    *(.rsrc)
+    ${R_RSRC}
+  }
+
+  .reloc ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    *(.reloc)
+  }
+
+  .stab ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.stab)
+  }
+
+  .stabstr ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.stabstr)
+  }
+
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section.  Unlike other targets that fake this by putting the
+     section VMA at 0, the PE format will not allow it.  */
+     
+  /* DWARF 1.1 and DWARF 2.  */
+  .debug_aranges ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_aranges)
+  }
+
+  .debug_pubnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_pubnames)
+  }
+
+  /* DWARF 2.  */
+  .debug_info ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_info) *(.gnu.linkonce.wi.*)
+  }
+
+  .debug_abbrev ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_abbrev)
+  }
+
+  .debug_line ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_line)
+  }
+
+  .debug_frame ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_frame)
+  }
+
+  .debug_str ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_str)
+  }
+
+  .debug_loc ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_loc)
+  }
+
+  .debug_macinfo ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_macinfo)
+  }
+
+  /* SGI/MIPS DWARF 2 extensions.  */
+  .debug_weaknames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_weaknames)
+  }
+
+  .debug_funcnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_funcnames)
+  }
+
+  .debug_typenames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_typenames)
+  }
+
+  .debug_varnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_varnames)
+  }
+
+  /* DWARF 3.  */
+  .debug_ranges ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_ranges)
+  }
+}
+EOF

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista binaries
  2006-08-17 16:25 PE+ and new COFF format for x86_64 target for XP64 and Vista binaries Kai Tietz
@ 2006-08-17 16:45 ` H. J. Lu
  2006-09-07 13:41   ` Kai Tietz
  2006-09-08  9:48 ` Pedro Alves
  1 sibling, 1 reply; 17+ messages in thread
From: H. J. Lu @ 2006-08-17 16:45 UTC (permalink / raw)
  To: Kai Tietz; +Cc: binutils

Do you have copyright paper with FSF? Also you need to provide
ChangeLog entries. You should also provide some testcases for as,
ld and objcopy/strip.

H.J.
--
On Thu, Aug 17, 2006 at 11:40:36AM +0200, Kai Tietz wrote:
> Hallo,
> 
> This is a port of binutils-2.17 for COFF-format x86-64 (AMD64) and the PE+ 
> for Windows XP64 and Vista EXE/DLL. The target is named x86_64-pc-mingw64. 
> I enabled windres and dlltool for this target. For the tool objdump the 
> processing and printing methods for DLL-imports are adjusted (they are now 
> 8 bytes long :( )
> 
> I made a copy of the pe_dll(.c&.h) as pep_dll(.c&.h) to minimize 
> intersections. May these files can be merged.
> 
> In the "include/coff/external.h" I introduced the proper PE+ external 
> aouthdr structure without the data_start member. Because this non-existing 
> member breaks the
> size of the PEPAOUT structure in include/coff/pe.h.
> 
> For the bfd/pexxigen.c template I used the pex64 name alias for 
> generation.
> 
> I added the following new files:
>         bfd/coff-x86_64.c
>         bfd/pe-x86_64.c
>         bfd/pei-x86_64.c
>         gas/config/te-pep.h
>         include/coff/x86_54.h
>         ld/pep_dll.c
>         ld/pep_dll.h
>         ld/emulparams/i386pep.sh
>         ld/emultempl/pep.em
>         ld/scripttempl/pep.sc
> 
> 
> I tested the ld of this target by MSVC object-files and by (a patched) gcc 
> object-files (using this gas) linking against MS-Runtime-libraries.
> 
> i.A. Kai Tietz
> 
> 
> 
> ----------------------------------------
>   Kai Tietz - Software engineering
>   OneVision Software Entwicklungs GmbH & Co KG
>   Dr.-Leo-Ritter-Str. 9, 93049 Regensburg, Germany
>   Phone: +49-941-78004-0
>   FAX:   +49-941-78004-489
>   WWW:   http://www.OneVision.com


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista binaries
  2006-08-17 16:45 ` H. J. Lu
@ 2006-09-07 13:41   ` Kai Tietz
  2006-09-07 15:04     ` H. J. Lu
  0 siblings, 1 reply; 17+ messages in thread
From: Kai Tietz @ 2006-09-07 13:41 UTC (permalink / raw)
  To: binutils; +Cc: H. J. Lu, Roland Schwingel

[-- Attachment #1: Type: text/plain, Size: 2484 bytes --]

Ok, the copyright paper is on the way to FSF.
Additionally I added the ChangeLog entries. Also the testcases of 
binutils, gas, and ld are extended for supporting the new target.
Most testcases work proper, just there seems to be a problem with the weak 
alias test. It fails for some reason I didn't got it.
Also the align test case seems to work for this new target (for pe target 
it was defined as xfail ...).

Regards,
 i.A. Kai Tietz


----------------------------------------
  Kai Tietz - Software engineering
  OneVision Software Entwicklungs GmbH & Co KG
  Dr.-Leo-Ritter-Str. 9, 93049 Regensburg, Germany
  Phone: +49-941-78004-0
  FAX:   +49-941-78004-489
  WWW:   http://www.OneVision.com


Do you have copyright paper with FSF? Also you need to provide
ChangeLog entries. You should also provide some testcases for as,
ld and objcopy/strip.

H.J.
--
On Thu, Aug 17, 2006 at 11:40:36AM +0200, Kai Tietz wrote:
> Hallo,
> 
> This is a port of binutils-2.17 for COFF-format x86-64 (AMD64) and the 
PE+ 
> for Windows XP64 and Vista EXE/DLL. The target is named 
x86_64-pc-mingw64. 
> I enabled windres and dlltool for this target. For the tool objdump the 
> processing and printing methods for DLL-imports are adjusted (they are 
now 
> 8 bytes long :( )
> 
> I made a copy of the pe_dll(.c&.h) as pep_dll(.c&.h) to minimize 
> intersections. May these files can be merged.
> 
> In the "include/coff/external.h" I introduced the proper PE+ external 
> aouthdr structure without the data_start member. Because this 
non-existing 
> member breaks the
> size of the PEPAOUT structure in include/coff/pe.h.
> 
> For the bfd/pexxigen.c template I used the pex64 name alias for 
> generation.
> 
> I added the following new files:
>         bfd/coff-x86_64.c
>         bfd/pe-x86_64.c
>         bfd/pei-x86_64.c
>         gas/config/te-pep.h
>         include/coff/x86_54.h
>         ld/pep_dll.c
>         ld/pep_dll.h
>         ld/emulparams/i386pep.sh
>         ld/emultempl/pep.em
>         ld/scripttempl/pep.sc
> 
> 
> I tested the ld of this target by MSVC object-files and by (a patched) 
gcc 
> object-files (using this gas) linking against MS-Runtime-libraries.
> 
> i.A. Kai Tietz
> 
> 
> 
> ----------------------------------------
>   Kai Tietz - Software engineering
>   OneVision Software Entwicklungs GmbH & Co KG
>   Dr.-Leo-Ritter-Str. 9, 93049 Regensburg, Germany
>   Phone: +49-941-78004-0
>   FAX:   +49-941-78004-489
>   WWW:   http://www.OneVision.com




[-- Attachment #2: binutils-2.17.pex64.20060907.diff --]
[-- Type: application/octet-stream, Size: 260673 bytes --]

diff -rNbu binutils-2.17_org/bfd/ChangeLog binutils-2.17/bfd/ChangeLog
--- binutils-2.17_org/bfd/ChangeLog	2006-06-23 20:18:16.000000000 +0200
+++ binutils-2.17/bfd/ChangeLog	2006-09-07 13:02:43.000000000 +0200
@@ -1,3 +1,30 @@
+2006-09-07	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* bfd/configure.in:	Added new target-vectors x86_64coff_vec, x86_64pe_vec, and x86_64pei_vec
+	* bfd/configure:		Added new target x86_64-pc-mingw64 and build rules for target-vectors
+	* bfd/config.bfd:		Adjusted x86_64 target architecture detection
+	* bfd/bfd.c:			Add for new target "coff-x86-64"
+		bfd_get_sign_extend:	Add target vector idents for pe-x86-64. and pei-x86-64
+	* bfd/coff-x86_64.c: 	Add new file for x86_64 (AMD64) coff support
+	* bfd/libpei.h				Adjustments for COFF_WITH_pex64
+	* bfd/coffcode.h:			Add for new target machine, architecture, signature, and internal
+								signature handler.
+	* bfd/makefile.am:	Add new files to target-all and define make-rule for pex64igen.c
+	* bfd/makefile.in:	Add new files to target-all and define make-rule for pex64igen.c
+	* bfd/pe-x86_64.c:	Add for new target "pe-x86-64"
+	* bfd/pei-x86_64.c:	Add for new target "pei-x86-64"
+	* bfd/peicode.h:		Adjusts for new targets
+		coff_swap_filehdr_out:	set for this target to _bfd_pex64_only_swap_filehdr_out
+		SIZEOF_IDATA4:				define it as 8 byte size for this target
+		SIZEOF_IDATA5:				define it as 8 byte size for this target
+		jump_table jtab:			Add for AMD64MAGIC
+		pe_ILF_build_a_bfd:		Adjusts for new size of SIZEOF_IDATA4 and SIZE_IDATA5
+		pe_ILF_object_p:			Add coff image-file signature to internal signature translation
+	* bfd/pexxigen.c:		Adjust proper include of target coff-header and introduced target specific code
+		COFF_WITH_pex64:	New macro for this target
+		pe_print_idata:	New dumping method for import section of PE+ files
+	* bfd/target.c:		Add new target vectors declarations for x86_64 coff targets
+	
 2006-06-23  Daniel Jacobowitz  <dan@codesourcery.com>
 
 	* configure.in: Update version to 2.17.
diff -rNbu binutils-2.17_org/bfd/Makefile.am binutils-2.17/bfd/Makefile.am
--- binutils-2.17_org/bfd/Makefile.am	2006-06-23 20:17:17.000000000 +0200
+++ binutils-2.17/bfd/Makefile.am	2006-08-09 10:16:55.000000000 +0200
@@ -555,7 +555,11 @@
 	mmo.lo \
 	nlm32-alpha.lo \
 	nlm64.lo \
-	pepigen.lo
+	coff-x86_64.lo \
+	pe-x86_64.lo \
+	pei-x86_64.lo \
+	pepigen.lo \
+	pex64igen.lo
 
 BFD64_BACKENDS_CFILES = \
 	aix5ppc-core.c \
@@ -578,6 +582,9 @@
 	elf64.c \
 	mmo.c \
 	nlm32-alpha.c \
+	coff-x86_64.c \
+	pe-x86_64.c \
+	pei-x86_64.c \
 	nlm64.c
 
 OPTIONAL_BACKENDS = \
@@ -628,7 +635,7 @@
 	$(OPTIONAL_BACKENDS_CFILES)
 
 BUILD_CFILES = \
-	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c
+	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c pex64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 
@@ -781,6 +788,11 @@
 	sed -e s/XX/pe/g < $(srcdir)/peXXigen.c > peigen.new
 	mv -f peigen.new peigen.c
 
+pex64igen.c : peXXigen.c
+	rm -f pex64igen.c
+	sed -e s/XX/pex64/g < $(srcdir)/peXXigen.c > pex64igen.new
+	mv -f pex64igen.new pex64igen.c
+
 pepigen.c : peXXigen.c
 	rm -f pepigen.c
 	sed -e s/XX/pep/g < $(srcdir)/peXXigen.c > pepigen.new
@@ -1830,6 +1842,9 @@
   $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(INCDIR)/opcode/ia64.h \
   $(INCDIR)/elf/ia64.h $(INCDIR)/elf/reloc-macros.h $(INCDIR)/objalloc.h \
   elf64-target.h
+pex64igen.lo: pex64igen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+  $(INCDIR)/coff/internal.h $(INCDIR)/coff/x86_64.h $(INCDIR)/coff/external.h \
+  $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
 peigen.lo: peigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
diff -rNbu binutils-2.17_org/bfd/Makefile.in binutils-2.17/bfd/Makefile.in
--- binutils-2.17_org/bfd/Makefile.in	2006-06-23 20:17:19.000000000 +0200
+++ binutils-2.17/bfd/Makefile.in	2006-08-09 10:17:57.000000000 +0200
@@ -793,7 +793,11 @@
 	mmo.lo \
 	nlm32-alpha.lo \
 	nlm64.lo \
-	pepigen.lo
+	coff-x86_64.lo \
+	pe-x86_64.lo \
+	pei-x86_64.lo \
+	pepigen.lo \
+	pex64igen.lo
 
 BFD64_BACKENDS_CFILES = \
 	aix5ppc-core.c \
@@ -816,6 +820,9 @@
 	elf64.c \
 	mmo.c \
 	nlm32-alpha.c \
+	coff-x86_64.c \
+	pe-x86_64.c \
+	pei-x86_64.c \
 	nlm64.c
 
 OPTIONAL_BACKENDS = \
@@ -867,7 +874,7 @@
 	$(OPTIONAL_BACKENDS_CFILES)
 
 BUILD_CFILES = \
-	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c
+	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c pex64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 SOURCE_HFILES = \
@@ -1365,6 +1372,11 @@
 	sed -e s/XX/pe/g < $(srcdir)/peXXigen.c > peigen.new
 	mv -f peigen.new peigen.c
 
+pex64igen.c : peXXigen.c
+	rm -f pex64igen.c
+	sed -e s/XX/pex64/g < $(srcdir)/peXXigen.c > pex64igen.new
+	mv -f pex64igen.new pex64igen.c
+	
 pepigen.c : peXXigen.c
 	rm -f pepigen.c
 	sed -e s/XX/pep/g < $(srcdir)/peXXigen.c > pepigen.new
@@ -2399,6 +2411,9 @@
 peigen.lo: peigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
+pex64igen.lo: pex64igen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+  $(INCDIR)/coff/internal.h $(INCDIR)/coff/x86_64.h $(INCDIR)/coff/external.h \
+  $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
 pepigen.lo: pepigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/ia64.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
diff -rNbu binutils-2.17_org/bfd/bfd.c binutils-2.17/bfd/bfd.c
--- binutils-2.17_org/bfd/bfd.c	2006-03-16 13:20:15.000000000 +0100
+++ binutils-2.17/bfd/bfd.c	2006-08-04 11:42:38.000000000 +0200
@@ -858,7 +858,8 @@
      a place will have to be found.  Until then, this hack will do.  */
   if (strncmp (name, "coff-go32", sizeof ("coff-go32") - 1) == 0
       || strcmp (name, "pe-i386") == 0
-      || strcmp (name, "pei-i386") == 0)
+      || strcmp (name, "pei-i386") == 0 ||
+	  strcmp(name,"pe-x86-64")==0 || strcmp(name,"pei-x86-64"))
     return 1;
 
   bfd_set_error (bfd_error_wrong_format);
diff -rNbu binutils-2.17_org/bfd/coff-x86_64.c binutils-2.17/bfd/coff-x86_64.c
--- binutils-2.17_org/bfd/coff-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/bfd/coff-x86_64.c	2006-09-06 12:28:11.000000000 +0200
@@ -0,0 +1,751 @@
+/* BFD back-end for AMD 64 COFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+#ifndef COFF_WITH_pex64
+#define COFF_WITH_pex64
+#endif
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#include "coff/x86_64.h"
+#include "coff/internal.h"
+#include "coff/pe.h"
+#include "libcoff.h"
+
+#define BADMAG(x) AMD64BADMAG(x)
+
+#ifdef COFF_WITH_pex64
+# undef AOUTSZ
+# define AOUTSZ		PEPAOUTSZ
+# define PEAOUTHDR	PEPAOUTHDR
+#endif
+
+static bfd_reloc_status_type coff_amd64_reloc(bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **);
+static reloc_howto_type *coff_amd64_rtype_to_howto(bfd *, asection *, struct internal_reloc *,struct coff_link_hash_entry *, struct internal_syment *,bfd_vma *);
+static reloc_howto_type *coff_amd64_reloc_type_lookup(bfd *, bfd_reloc_code_real_type);
+
+#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 AMD 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 relocatable 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_amd64_reloc(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 !defined(COFF_WITH_PE)
+  if(output_bfd == (bfd *) NULL)
+    return bfd_reloc_continue;
+#endif
+
+  if(bfd_is_com_section (symbol->section)) {
+#if !defined(COFF_WITH_PE)
+     /* 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
+      /* In PE mode, we do not offset the common symbol.  */
+      diff = reloc_entry->addend;
+#endif
+    }
+  else
+    {
+      /* For some reason bfd_perform_relocation always effectively
+	 ignores the addend for a COFF target when producing
+	 relocatable output.  This seems to be always wrong for 386
+	 COFF, so we handle the addend here instead.  */
+#if defined(COFF_WITH_PE)
+      if(output_bfd == (bfd *) NULL)
+	{
+	  reloc_howto_type *howto = reloc_entry->howto;
+
+	  /* Although PC relative relocations are very similar between
+	     PE and non-PE formats, but they are off by 1 << howto->size
+	     bytes. For the external relocation, PE is very different
+	     from others. See md_apply_fix3 () in gas/config/tc-amd64.c.
+	     When we link PE and non-PE object files together to
+	     generate a non-PE executable, we have to compensate it
+	     here.  */
+	  if(howto->pc_relative && howto->pcrel_offset)
+	    diff = -(1 << howto->size);
+	  else if(symbol->flags & BSF_WEAK)
+	    diff = reloc_entry->addend - symbol->value;
+	  else
+	    diff = -reloc_entry->addend;
+	}
+      else
+#endif
+	diff = reloc_entry->addend;
+    }
+
+#if defined(COFF_WITH_PE)
+  /* FIXME: How should this case be handled?  */
+  if(reloc_entry->howto->type == R_AMD64_IMAGEBASE
+      && output_bfd!=NULL
+      && bfd_get_flavour(output_bfd) == bfd_target_coff_flavour)
+    diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
+#endif
+
+#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;
+	  case 4:
+	    {
+	      long long x = bfd_get_64 (abfd, addr);
+	      DOIT (x);
+	      bfd_put_64 (abfd, (bfd_vma) x, addr);
+	    }
+	    break;
+
+	  default:
+	    abort ();
+	  }
+      }
+
+  /* Now let bfd_perform_relocation finish everything up.  */
+  return bfd_reloc_continue;
+}
+
+#if defined(COFF_WITH_PE)
+/* Return TRUE if this relocation should appear in the output .reloc
+   section.  */
+
+static bfd_boolean in_reloc_p(bfd *, reloc_howto_type *);
+
+static bfd_boolean in_reloc_p(bfd *abfd ATTRIBUTE_UNUSED,reloc_howto_type *howto)
+{
+  return ! howto->pc_relative && howto->type!=R_AMD64_IMAGEBASE;
+}
+#endif /* COFF_WITH_PE */
+
+#ifndef PCRELOFFSET
+#define PCRELOFFSET TRUE
+#endif
+
+static reloc_howto_type howto_table[] =
+{
+  EMPTY_HOWTO (0),
+  HOWTO (R_AMD64_DIR64,		/* type  1*/
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long, 4 = long long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "R_X86_64_64",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffffffffffffll,		/* src_mask */
+	 0xffffffffffffffffll,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+  HOWTO (R_AMD64_DIR32,		/* type 2 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "R_X86_64_32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+  /* PE IMAGE_REL_AMD64_ADDR32NB relocation (3).	*/
+  HOWTO (R_AMD64_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_amd64_reloc,	/* special_function */
+	 "rva32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+  /* 32-bit longword PC relative relocation (4).  */
+  HOWTO (R_AMD64_PCRLONG,		/* type 4 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+
+ HOWTO (R_AMD64_PCRLONG_1,		/* type 5 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+1",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_2,		/* type 6 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+2",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_3,		/* type 7 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+3",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_4,		/* type 8 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+4",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_5,		/* type 9 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+5",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  EMPTY_HOWTO (10), // R_AMD64_SECTION 10
+#if defined(COFF_WITH_PE)
+  /* 32-bit longword section relative relocation (11).  */
+  HOWTO (R_AMD64_SECREL,		/* 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_amd64_reloc,	/* special_function */
+	 "secrel32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+#else
+  EMPTY_HOWTO (11),
+#endif
+  EMPTY_HOWTO (12),
+  EMPTY_HOWTO (13),
+#ifndef DONT_EXTEND_AMD64
+  HOWTO (R_AMD64_PCRQUAD,
+         0,                     /* rightshift */
+         4,                     /* size (0 = byte, 1 = short, 2 = long) */
+         64,                    /* bitsize */
+         TRUE,                  /* pc_relative */
+         0,                     /* bitpos */
+         complain_overflow_signed, /* complain_on_overflow */
+         coff_amd64_reloc,      /* special_function */
+         "R_X86_64_PC64",       /* name */
+         TRUE,                  /* partial_inplace */
+         0xffffffffffffffffll,  /* src_mask */
+         0xffffffffffffffffll,  /* dst_mask */
+         PCRELOFFSET),           /* pcrel_offset */
+#else
+  EMPTY_HOWTO (14),
+#endif
+  /* Byte relocation (15).  */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_8",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0x000000ff,		/* src_mask */
+	 0x000000ff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 16-bit word relocation (16).  */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_16",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 32-bit longword relocation (17).	*/
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_32S",			/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* Byte PC relative relocation (18).	 */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC8",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x000000ff,		/* src_mask */
+	 0x000000ff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 16-bit word PC relative relocation (19).	*/
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 32-bit longword PC relative relocation (20).  */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC32",	/* 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 I386 1			/* Customize coffcode.h */
+#define AMD64 1
+#define RTYPE2HOWTO(cache_ptr, dst)					\
+  ((cache_ptr)->howto =							\
+   ((dst)->r_type < sizeof (howto_table) / sizeof (howto_table[0])	\
+    ? howto_table + (dst)->r_type					\
+    : NULL))
+
+/* For 386 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.  For normal AMD64 COFF, we
+   can use the generic relocate_section routine.  For PE, we need our
+   own routine.  */
+
+#if !defined(COFF_WITH_PE)
+
+#define coff_relocate_section _bfd_coff_generic_relocate_section
+
+#else /* COFF_WITH_PE */
+
+/* The PE relocate section routine.  The only difference between this
+   and the regular routine is that we don't want to do anything for a
+   relocatable link.  */
+
+static bfd_boolean coff_pe_amd64_relocate_section(bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,struct internal_reloc *, struct internal_syment *, asection **);
+
+static bfd_boolean
+coff_pe_amd64_relocate_section(bfd *output_bfd,struct bfd_link_info *info,bfd *input_bfd,asection *input_section,bfd_byte *contents,struct internal_reloc *relocs,struct internal_syment *syms,asection **sections)
+{
+  if(info->relocatable)
+    return TRUE;
+
+  return _bfd_coff_generic_relocate_section(output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
+}
+
+#define coff_relocate_section coff_pe_amd64_relocate_section
+
+#endif /* COFF_WITH_PE */
+
+/* Convert an rtype to howto for the COFF backend linker.  */
+
+static reloc_howto_type *
+coff_amd64_rtype_to_howto(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;
+
+  if(rel->r_type > sizeof (howto_table) / sizeof (howto_table[0])) {
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
+  if(rel->r_type>=R_AMD64_PCRLONG_1 && rel->r_type<=R_AMD64_PCRLONG_5) {
+	  rel->r_vaddr+=(bfd_vma)(rel->r_type-R_AMD64_PCRLONG);
+	  rel->r_type=R_AMD64_PCRLONG;
+  }
+  howto = howto_table + rel->r_type;
+
+#if defined(COFF_WITH_PE)
+  /* Cancel out code in _bfd_coff_generic_relocate_section.  */
+  *addendp = 0;
+#endif
+
+  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);
+
+#if !defined(COFF_WITH_PE)
+      /* I think we *do* want to bypass this.  If we don't, I have
+	 seen some data parameters get the wrong relocation 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;
+#endif
+    }
+
+#if !defined(COFF_WITH_PE)
+  /* If the output symbol is common (in which case this must be a
+     relocatable 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;
+#endif
+
+#if defined(COFF_WITH_PE)
+  if(howto->pc_relative)
+    {
+      *addendp -= 4;
+
+      /* If the symbol is defined, then the generic code is going to
+         add back the symbol value in order to cancel out an
+         adjustment it made to the addend.  However, we set the addend
+         to 0 at the start of this function.  We need to adjust here,
+         to avoid the adjustment the generic code will make.  FIXME:
+         This is getting a bit hackish.  */
+      if(sym!=NULL && sym->n_scnum!=0)
+	*addendp -= sym->n_value;
+    }
+
+  if(rel->r_type == R_AMD64_IMAGEBASE && (bfd_get_flavour(sec->output_section->owner) == bfd_target_coff_flavour)) {
+      *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
+  }
+
+  if(rel->r_type == R_AMD64_SECREL) {
+      bfd_vma osect_vma;
+
+      if(h && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak))
+	osect_vma = h->root.u.def.section->output_section->vma;
+      else {
+	  asection *sec;
+	  int i;
+
+	  /* Sigh, the only way to get the section to offset against
+	     is to find it the hard way.  */
+
+	  for (sec = abfd->sections, i = 1; i < sym->n_scnum; i++)
+	    sec = sec->next;
+
+	  osect_vma = sec->output_section->vma;
+	}
+
+      *addendp -= osect_vma;
+    }
+#endif
+
+  return howto;
+}
+
+#define coff_bfd_reloc_type_lookup coff_amd64_reloc_type_lookup
+
+static reloc_howto_type *
+coff_amd64_reloc_type_lookup(bfd *abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)
+{
+  switch (code) {
+    case BFD_RELOC_RVA:
+      return howto_table + R_AMD64_IMAGEBASE;
+    case BFD_RELOC_32:
+      return howto_table + R_AMD64_DIR32;
+    case BFD_RELOC_64:
+      return howto_table + R_AMD64_DIR64;
+    case BFD_RELOC_64_PCREL:
+#ifndef DONT_EXTEND_AMD64
+      return howto_table + R_AMD64_PCRQUAD;
+#else
+	/* Fall trough */
+#endif
+    case BFD_RELOC_32_PCREL:
+      return howto_table + R_AMD64_PCRLONG;
+    case BFD_RELOC_X86_64_32S:
+      return howto_table + R_RELLONG;
+    case BFD_RELOC_16:
+      return howto_table + R_RELWORD;
+    case BFD_RELOC_16_PCREL:
+      return howto_table + R_PCRWORD;
+    case BFD_RELOC_8:
+      return howto_table + R_RELBYTE;
+    case BFD_RELOC_8_PCREL:
+      return howto_table + R_PCRBYTE;
+#if defined(COFF_WITH_PE)
+    case BFD_RELOC_32_SECREL:
+      return howto_table + R_AMD64_SECREL;
+#endif
+    default:
+      BFD_FAIL ();
+      return 0;
+    }
+}
+
+#define coff_rtype_to_howto coff_amd64_rtype_to_howto
+
+#ifdef TARGET_UNDERSCORE
+
+/* If amd64 gcc uses underscores for symbol names, then it does not use
+   a leading dot for local labels, so if TARGET_UNDERSCORE is defined
+   we treat all symbols starting with L as local.  */
+
+static bfd_boolean coff_amd64_is_local_label_name(bfd *, const char *);
+
+static bfd_boolean coff_amd64_is_local_label_name(bfd *abfd,const char *name)
+{
+  if(name[0] == 'L')
+    return TRUE;
+
+  return _bfd_coff_is_local_label_name (abfd, name);
+}
+
+#define coff_bfd_is_local_label_name coff_amd64_is_local_label_name
+
+#endif /* TARGET_UNDERSCORE */
+
+#include "coffcode.h"
+
+#ifdef PE
+#define amd64coff_object_p pe_bfd_object_p
+#else
+#define amd64coff_object_p coff_object_p
+#endif
+
+const bfd_target
+#ifdef TARGET_SYM
+  TARGET_SYM =
+#else
+  x86_64coff_vec =
+#endif
+{
+#ifdef TARGET_NAME
+  TARGET_NAME,
+#else
+ "coff-x86-64",			/* 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 | D_PAGED),
+
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
+#if defined(COFF_WITH_PE)
+   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY
+#endif
+   | SEC_CODE | SEC_DATA),
+
+#ifdef TARGET_UNDERSCORE
+  TARGET_UNDERSCORE,		/* leading underscore */
+#else
+  0,				/* leading underscore */
+#endif
+  '/',				/* 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, amd64coff_object_p, /* bfd_check_format */
+       bfd_generic_archive_p, amd64coff_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 -rNbu binutils-2.17_org/bfd/coffcode.h binutils-2.17/bfd/coffcode.h
--- binutils-2.17_org/bfd/coffcode.h	2005-10-25 19:40:09.000000000 +0200
+++ binutils-2.17/bfd/coffcode.h	2006-09-05 11:42:19.000000000 +0200
@@ -298,7 +298,7 @@
 
 */
 
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
 #include "peicode.h"
 #else
 #include "coffswap.h"
@@ -350,7 +350,7 @@
 static void * coff_mkobject_hook
   (bfd *, void *,  void *);
 #endif
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
 static flagword handle_COMDAT
   (bfd *, flagword, void *, const char *, asection *);
 #endif
@@ -376,7 +376,7 @@
    styp_to_sec_flags().  NOTE: If you add to/change this routine, you
    should probably mirror the changes in styp_to_sec_flags().  */
 
-#ifndef COFF_WITH_PE
+#if !defined(COFF_WITH_PE)
 
 /* Macros for setting debugging flags.  */
 
@@ -584,7 +584,7 @@
    sec_to_styp_flags().  NOTE: If you add to/change this routine, you
    should probably mirror the changes in sec_to_styp_flags().  */
 
-#ifndef COFF_WITH_PE
+#if !defined(COFF_WITH_PE)
 
 static bfd_boolean
 styp_to_sec_flags (bfd *abfd ATTRIBUTE_UNUSED,
@@ -718,7 +718,6 @@
   if (strncmp (name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0)
     sec_flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
 #endif
-
   if (flags_ptr == NULL)
     return FALSE;
 
@@ -1621,7 +1620,7 @@
 }
 
 #else /* ! COFF_ALIGN_IN_SECTION_HEADER */
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
 
 /* A couple of macros to help setting the alignment power field.  */
 #define ALIGN_SET(field, x, y) \
@@ -1835,7 +1834,7 @@
     coff->flags = 0;
 #endif
 
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
   /* FIXME: I'm not sure this is ever executed, since peicode.h
      defines coff_mkobject_hook.  */
   if ((internal_f->f_flags & IMAGE_FILE_DEBUG_STRIPPED) == 0)
@@ -1883,6 +1882,12 @@
       arch = bfd_arch_i386;
       break;
 #endif
+#ifdef AMD64MAGIC
+	case AMD64MAGIC:
+		arch=bfd_arch_i386;
+		machine=bfd_mach_x86_64;
+		break;
+#endif
 #ifdef IA64MAGIC
     case IA64MAGIC:
       arch = bfd_arch_ia64;
@@ -2158,7 +2163,7 @@
 #ifdef SH_ARCH_MAGIC_BIG
     case SH_ARCH_MAGIC_BIG:
     case SH_ARCH_MAGIC_LITTLE:
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
     case SH_ARCH_MAGIC_WINCE:
 #endif
       arch = bfd_arch_sh;
@@ -2453,7 +2458,7 @@
       if (bfd_seek (abfd, s->rel_filepos, SEEK_SET) != 0)
 	return FALSE;
 
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
       if (obj_pe (abfd) && s->reloc_count >= 0xffff)
 	{
 	  /* Encode real count here as first reloc.  */
@@ -2713,13 +2718,18 @@
       return TRUE;
 #endif
 
-#ifdef I386MAGIC
+#if defined(I386MAGIC) || defined(AMD64MAGIC)
     case bfd_arch_i386:
+#ifdef I386MAGIC
       *magicp = I386MAGIC;
+#endif
 #ifdef LYNXOS
       /* Just overwrite the usual value if we're doing Lynx.  */
       *magicp = LYNXCOFFMAGIC;
 #endif
+#ifdef AMD64MAGIC
+	  *magicp=AMD64MAGIC;
+#endif
       return TRUE;
 #endif
 
@@ -3385,7 +3395,7 @@
   for (current = abfd->sections; current != NULL; current =
        current->next)
     {
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
       /* We store the actual reloc count in the first reloc's addr.  */
       if (obj_pe (abfd) && current->reloc_count >= 0xffff)
 	reloc_count ++;
@@ -3415,7 +3425,7 @@
 	{
 	  current->rel_filepos = reloc_base;
 	  reloc_base += current->reloc_count * bfd_coff_relsz (abfd);
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
 	  /* Extra reloc to hold real count.  */
 	  if (obj_pe (abfd) && current->reloc_count >= 0xffff)
 	    reloc_base += bfd_coff_relsz (abfd);
@@ -3498,7 +3508,7 @@
       section.s_page = coff_get_section_load_page (current);
 #endif
 
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
       section.s_paddr = 0;
 #endif
 #ifdef COFF_IMAGE_WITH_PE
@@ -3585,7 +3595,7 @@
 	    return FALSE;
 	}
 
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
       /* PE stores COMDAT section information in the symbol table.  If
          this section is supposed to have some COMDAT info, track down
          the symbol in the symbol table and modify it.  */
@@ -3751,14 +3761,18 @@
     internal_f.f_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
 #endif
 
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   internal_f.f_flags |= IMAGE_FILE_32BIT_MACHINE;
+#endif
 #else
+#ifndef COFF_WITH_pex64
   if (bfd_little_endian (abfd))
     internal_f.f_flags |= F_AR32WR;
   else
     internal_f.f_flags |= F_AR32W;
 #endif
+#endif
 
 #ifdef TI_TARGET_ID
   /* Target id is used in TI COFF v1 and later; COFF0 won't use this field,
@@ -3855,7 +3869,11 @@
 #if defined(LYNXOS)
     internal_a.magic = LYNXCOFFMAGIC;
 #else  /* LYNXOS */
+#ifdef AMD64
+	internal_a.magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+#else
     internal_a.magic = ZMAGIC;
+#endif
 #endif /* LYNXOS */
 #endif /* I386 */
 
@@ -4382,7 +4400,7 @@
 #ifdef C_SYSTEM
 	    case C_SYSTEM:	/* System Wide variable.  */
 #endif
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
             /* In PE, 0x68 (104) denotes a section symbol.  */
             case C_SECTION:
 	    /* In PE, 0x69 (105) denotes a weak external symbol.  */
@@ -4392,7 +4410,7 @@
 		{
 		case COFF_SYMBOL_GLOBAL:
 		  dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL;
-#if defined COFF_WITH_PE
+#if defined(COFF_WITH_PE)
 		  /* PE sets the symbol to a value relative to the
                      start of the section.  */
 		  dst->symbol.value = src->u.syment.n_value;
@@ -4423,7 +4441,7 @@
 
 		case COFF_SYMBOL_LOCAL:
 		  dst->symbol.flags = BSF_LOCAL;
-#if defined COFF_WITH_PE
+#if defined(COFF_WITH_PE)
 		  /* PE sets the symbol to a value relative to the
                      start of the section.  */
 		  dst->symbol.value = src->u.syment.n_value;
@@ -4442,7 +4460,7 @@
 		dst->symbol.flags |= BSF_NOT_AT_END;
 #endif
 
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
 	      if (src->u.syment.n_sclass == C_NT_WEAK)
 		dst->symbol.flags |= BSF_WEAK;
 
@@ -4474,7 +4492,7 @@
 		 section, if there is one.  */
 	      if (dst->symbol.section)
 		{
-#if defined COFF_WITH_PE
+#if defined(COFF_WITH_PE)
 		  /* PE sets the symbol to a value relative to the
                      start of the section.  */
 		  dst->symbol.value = src->u.syment.n_value;
@@ -4577,7 +4595,7 @@
 	    case C_BLOCK:	/* ".bb" or ".eb".  */
 	    case C_FCN:		/* ".bf" or ".ef" (or PE ".lf").  */
 	    case C_EFCN:	/* Physical end of function.  */
-#if defined COFF_WITH_PE
+#if defined(COFF_WITH_PE)
 	      /* PE sets the symbol to a value relative to the start
 		 of the section.  */
 	      dst->symbol.value = src->u.syment.n_value;
@@ -4614,7 +4632,7 @@
 	    case C_EXTDEF:	/* External definition.  */
 	    case C_ULABEL:	/* Undefined label.  */
 	    case C_USTATIC:	/* Undefined static.  */
-#ifndef COFF_WITH_PE
+#if !defined(COFF_WITH_PE)
             /* C_LINE in regular coff is 0x68.  NT has taken over this storage
                class to represent a section symbol.  */
 	    case C_LINE:	/* line # reformatted as symbol table entry.  */
@@ -4691,7 +4709,7 @@
 #ifdef C_SYSTEM
     case C_SYSTEM:
 #endif
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
     case C_NT_WEAK:
 #endif
       if (syment->n_scnum == 0)
@@ -4707,7 +4725,7 @@
       break;
     }
 
-#ifdef COFF_WITH_PE
+#if defined(COFF_WITH_PE)
   if (syment->n_sclass == C_STAT)
     {
       if (syment->n_scnum == 0)
diff -rNbu binutils-2.17_org/bfd/config.bfd binutils-2.17/bfd/config.bfd
--- binutils-2.17_org/bfd/config.bfd	2006-04-05 14:41:57.000000000 +0200
+++ binutils-2.17/bfd/config.bfd	2006-07-27 10:10:36.000000000 +0200
@@ -98,7 +98,7 @@
 strongarm*)	 targ_archs=bfd_arm_arch ;;
 thumb*)		 targ_archs=bfd_arm_arch ;;
 v850*)		 targ_archs=bfd_v850_arch ;;
-x86_64)		 targ_archs=bfd_i386_arch ;;
+x86_64*)		 targ_archs=bfd_i386_arch ;;
 xscale*)	 targ_archs=bfd_arm_arch ;;
 xtensa*)	 targ_archs=bfd_xtensa_arch ;;
 z80|r800)	 targ_archs=bfd_z80_arch ;;
@@ -562,6 +562,11 @@
     targ_defvec=bfd_elf64_x86_64_vec
     targ_selvecs="bfd_elf32_i386_vec i386linux_vec bfd_efi_app_ia32_vec"
     ;;
+  x86_64-*-mingw64*)
+    targ_defvec=x86_64pe_vec
+    targ_selvecs="x86_64pe_vec x86_64pei_vec x86_64coff_vec bfd_elf64_x86_64_vec"
+    targ_underscore=yes
+    ;;
 #endif
   i[3-7]86-*-lynxos*)
     targ_defvec=bfd_elf32_i386_vec
diff -rNbu binutils-2.17_org/bfd/configure binutils-2.17/bfd/configure
--- binutils-2.17_org/bfd/configure	2006-06-23 20:17:03.000000000 +0200
+++ binutils-2.17/bfd/configure	2006-08-03 16:38:05.000000000 +0200
@@ -4087,7 +4087,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -4114,6 +4114,9 @@
       ;;
     *64-bit*)
       case $host in
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
@@ -13216,6 +13219,7 @@
     i386aout_vec)		tb="$tb i386aout.lo aout32.lo" ;;
     i386bsd_vec)		tb="$tb i386bsd.lo aout32.lo" ;;
     i386coff_vec)		tb="$tb coff-i386.lo cofflink.lo" ;;
+    x86_64coff_vec)		tb="$tb coff-x86_64.lo cofflink.lo"; target_size=64 ;;
     i386dynix_vec)		tb="$tb i386dynix.lo aout32.lo" ;;
     i386freebsd_vec)		tb="$tb i386freebsd.lo aout32.lo" ;;
     i386linux_vec)		tb="$tb i386linux.lo aout32.lo" ;;
@@ -13226,7 +13230,9 @@
     i386netbsd_vec)		tb="$tb i386netbsd.lo aout32.lo" ;;
     i386os9k_vec)		tb="$tb i386os9k.lo aout32.lo" ;;
     i386pe_vec)			tb="$tb pe-i386.lo peigen.lo cofflink.lo" ;;
-    i386pei_vec)		tb="$tb pei-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pe_vec)			tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
+    i386pei_vec)		tb="$tb pei-i386.lo pepigen.lo cofflink.lo" ;;
+    x86_64pei_vec)		tb="$tb pei-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i860coff_vec)		tb="$tb coff-i860.lo cofflink.lo" ;;
     icoff_big_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
     icoff_little_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
diff -rNbu binutils-2.17_org/bfd/configure.in binutils-2.17/bfd/configure.in
--- binutils-2.17_org/bfd/configure.in	2006-06-23 20:17:07.000000000 +0200
+++ binutils-2.17/bfd/configure.in	2006-08-03 16:39:09.000000000 +0200
@@ -729,6 +729,7 @@
     i386aout_vec)		tb="$tb i386aout.lo aout32.lo" ;;
     i386bsd_vec)		tb="$tb i386bsd.lo aout32.lo" ;;
     i386coff_vec)		tb="$tb coff-i386.lo cofflink.lo" ;;
+    x86_64coff_vec)		tb="$tb coff-x86_64.lo cofflink.lo"; target_size=64 ;;
     i386dynix_vec)		tb="$tb i386dynix.lo aout32.lo" ;;
     i386freebsd_vec)		tb="$tb i386freebsd.lo aout32.lo" ;;
     i386linux_vec)		tb="$tb i386linux.lo aout32.lo" ;;
@@ -739,7 +740,9 @@
     i386netbsd_vec)		tb="$tb i386netbsd.lo aout32.lo" ;;
     i386os9k_vec)		tb="$tb i386os9k.lo aout32.lo" ;;
     i386pe_vec)			tb="$tb pe-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pe_vec)			tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i386pei_vec)		tb="$tb pei-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pei_vec)		tb="$tb pei-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i860coff_vec)		tb="$tb coff-i860.lo cofflink.lo" ;;
     icoff_big_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
     icoff_little_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
diff -rNbu binutils-2.17_org/bfd/libpei.h binutils-2.17/bfd/libpei.h
--- binutils-2.17_org/bfd/libpei.h	2005-05-04 17:53:35.000000000 +0200
+++ binutils-2.17/bfd/libpei.h	2006-08-09 10:42:53.000000000 +0200
@@ -204,6 +204,38 @@
 #define PUT_SCNHDR_LNNOPTR H_PUT_32
 #endif
 
+#ifdef COFF_WITH_pex64
+#define GET_OPTHDR_IMAGE_BASE H_GET_64
+#define PUT_OPTHDR_IMAGE_BASE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_RESERVE H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_RESERVE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_COMMIT H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_COMMIT H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_RESERVE H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_RESERVE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_COMMIT H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_COMMIT H_PUT_64
+#define GET_PDATA_ENTRY bfd_get_32
+
+#define _bfd_XX_bfd_copy_private_bfd_data_common	_bfd_pex64_bfd_copy_private_bfd_data_common
+#define _bfd_XX_bfd_copy_private_section_data		_bfd_pex64_bfd_copy_private_section_data
+#define _bfd_XX_get_symbol_info				_bfd_pex64_get_symbol_info
+#define _bfd_XX_only_swap_filehdr_out			_bfd_pex64_only_swap_filehdr_out
+#define _bfd_XX_print_private_bfd_data_common		_bfd_pex64_print_private_bfd_data_common
+#define _bfd_XXi_final_link_postscript			_bfd_pex64i_final_link_postscript
+#define _bfd_XXi_final_link_postscript			_bfd_pex64i_final_link_postscript
+#define _bfd_XXi_only_swap_filehdr_out			_bfd_pex64i_only_swap_filehdr_out
+#define _bfd_XXi_swap_aouthdr_in			_bfd_pex64i_swap_aouthdr_in
+#define _bfd_XXi_swap_aouthdr_out			_bfd_pex64i_swap_aouthdr_out
+#define _bfd_XXi_swap_aux_in				_bfd_pex64i_swap_aux_in
+#define _bfd_XXi_swap_aux_out				_bfd_pex64i_swap_aux_out
+#define _bfd_XXi_swap_lineno_in				_bfd_pex64i_swap_lineno_in
+#define _bfd_XXi_swap_lineno_out			_bfd_pex64i_swap_lineno_out
+#define _bfd_XXi_swap_scnhdr_out			_bfd_pex64i_swap_scnhdr_out
+#define _bfd_XXi_swap_sym_in				_bfd_pex64i_swap_sym_in
+#define _bfd_XXi_swap_sym_out				_bfd_pex64i_swap_sym_out
+
+#else /* !COFF_WITH_pex64 */
 #ifdef COFF_WITH_pep
 
 #define GET_OPTHDR_IMAGE_BASE H_GET_64
@@ -269,6 +301,7 @@
 #define _bfd_XXi_swap_sym_out				_bfd_pei_swap_sym_out
 
 #endif /* !COFF_WITH_pep */
+#endif /* !COFF_WITH_pex64 */
 
 /* Macro: Returns true if the bfd is a PE executable as opposed to a PE object file.  */
 #define bfd_pe_executable_p(abfd) \
diff -rNbu binutils-2.17_org/bfd/pe-x86_64.c binutils-2.17/bfd/pe-x86_64.c
--- binutils-2.17_org/bfd/pe-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/bfd/pe-x86_64.c	2006-09-06 12:23:54.000000000 +0200
@@ -0,0 +1,54 @@
+/* BFD back-end for Intel/AMD x86_64 PECOFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_SYM 		x86_64pe_vec
+#define TARGET_NAME 		"pe-x86-64"
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+#define PCRELOFFSET 		TRUE
+#define TARGET_UNDERSCORE 	'_'
+#define COFF_LONG_SECTION_NAMES
+#define COFF_SUPPORT_GNU_LINKONCE
+#define COFF_LONG_FILENAMES
+
+#define COFF_SECTION_ALIGNMENT_ENTRIES \
+{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
+
+#include "coff-x86_64.c"
diff -rNbu binutils-2.17_org/bfd/peXXigen.c binutils-2.17/bfd/peXXigen.c
--- binutils-2.17_org/bfd/peXXigen.c	2006-01-09 16:58:42.000000000 +0100
+++ binutils-2.17/bfd/peXXigen.c	2006-08-24 13:42:21.000000000 +0200
@@ -52,7 +52,7 @@
    on this code has a chance of getting something accomplished without
    wasting too much time.  */
 
-/* This expands into COFF_WITH_pe or COFF_WITH_pep depending on whether
+/* This expands into COFF_WITH_pe, COFF_WITH_pep, or COFF_WITH_pex64 depending on whether
    we're compiling for straight PE or PE+.  */
 #define COFF_WITH_XX
 
@@ -67,17 +67,21 @@
    within PE/PEI, so we get them from there.  FIXME: The lack of
    variance is an assumption which may prove to be incorrect if new
    PE/PEI targets are created.  */
+#ifdef COFF_WITH_pex64
+# include "coff/x86_64.h"
+#else
 #ifdef COFF_WITH_pep
 # include "coff/ia64.h"
 #else
 # include "coff/i386.h"
 #endif
+#endif
 
 #include "coff/pe.h"
 #include "libcoff.h"
 #include "libpei.h"
 
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
 # undef AOUTSZ
 # define AOUTSZ		PEPAOUTSZ
 # define PEAOUTHDR	PEPAOUTHDR
@@ -398,7 +402,7 @@
   aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry);
   aouthdr_int->text_start =
     GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   aouthdr_int->data_start =
     GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start);
@@ -454,7 +458,7 @@
   if (aouthdr_int->entry)
     {
       aouthdr_int->entry += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_int->entry &= 0xffffffff;
 #endif
     }
@@ -462,12 +466,12 @@
   if (aouthdr_int->tsize)
     {
       aouthdr_int->text_start += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_int->text_start &= 0xffffffff;
 #endif
     }
 
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   if (aouthdr_int->dsize)
     {
@@ -547,7 +551,7 @@
   if (aouthdr_in->tsize)
     {
       aouthdr_in->text_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->text_start &= 0xffffffff;
 #endif
     }
@@ -555,7 +559,7 @@
   if (aouthdr_in->dsize)
     {
       aouthdr_in->data_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->data_start &= 0xffffffff;
 #endif
     }
@@ -563,7 +567,7 @@
   if (aouthdr_in->entry)
     {
       aouthdr_in->entry -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->entry &= 0xffffffff;
 #endif
     }
@@ -660,7 +664,7 @@
   PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
 			  aouthdr_out->standard.text_start);
 
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
 			  aouthdr_out->standard.data_start);
@@ -1261,6 +1265,35 @@
 	    }
 
 	  /* Print HintName vector entries.  */
+#ifdef COFF_WITH_pex64
+	  for (j = 0; j < datasize; j += 8)
+	    {
+			unsigned long member = bfd_get_32(abfd,data+idx+j);
+			unsigned long member_high = bfd_get_32(abfd,data+idx+j+4);
+			if(!member && !member_high) break;
+	      if (member_high & 0x80000000)
+		fprintf (file, "\t%lx%08lx\t %4lx%08lx  <none>",
+			 member_high,member, member_high & 0x7fffffff,member);
+	      else
+		{
+		  int ordinal;
+		  char *member_name;
+
+		  ordinal = bfd_get_16 (abfd, data + member - adj);
+		  member_name = (char *) data + member - adj + 2;
+		  fprintf (file, "\t%04lx\t %4d  %s",member, ordinal, member_name);
+		  }
+
+	      /* If the time stamp is not zero, the import address
+		 table holds actual addresses.  */
+	      if (time_stamp != 0
+		  && first_thunk != 0
+		  && first_thunk != hint_addr)
+		fprintf (file, "\t%04lx",
+			 (long) bfd_get_32 (abfd, ft_data + ft_idx + j));
+	      fprintf (file, "\n");
+	    }
+#else
 	  for (j = 0; j < datasize; j += 4)
 	    {
 	      unsigned long member = bfd_get_32 (abfd, data + idx + j);
@@ -1290,9 +1323,9 @@
 		  && first_thunk != hint_addr)
 		fprintf (file, "\t%04lx",
 			 (long) bfd_get_32 (abfd, ft_data + ft_idx + j));
-
 	      fprintf (file, "\n");
 	    }
+#endif
 
 	  if (ft_allocated)
 	    free (ft_data);
@@ -1533,7 +1566,7 @@
 static bfd_boolean
 pe_print_pdata (bfd * abfd, void * vfile)
 {
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
 # define PDATA_ROW_SIZE	(3*8)
 #else
 # define PDATA_ROW_SIZE	(5*4)
@@ -1559,7 +1592,7 @@
 
   fprintf (file,
 	   _("\nThe Function Table (interpreted .pdata section contents)\n"));
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   fprintf (file,
 	   _(" vma:\t\t\tBegin Address    End Address      Unwind Info\n"));
 #else
@@ -1613,7 +1646,7 @@
       fprintf_vma (file, begin_addr); fputc (' ', file);
       fprintf_vma (file, end_addr); fputc (' ', file);
       fprintf_vma (file, eh_handler);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
       fputc (' ', file);
       fprintf_vma (file, eh_data); fputc (' ', file);
       fprintf_vma (file, prolog_end_addr);
diff -rNbu binutils-2.17_org/bfd/pei-x86_64.c binutils-2.17/bfd/pei-x86_64.c
--- binutils-2.17_org/bfd/pei-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/bfd/pei-x86_64.c	2006-09-06 12:23:58.000000000 +0200
@@ -0,0 +1,55 @@
+/* BFD back-end for Intel 386 PE IMAGE COFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_SYM 		x86_64pei_vec
+#define TARGET_NAME 		"pei-x86-64"
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+#define PCRELOFFSET 		TRUE
+#define TARGET_UNDERSCORE 	'_'
+#define COFF_LONG_SECTION_NAMES
+#define COFF_SUPPORT_GNU_LINKONCE
+#define COFF_LONG_FILENAMES
+
+#define COFF_SECTION_ALIGNMENT_ENTRIES \
+{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
+
+#include "coff-x86_64.c"
diff -rNbu binutils-2.17_org/bfd/peicode.h binutils-2.17/bfd/peicode.h
--- binutils-2.17_org/bfd/peicode.h	2005-05-04 17:53:37.000000000 +0200
+++ binutils-2.17/bfd/peicode.h	2006-08-24 13:03:13.000000000 +0200
@@ -183,8 +183,16 @@
 #ifdef COFF_IMAGE_WITH_PE
 # define coff_swap_filehdr_out _bfd_XXi_only_swap_filehdr_out
 #else
+#ifdef COFF_WITH_pex64
+#define coff_swap_filehdr_out _bfd_pex64_only_swap_filehdr_out
+#else
+#ifdef COFF_WITH_pep
+#define coff_swap_filehdr_out _bfd_pep_only_swap_filehdr_out
+#else
 # define coff_swap_filehdr_out _bfd_pe_only_swap_filehdr_out
 #endif
+#endif
+#endif
 
 static void
 coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
@@ -217,7 +225,9 @@
   if (scnhdr_int->s_vaddr != 0)
     {
       scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
+#ifndef COFF_WITH_pex64
       scnhdr_int->s_vaddr &= 0xffffffff;
+#endif
     }
 
 #ifndef COFF_NO_HACK_SCNHDR_SIZE
@@ -363,7 +373,6 @@
 #define coff_get_symbol_info _bfd_XX_get_symbol_info
 
 #ifdef COFF_IMAGE_WITH_PE
-\f
 /* Code to handle Microsoft's Image Library Format.
    Also known as LINK6 format.
    Documentation about this format can be found at:
@@ -405,8 +414,13 @@
 					+ NUM_ILF_SECTIONS * 9 \
 					+ STRING_SIZE_SIZE)
 #define SIZEOF_IDATA2		(5 * 4)
+#ifndef COFF_WITH_pex64
 #define SIZEOF_IDATA4		(1 * 4)
 #define SIZEOF_IDATA5		(1 * 4)
+#else
+#define SIZEOF_IDATA4		(2 * 4)
+#define SIZEOF_IDATA5		(2 * 4)
+#endif
 #define SIZEOF_IDATA6		(2 + strlen (symbol_name) + 1 + 1)
 #define SIZEOF_IDATA7		(strlen (source_dll) + 1 + 1)
 #define SIZEOF_ILF_SECTIONS     (NUM_ILF_SECTIONS * sizeof (struct coff_section_tdata))
@@ -655,6 +669,12 @@
     8, 2
   },
 #endif
+#ifdef AMD64MAGIC
+  { AMD64MAGIC,
+  { 0xff,0x25,0x00,0x00,0x00,0x00,0x90,0x90 },
+  8,2
+  },
+#endif
 
 #ifdef  MC68MAGIC
   { MC68MAGIC, { /* XXX fill me in */ }, 0, 0 },
@@ -830,8 +850,15 @@
 	/* XXX - treat as IMPORT_NAME ??? */
 	abort ();
 
+#ifndef COFF_WITH_pex64
       * (unsigned int *) id4->contents = ordinal | 0x80000000;
       * (unsigned int *) id5->contents = ordinal | 0x80000000;
+#else
+      * (unsigned int *) id4->contents = ordinal;
+	  ((unsigned int *) id4->contents)[1] = 0x80000000;
+      * (unsigned int *) id5->contents = ordinal;
+      ((unsigned int *) id5->contents)[1] = 0x80000000;
+#endif
     }
   else
     {
@@ -1070,7 +1097,11 @@
       magic = I386MAGIC;
 #endif
       break;
-
+	case IMAGE_FILE_MACHINE_AMD64:
+#ifdef AMD64MAGIC
+		magic=AMD64MAGIC;
+#endif
+		break;
     case IMAGE_FILE_MACHINE_M68K:
 #ifdef MC68AGIC
       magic = MC68MAGIC;
@@ -1255,7 +1286,6 @@
       bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
-
   /* Here is the hack.  coff_object_p wants to read filhsz bytes to
      pick up the COFF header for PE, see "struct external_PEI_filehdr"
      in include/coff/pe.h.  We adjust so that that will work. */
@@ -1265,7 +1295,6 @@
 	bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
-
   return coff_object_p (abfd);
 }
 
diff -rNbu binutils-2.17_org/bfd/targets.c binutils-2.17/bfd/targets.c
--- binutils-2.17_org/bfd/targets.c	2006-04-05 14:41:57.000000000 +0200
+++ binutils-2.17/bfd/targets.c	2006-08-04 11:57:02.000000000 +0200
@@ -782,6 +782,9 @@
 extern const bfd_target we32kcoff_vec;
 extern const bfd_target z80coff_vec;
 extern const bfd_target z8kcoff_vec;
+extern const bfd_target x86_64pe_vec;
+extern const bfd_target x86_64pei_vec;
+extern const bfd_target x86_64coff_vec;
 
 /* These are always included.  */
 extern const bfd_target srec_vec;
@@ -1019,6 +1022,11 @@
 #if 0
 	&i386dynix_vec,
 #endif
+#ifdef BFD64
+	&x86_64coff_vec,
+	&x86_64pe_vec,
+	&x86_64pei_vec,
+#endif
 	&i386freebsd_vec,
 #if 0
 	/* Since a.out files lack decent magic numbers, no way to recognize
diff -rNbu binutils-2.17_org/binutils/ChangeLog binutils-2.17/binutils/ChangeLog
--- binutils-2.17_org/binutils/ChangeLog	2006-06-12 15:05:03.000000000 +0200
+++ binutils-2.17/binutils/ChangeLog	2006-09-07 12:45:39.000000000 +0200
@@ -1,3 +1,22 @@
+2006-09-07	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* binutils/configure:	Add new target x86_64-pc-mingw64
+	* binutils/configure.in:	Add new target x86_64-pc-mingw64
+	* binutils/dlltool.c:	Adjust include for this target
+		DLLTOOL_MX86_64:	Added macro to handle target specific code
+		mname:					Added default target static as "i386:x86-64"
+		MX86:					Added macro for target ident
+		mtable:				Added target specific definitions
+		rvaafter:			Add handling of MX86
+		rvabefore:			Add handling of MX86
+		asmprefix:			Add handling of MX86
+	* binutils/testsuite/binutils-all/dlltool.exp:	Add support for target x86_64-pc-mingw64
+	* binutils/testsuite/binutils-all/objcopy.exp:	Add support for target x86_64-pc-mingw64
+	* binutils/testsuite/binutils-all/windres/windres.exp:	Add support for target x86_64-pc-mingw64
+	* binutils/testsuite/binutils-all/windres/lang.rc:	xfail it as long as there is no windows.h
+	* binutils/testsuite/binutils-all/windres/strtab1.rc:	xfail it as long as there is no windows.h
+	* binutils/testsuite/lib/utils-lib.exp:	Adjust executable prefix detection (as .exe)
+
 2006-06-07  Joseph S. Myers  <joseph@codesourcery.com>
 
 	* po/Make-in (pdf, ps): New dummy targets.
diff -rNbu binutils-2.17_org/binutils/configure binutils-2.17/binutils/configure
--- binutils-2.17_org/binutils/configure	2006-04-06 23:49:29.000000000 +0200
+++ binutils-2.17/binutils/configure	2006-08-08 15:57:54.000000000 +0200
@@ -10722,6 +10722,12 @@
 	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
 	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
 	  ;;
+	x86_64-*-mingw64*)
+  	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MX86_64"
+	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+	  ;;
 	i[3-7]86-*-interix)
 	  BUILD_DLLTOOL='$(DLLTOOL_PROG)'
 	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386"
diff -rNbu binutils-2.17_org/binutils/configure.in binutils-2.17/binutils/configure.in
--- binutils-2.17_org/binutils/configure.in	2006-04-06 23:49:29.000000000 +0200
+++ binutils-2.17/binutils/configure.in	2006-08-08 15:56:56.000000000 +0200
@@ -260,6 +260,14 @@
 	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
 	  ;;
 changequote(,)dnl
+	x86_64-*-mingw64*)
+changequote([,])dnl
+  	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MX86_64"
+	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+	  ;;
+changequote(,)dnl
 	i[3-7]86-*-interix)
 changequote([,])dnl
 	  BUILD_DLLTOOL='$(DLLTOOL_PROG)'
diff -rNbu binutils-2.17_org/binutils/dlltool.c binutils-2.17/binutils/dlltool.c
--- binutils-2.17_org/binutils/dlltool.c	2006-03-09 22:50:53.000000000 +0100
+++ binutils-2.17/binutils/dlltool.c	2006-08-24 09:51:46.000000000 +0200
@@ -261,6 +261,9 @@
 #include "coff/arm.h"
 #include "coff/internal.h"
 #endif
+#ifdef DLLTOOL_MX86_64
+#include "coff/x86_64.h"
+#endif
 
 /* Forward references.  */
 static char *look_for_prog (const char *, const char *, int);
@@ -396,6 +399,10 @@
 static const char *mname = "i386";
 #endif
 
+#ifdef DLLTOOL_MX86_64
+static const char *mname = "i386:x86-64";
+#endif
+
 #ifdef DLLTOOL_PPC
 static const char *mname = "ppc";
 #endif
@@ -629,6 +636,14 @@
     arm_jtab, sizeof (arm_jtab), 8
   }
   ,
+  {
+#define MX86 10
+    "i386:x86-64", ".byte", ".short", ".long", ".asciz", "#",
+    "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
+    "pe-x86-64",bfd_arch_i386,
+    i386_jtab, sizeof (i386_jtab), 2
+  }
+  ,
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 };
 
@@ -752,6 +767,7 @@
     {
     case MARM:
     case M386:
+	case MX86:
     case MPPC:
     case MTHUMB:
     case MARM_INTERWORK:
@@ -776,6 +792,7 @@
     {
     case MARM:
     case M386:
+	case MX86:
     case MPPC:
     case MTHUMB:
     case MARM_INTERWORK:
@@ -809,6 +826,7 @@
     case MARM_EPOC:
       break;
     case M386:
+	case MX86:
       /* Symbol names starting with ? do not have a leading underscore. */
       if (name && *name == '?')
         break;
@@ -1686,10 +1704,20 @@
   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
     {
       fprintf (filvar, "listone%d:\n", headindex);
-      for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
+	  for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ ) {
+#ifdef DLLTOOL_MX86_64
+	fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
+		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG);
+#else
 	fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
 		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
+#endif
+	  }
+#ifdef DLLTOOL_MX86_64
+      fprintf (filvar,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
       fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       headindex++;
     }
 
@@ -1698,10 +1726,20 @@
   for (headptr = import_list; headptr != NULL; headptr = headptr->next)
     {
       fprintf (filvar, "listtwo%d:\n", headindex);
-      for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
+	  for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ ) {
+#ifdef DLLTOOL_MX86_64
+	fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
+		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG);
+#else
 	fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
 		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
-      fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
+	  }
+#ifdef DLLTOOL_MX86_64
+      fprintf (filvar,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       headindex++;
     }
 
@@ -2374,6 +2412,36 @@
 	  /* An idata$4 or idata$5 is one word long, and has an
 	     rva to idata$6.  */
 
+#ifdef DLLTOOL_MX86_64
+	  si->data = xmalloc (8);
+	  si->size = 8;
+
+	  if (exp->noname)
+	    {
+	      si->data[0] = exp->ordinal ;
+	      si->data[1] = exp->ordinal >> 8;
+	      si->data[2] = exp->ordinal >> 16;
+		  si->data[3] = exp->ordinal >> 24;
+		  si->data[4] = 0;
+		  si->data[5] = 0;
+		  si->data[6] = 0;
+	      si->data[7] = 0x80;
+	    }
+	  else
+	    {
+	      sec->reloc_count = 1;
+	      memset (si->data, 0, si->size);
+	      rel = xmalloc (sizeof (arelent));
+	      rpp = xmalloc (sizeof (arelent *) * 2);
+	      rpp[0] = rel;
+	      rpp[1] = 0;
+	      rel->address = 0;
+	      rel->addend = 0;
+	      rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
+	      rel->sym_ptr_ptr = secdata[IDATA6].sympp;
+	      sec->orelocation = rpp;
+	    }
+#else
 	  si->data = xmalloc (4);
 	  si->size = 4;
 
@@ -2398,7 +2466,7 @@
 	      rel->sym_ptr_ptr = secdata[IDATA6].sympp;
 	      sec->orelocation = rpp;
 	    }
-
+#endif
 	  break;
 
 	case IDATA6:
@@ -2612,7 +2680,11 @@
   if (!no_idata5)
     {
       fprintf (f, "\t.section\t.idata$5\n");
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       fprintf (f, "fthunk:\n");
     }
 
@@ -2620,7 +2692,11 @@
     {
       fprintf (f, "\t.section\t.idata$4\n");
 
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       fprintf (f, "\t.section	.idata$4\n");
       fprintf (f, "hname:\n");
     }
@@ -2646,13 +2722,21 @@
   if (!no_idata4)
     {
       fprintf (f, "\t.section	.idata$4\n");
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
     }
 
   if (!no_idata5)
     {
       fprintf (f, "\t.section	.idata$5\n");
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
     }
 
 #ifdef DLLTOOL_PPC
diff -rNbu binutils-2.17_org/binutils/testsuite/binutils-all/dlltool.exp binutils-2.17/binutils/testsuite/binutils-all/dlltool.exp
--- binutils-2.17_org/binutils/testsuite/binutils-all/dlltool.exp	2005-05-08 16:17:40.000000000 +0200
+++ binutils-2.17/binutils/testsuite/binutils-all/dlltool.exp	2006-09-07 10:37:43.000000000 +0200
@@ -14,13 +14,14 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 
-if {![istarget "i*86-*-*"]} {
+if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw64*"] } {
     return
 }
 
 if {![istarget "i*86-*-*pe*"] \
     && ![istarget "i*86-*-cygwin*"] \
-    && ![istarget "i*86-*-mingw32*"] } {
+    && ![istarget "i*86-*-mingw32*"] \
+    && ![istarget "x86_64-*-mingw64*"] } {
     set target_xfail "yes"
 } else {
     set target_xfail "no"
diff -rNbu binutils-2.17_org/binutils/testsuite/binutils-all/objcopy.exp binutils-2.17/binutils/testsuite/binutils-all/objcopy.exp
--- binutils-2.17_org/binutils/testsuite/binutils-all/objcopy.exp	2005-10-20 19:06:40.000000000 +0200
+++ binutils-2.17/binutils/testsuite/binutils-all/objcopy.exp	2006-09-07 09:35:43.000000000 +0200
@@ -437,7 +437,7 @@
 
 # Build a final executable.
 
-if { [istarget *-*-cygwin] || [istarget *-*-mingw32] } {
+if { [istarget *-*-cygwin] || [istarget *-*-mingw32] || [istarget *-*-mingw64] } {
     set test_prog "testprog.exe"
 } else {
     set test_prog "testprog"
diff -rNbu binutils-2.17_org/binutils/testsuite/binutils-all/windres/lang.rc binutils-2.17/binutils/testsuite/binutils-all/windres/lang.rc
--- binutils-2.17_org/binutils/testsuite/binutils-all/windres/lang.rc	2001-07-19 01:56:41.000000000 +0200
+++ binutils-2.17/binutils/testsuite/binutils-all/windres/lang.rc	2006-09-07 10:26:02.000000000 +0200
@@ -1,3 +1,4 @@
+//#xfail *-*-mingw64
 #include "windows.h"
 
 LANGUAGE 0, 0
diff -rNbu binutils-2.17_org/binutils/testsuite/binutils-all/windres/strtab1.rc binutils-2.17/binutils/testsuite/binutils-all/windres/strtab1.rc
--- binutils-2.17_org/binutils/testsuite/binutils-all/windres/strtab1.rc	2001-07-19 01:56:41.000000000 +0200
+++ binutils-2.17/binutils/testsuite/binutils-all/windres/strtab1.rc	2006-09-07 10:27:10.000000000 +0200
@@ -1,4 +1,5 @@
-#include "windows.h"
+//#xfail *-*-mingw64
+#include <windows.h>
 
 LANGUAGE 0, 0
 
diff -rNbu binutils-2.17_org/binutils/testsuite/binutils-all/windres/windres.exp binutils-2.17/binutils/testsuite/binutils-all/windres/windres.exp
--- binutils-2.17_org/binutils/testsuite/binutils-all/windres/windres.exp	2005-05-08 16:17:41.000000000 +0200
+++ binutils-2.17/binutils/testsuite/binutils-all/windres/windres.exp	2006-09-07 10:20:21.000000000 +0200
@@ -19,13 +19,14 @@
 
 # Written by DJ Delorie <dj@redhat.com>
 
-if {![istarget "i*86-*-*"]} {
+if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw64"] } {
     return
 }
 
 if {![istarget "i*86-*-*pe*"] \
     && ![istarget "i*86-*-cygwin*"] \
-    && ![istarget "i*86-*-mingw32*"] } {
+    && ![istarget "i*86-*-mingw32*"] \
+    && ![istarget "x86_64-*-mingw64*"] } {
     set target_xfail "yes"
 } else {
     set target_xfail "no"
diff -rNbu binutils-2.17_org/binutils/testsuite/lib/utils-lib.exp binutils-2.17/binutils/testsuite/lib/utils-lib.exp
--- binutils-2.17_org/binutils/testsuite/lib/utils-lib.exp	2006-04-10 21:05:31.000000000 +0200
+++ binutils-2.17/binutils/testsuite/lib/utils-lib.exp	2006-09-07 09:40:57.000000000 +0200
@@ -161,7 +161,7 @@
 #	Returns target executable extension, if any.
 #
 proc exe_ext {} {
-    if { [istarget *-*-mingw32] || [istarget *-*-cygwin*] } {
+    if { [istarget *-*-mingw*] || [istarget *-*-cygwin*] } {
         return ".exe"
     } else {
         return ""
diff -rNbu binutils-2.17_org/config.guess binutils-2.17/config.guess
--- binutils-2.17_org/config.guess	2006-01-16 18:34:37.000000000 +0100
+++ binutils-2.17/config.guess	2006-07-26 15:22:53.000000000 +0200
@@ -777,6 +777,9 @@
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
 	exit ;;
+    i*:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
     i*:MINGW*:*)
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
diff -rNbu binutils-2.17_org/config.sub binutils-2.17/config.sub
--- binutils-2.17_org/config.sub	2006-01-16 18:34:37.000000000 +0100
+++ binutils-2.17/config.sub	2006-07-26 15:25:35.000000000 +0200
@@ -683,6 +683,10 @@
 		basic_machine=i386-pc
 		os=-mingw32
 		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
 	miniframe)
 		basic_machine=m68000-convergent
 		;;
@@ -1207,7 +1211,7 @@
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 	      | -chorusos* | -chorusrdb* \
 	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
 	      | -uxpv* | -beos* | -mpeix* | -udk* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
diff -rNbu binutils-2.17_org/configure binutils-2.17/configure
--- binutils-2.17_org/configure	2006-04-06 23:49:25.000000000 +0200
+++ binutils-2.17/configure	2006-07-26 15:29:08.000000000 +0200
@@ -1771,6 +1771,8 @@
     ;;
   *-mingw32*)
     ;;
+  *-mingw64*)
+    ;;
   *-interix*)
     host_makefile_frag="config/mh-interix"
     ;;
diff -rNbu binutils-2.17_org/gas/ChangeLog binutils-2.17/gas/ChangeLog
--- binutils-2.17_org/gas/ChangeLog	2006-06-12 15:05:03.000000000 +0200
+++ binutils-2.17/gas/ChangeLog	2006-09-07 12:58:59.000000000 +0200
@@ -1,3 +1,31 @@
+2006-09-07	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* gas/configure:		Add new target x86_64-pc-mingw64
+	* gas/configure.in:	Add new target x86_64-pc-mingw64
+	* gas/configure.tgt:	Add new target x86_64-pc-mingw64
+	* gas/config/obj-coff.h:	Add handling for TE_PEP target specific code and definitions
+	* gas/config/tc-i386.c:		Add new targets
+		md_parse_option:			Add targets to OPTION_64
+		x86_64_target_format:	Add new method for setup proper default target cpu mode
+	* gas/config/te-pep.h:		Add new target definition header
+		TE_PEP:				Identifies new target architecture
+		COFF_WITH_pex64:	Set proper includes in bfd
+	* gas/testsuite/i386/immed64.d:	Add #pass for avoid proplems with alignment paddings
+	* gas/testsuite/i386/rex.d:		Changed for target matching
+	* gas/testsuite/i386/x86-64-addr32.d:	Changed for target matching and padding
+	* gas/testsuite/i386/x86-64-branch.d:	Changed for target matching and padding
+	* gas/testsuite/i386/x86-64-crx-suffix.d:	Changed for target matching and padding
+	* gas/testsuite/i386/x86-64-crx.d:	Changed for target matching
+	* gas/testsuite/i386/x86-64-drx-suffix.d:	Changed for target matching and padding
+	* gas/testsuite/i386/x86-64-crx-suffix.d:	Changed for target matching and padding
+	* gas/testsuite/i386/x86-64-opcode.d:	Changed for target matching
+	* gas/testsuite/i386/x86-64-pcrel.d:	Changed for target matching and relocation fixing
+	* gas/testsuite/i386/x86-64-rip.d:	Changed for target matching and padding
+	* gas/testsuite/i386/x86-64-stack-intel.d:	Changed for target matching and padding
+	* gas/testsuite/i386/x86-64-stack-suffix.d:	Changed for target matching and padding
+	* gas/testsuite/i386/x86-64-stack.d:	Changed for target matching and padding
+	* gas/testsuite/i386/x86_64.d:	Changed section specifier to .text
+
 2006-06-07  Joseph S. Myers  <joseph@codesourcery.com>
 
 	* po/Make-in (pdf, ps): New dummy targets.
diff -rNbu binutils-2.17_org/gas/config/obj-coff.h binutils-2.17/gas/config/obj-coff.h
--- binutils-2.17_org/gas/config/obj-coff.h	2006-08-03 15:18:32.000000000 +0200
+++ binutils-2.17/gas/config/obj-coff.h	2006-09-05 15:35:16.000000000 +0200
@@ -57,24 +57,30 @@
 #endif
 
 #ifdef TC_I386
-#ifdef TE_PEP
-#include "coff/x86_64.h"
-#else
+#ifndef TE_PEP
 #include "coff/i386.h"
+#else
+#include "coff/x86_64.h"
 #endif
 
 #ifdef TE_PE
-#ifndef TE_PEP
-#define TARGET_FORMAT "pe-i386"
+#ifdef TE_PEP
+extern const char *x86_64_target_format PARAMS ((void));
+#define TARGET_FORMAT x86_64_target_format ()
+#define COFF_TARGET_FORMAT "pe-x86-64"
 #else
-#define TARGET_FORMAT "pe-x86-64"
+#define TARGET_FORMAT "pe-i386"
 #endif
 #endif
 
 #ifndef TARGET_FORMAT
+#ifdef TE_PEP
+#define TARGET_FORMAT "coff-x86-64"
+#else
 #define TARGET_FORMAT "coff-i386"
 #endif
 #endif
+#endif
 
 #ifdef TC_M68K
 #include "coff/m68k.h"
diff -rNbu binutils-2.17_org/gas/config/tc-i386.c binutils-2.17/gas/config/tc-i386.c
--- binutils-2.17_org/gas/config/tc-i386.c	2006-04-07 08:40:57.000000000 +0200
+++ binutils-2.17/gas/config/tc-i386.c	2006-09-05 15:39:13.000000000 +0200
@@ -5420,9 +5420,9 @@
 
 struct option md_longopts[] = {
   {"32", no_argument, NULL, OPTION_32},
-#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+//#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
   {"64", no_argument, NULL, OPTION_64},
-#endif
+//#endif
   {"divide", no_argument, NULL, OPTION_DIVIDE},
   {NULL, no_argument, NULL, 0}
 };
@@ -5463,13 +5463,16 @@
 	 .stab instead of .stab.excl.  We always use .stab anyhow.  */
       break;
 
+#endif
+
     case OPTION_64:
       {
 	const char **list, **l;
 
 	list = bfd_target_list ();
 	for (l = list; *l != NULL; l++)
-	  if (strcmp (*l, "elf64-x86-64") == 0)
+	  if (strcmp (*l, "elf64-x86-64") == 0 || strcmp(*l,"coff-x86-64")==0 || strcmp(*l,"pe-x86-64")==0 ||
+		  strcmp(*l,"pei-x86-64")==0)
 	    {
 	      default_arch = "x86_64";
 	      break;
@@ -5479,7 +5482,6 @@
 	free (list);
       }
       break;
-#endif
 
     case OPTION_32:
       default_arch = "i386";
@@ -5534,9 +5536,24 @@
 #endif
 }
 
+#if defined(TE_PEP)
+const char *x86_64_target_format(void)
+{
+	if (!strcmp (default_arch, "x86_64")) {
+		set_code_flag (CODE_64BIT);
+		return COFF_TARGET_FORMAT;
+	} else if (!strcmp (default_arch, "i386")) {
+		set_code_flag (CODE_32BIT);
+		return "coff-i386";
+	} else
+		as_fatal (_("Unknown architecture"));
+	abort ();
+	return NULL;
+}
+#endif
+
 #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
      || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))
-
 /* Pick the target format to use.  */
 
 const char *
diff -rNbu binutils-2.17_org/gas/config/te-pep.h binutils-2.17/gas/config/te-pep.h
--- binutils-2.17_org/gas/config/te-pep.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/gas/config/te-pep.h	2006-09-05 14:02:20.000000000 +0200
@@ -0,0 +1,11 @@
+#define TE_PEP
+//#define COFF_WITH_PE
+#define COFF_WITH_pex64
+
+#define TE_PE
+#define LEX_AT (LEX_BEGIN_NAME | LEX_NAME) /* Can have @'s inside labels.  */
+
+/* The PE format supports long section names.  */
+#define COFF_LONG_SECTION_NAMES
+
+#include "obj-format.h"
diff -rNbu binutils-2.17_org/gas/configure binutils-2.17/gas/configure
--- binutils-2.17_org/gas/configure	2006-04-06 23:49:31.000000000 +0200
+++ binutils-2.17/gas/configure	2006-09-05 14:39:30.000000000 +0200
@@ -3922,7 +3922,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -3936,6 +3936,9 @@
         x86_64-*linux*)
           LD="${LD-ld} -m elf_i386"
           ;;
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_i386"
+          ;;
         ppc64-*linux*|powerpc64-*linux*)
           LD="${LD-ld} -m elf32ppclinux"
           ;;
@@ -3952,6 +3955,9 @@
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         ppc*-*linux*|powerpc*-*linux*)
           LD="${LD-ld} -m elf64ppc"
           ;;
@@ -4950,6 +4956,11 @@
 #define I386COFF 1
 _ACEOF
  ;;
+      x86_64)
+cat >>confdefs.h <<\_ACEOF
+#define I386COFF 1
+_ACEOF
+ ;;
       m68k)
 cat >>confdefs.h <<\_ACEOF
 #define M68KCOFF 1
diff -rNbu binutils-2.17_org/gas/configure.in binutils-2.17/gas/configure.in
--- binutils-2.17_org/gas/configure.in	2006-04-06 23:49:33.000000000 +0200
+++ binutils-2.17/gas/configure.in	2006-09-05 14:40:36.000000000 +0200
@@ -417,6 +417,19 @@
       ;;
     esac
   ;;
+  x86_64)
+    case ${obj_format} in
+    aout)
+      emulations="$emulations i386coff i386elf"
+      ;;
+    coff)
+      emulations="$emulations i386aout i386elf"
+    ;;
+    elf)
+      emulations="$emulations i386aout i386coff"
+      ;;
+    esac
+  ;;
   esac
 fi
 
@@ -460,6 +473,7 @@
   coff)
     case ${target_cpu_type} in
       i386) AC_DEFINE(I386COFF, 1, [Using i386 COFF?]) ;;
+      x86_64) AC_DEFINE(I386COFF, 1, [Using i386 COFF?]) ;;
       m68k) AC_DEFINE(M68KCOFF, 1, [Using m68k COFF?]) ;;
       m88k) AC_DEFINE(M88KCOFF, 1, [Using m88k COFF?]) ;;
     esac
diff -rNbu binutils-2.17_org/gas/configure.tgt binutils-2.17/gas/configure.tgt
--- binutils-2.17_org/gas/configure.tgt	2006-04-05 14:41:57.000000000 +0200
+++ binutils-2.17/gas/configure.tgt	2006-08-03 14:15:58.000000000 +0200
@@ -77,7 +77,7 @@
   strongarm*b)		cpu_type=arm endian=big ;;
   strongarm*)		cpu_type=arm endian=little ;;
   v850*)		cpu_type=v850 ;;
-  x86_64)		cpu_type=i386 arch=x86_64;;
+  x86_64*)		cpu_type=i386 arch=x86_64;;
   xscale*be|xscale*b)	cpu_type=arm endian=big ;;
   xscale*)		cpu_type=arm endian=little ;;
   xtensa*)		cpu_type=xtensa arch=xtensa ;;
@@ -87,6 +87,8 @@
 
 # Assign object format.  Set fmt, em, and bfd_gas.
 generic_target=${cpu_type}-$vendor-$os
+echo "$$$$: info: GAS want support target CPU ${generic_target}" >&2;
+
 # Note: This table is alpha-sorted, please try to keep it that way.
 case ${generic_target} in
   alpha-*-*vms*)			fmt=evax ;;
@@ -210,6 +212,7 @@
   i386-*-cygwin*)			fmt=coff em=pe ;;
   i386-*-interix*)			fmt=coff em=interix ;;
   i386-*-mingw32*)			fmt=coff em=pe ;;
+  i386-*-mingw64*)			fmt=coff em=pep ;;
   i386-*-nto-qnx*)			fmt=elf ;;
   i386-*-*nt*)				fmt=coff em=pe ;;
   i386-*-chaos)				fmt=elf ;;
diff -rNbu binutils-2.17_org/gas/testsuite/gas/all/gas.exp binutils-2.17/gas/testsuite/gas/all/gas.exp
--- binutils-2.17_org/gas/testsuite/gas/all/gas.exp	2005-11-21 05:30:32.000000000 +0100
+++ binutils-2.17/gas/testsuite/gas/all/gas.exp	2006-09-07 14:31:35.000000000 +0200
@@ -207,6 +207,7 @@
      || [istarget i*86-*-isc*] \
      || [istarget i*86-*-go32*] \
      || [istarget i*86-*-cygwin*] \
+     || [istarget x86_64-*-mingw64*] \
      || [istarget i*86-*-*nt] \
      || [istarget i*86-*-interix*] \
      || ([istarget i960-*-vxworks5.*] && ![istarget i960-*-vxworks5.0*]) } {
@@ -249,7 +250,7 @@
 
 if {  ([istarget "i*86-*-*pe*"] && ![istarget "i*86-*-openbsd*"]) \
     || [istarget "i*86-*-cygwin*"] \
-    || [istarget "i*86-*-mingw32*"] } {
+    || [istarget "i*86-*-mingw*"] } {
   gas_test "fastcall.s" ""   "" "fastcall labels"
 }
 
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/immed64.d binutils-2.17/gas/testsuite/gas/i386/immed64.d
--- binutils-2.17_org/gas/testsuite/gas/i386/immed64.d	2005-07-26 17:34:11.000000000 +0200
+++ binutils-2.17/gas/testsuite/gas/i386/immed64.d	2006-09-06 13:07:53.000000000 +0200
@@ -57,3 +57,4 @@
 [ 	]*[0-9a-fA-F]+:[ 	]+e5 04[ 	]+inl? +\$0x4,%eax
 [ 	]*[0-9a-fA-F]+:[ 	]+e5 08[ 	]+inl? +\$0x8,%eax
 [ 	]*[0-9a-fA-F]+:[ 	]+e5 00[ 	]+inl? +\$0x0,%eax
+#pass
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/rex.d binutils-2.17/gas/testsuite/gas/i386/rex.d
--- binutils-2.17_org/gas/testsuite/gas/i386/rex.d	2005-12-14 09:57:06.000000000 +0100
+++ binutils-2.17/gas/testsuite/gas/i386/rex.d	2006-09-06 13:12:44.000000000 +0200
@@ -1,7 +1,7 @@
 #objdump: -dw
 #name: x86-64 manual rex prefix use
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-addr32.d binutils-2.17/gas/testsuite/gas/i386/x86-64-addr32.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-addr32.d	2004-07-21 18:09:43.000000000 +0200
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-addr32.d	2006-09-06 11:11:33.000000000 +0200
@@ -2,12 +2,13 @@
 #objdump: -drw
 #name: x86-64 32-bit addressing
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
-0+000 <.text>:
+0+ <.text>:
 [	 ]*0:[	 ]+67 48 8d 80 00 00 00 00[	 ]+addr32[	 ]+lea[ 	]+0x0\(%[re]ax\),%rax.*
-[	 ]*8:[	 ]+67 49 8d 80 00 00 00 00[	 ]+addr32[	 ]+lea[ 	]+0x0\(%r8d?\),%rax.*
+[	 ]*8:[	 ]+67 49 8d 80 00 00 00 00[	 ]+addr32[	 ]+lea[ 	]+0x0\(%r8d\),%rax.*
 [	 ]*10:[	 ]+67 48 8d 05 00 00 00 00[	 ]+addr32[	 ]+lea[ 	]+0\(%[re]ip\),%rax.*
 [	 ]*18:[	 ]+67 48 8d 04 25 00 00 00 00[	 ]+addr32[	 ]+lea[ 	]+0x0,%rax.*
+#pass
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-branch.d binutils-2.17/gas/testsuite/gas/i386/x86-64-branch.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-branch.d	2005-05-07 15:30:02.000000000 +0200
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-branch.d	2006-09-06 13:04:24.000000000 +0200
@@ -2,7 +2,7 @@
 #objdump: -drw
 #name: x86-64 indirect branch
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -11,3 +11,4 @@
 [	 ]*2:[	 ]+ff d0[	 ]+callq[	 ]+\*%rax
 [	 ]*4:[	 ]+ff e0[	 ]+jmpq[	 ]+\*%rax
 [	 ]*6:[	 ]+ff e0[	 ]+jmpq[	 ]+\*%rax
+#pass
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-crx-suffix.d binutils-2.17/gas/testsuite/gas/i386/x86-64-crx-suffix.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-crx-suffix.d	2006-02-12 18:26:21.000000000 +0100
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-crx-suffix.d	2006-09-06 13:09:39.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 control register related opcodes (with suffixes)
 #source: x86-64-crx.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -19,3 +19,4 @@
 [ 	]*[0-9a-f]+:	44 0f 20 c7[ 	]+movq[ 	]+?%cr8,%rdi
 [ 	]*[0-9a-f]+:	44 0f 22 c0[ 	]+movq[ 	]+?%rax,%cr8
 [ 	]*[0-9a-f]+:	44 0f 22 c7[ 	]+movq[ 	]+?%rdi,%cr8
+#pass
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-crx.d binutils-2.17/gas/testsuite/gas/i386/x86-64-crx.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-crx.d	2006-02-11 18:00:58.000000000 +0100
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-crx.d	2006-09-06 13:08:20.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 control register related opcodes
 #source: x86-64-crx.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-drx-suffix.d binutils-2.17/gas/testsuite/gas/i386/x86-64-drx-suffix.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-drx-suffix.d	2006-02-11 19:08:35.000000000 +0100
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-drx-suffix.d	2006-09-06 13:11:04.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 debug register related opcodes (with suffixes)
 #source: x86-64-drx.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -19,3 +19,4 @@
 [ 	]*[0-9a-f]+:	44 0f 21 c7[ 	]+movq[ 	]+?%db8,%rdi
 [ 	]*[0-9a-f]+:	44 0f 23 c0[ 	]+movq[ 	]+?%rax,%db8
 [ 	]*[0-9a-f]+:	44 0f 23 c7[ 	]+movq[ 	]+?%rdi,%db8
+#pass
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-drx.d binutils-2.17/gas/testsuite/gas/i386/x86-64-drx.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-drx.d	2006-02-11 19:08:35.000000000 +0100
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-drx.d	2006-09-06 13:10:43.000000000 +0200
@@ -1,7 +1,7 @@
 #objdump: -dw
 #name: x86-64 debug register related opcodes
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -18,3 +18,4 @@
 [ 	]*[0-9a-f]+:	44 0f 21 c7[ 	]+movq?[ 	]+?%db8,%rdi
 [ 	]*[0-9a-f]+:	44 0f 23 c0[ 	]+movq?[ 	]+?%rax,%db8
 [ 	]*[0-9a-f]+:	44 0f 23 c7[ 	]+movq?[ 	]+?%rdi,%db8
+#pass
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-opcode.d binutils-2.17/gas/testsuite/gas/i386/x86-64-opcode.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-opcode.d	2005-03-29 21:30:47.000000000 +0200
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-opcode.d	2006-09-06 11:13:54.000000000 +0200
@@ -2,7 +2,7 @@
 #objdump: -drw
 #name: x86-64 opcode
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-pcrel.d binutils-2.17/gas/testsuite/gas/i386/x86-64-pcrel.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-pcrel.d	2005-06-17 10:03:58.000000000 +0200
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-pcrel.d	2006-09-06 12:56:52.000000000 +0200
@@ -1,16 +1,16 @@
 #objdump: -drw
 #name: x86-64 pcrel
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
 0+000 <_start>:
-[	 ]*[0-9a-f]+:[	 ]+b0 00[	 ]+movb?[	 ]+\$(0x)?0,%al[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC8[	 ]+xtrn\+(0x)?1
-[	 ]*[0-9a-f]+:[	 ]+66 b8 00 00[	 ]+movw?[	 ]+\$(0x)?0,%ax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC16[	 ]+xtrn\+(0x)?2
-[	 ]*[0-9a-f]+:[	 ]+b8( 00){4}[	 ]+movl?[	 ]+\$(0x)?0,%eax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn\+(0x)?1
-[	 ]*[0-9a-f]+:[	 ]+48 c7 c0( 00){4}[	 ]+movq?[	 ]+\$(0x)?0,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn\+(0x)?3
-[	 ]*[0-9a-f]+:[	 ]+48 b8( 00){8}[	 ]+mov(abs)?q?[	 ]+\$(0x)?0,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC64[	 ]+xtrn\+(0x)?2
+[	 ]*[0-9a-f]+:[	 ]+b0 0[02]+[	 ]+movb?[	 ]+\$(0x)?[02]+,%al[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC8[	 ]+xtrn(\+(0x)?1)?
+[	 ]*[0-9a-f]+:[	 ]+66 b8 0[04]+ 00[	 ]+movw?[	 ]+\$(0x)?[04]+,%ax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC16[	 ]+xtrn(\+(0x)?2)?
+[	 ]*[0-9a-f]+:[	 ]+b8 0[05]+( 00){3}[	 ]+movl?[	 ]+\$(0x)?[05]+,%eax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn(\+(0x)?1)?
+[	 ]*[0-9a-f]+:[	 ]+48 c7 c0 0[07]+( 00){3}[	 ]+movq?[	 ]+\$(0x)?[07]+,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn(\+(0x)?3)?
+[	 ]*[0-9a-f]+:[	 ]+48 b8 0[0a]+( 00){7}[	 ]+mov(abs)?q?[	 ]+\$(0x)?[0a]+,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC64[	 ]+xtrn(\+(0x)?2)?
 [	 ]*[0-9a-f]+:[	 ]+b0 00[	 ]+movb?[	 ]+\$(0x)?0,%al[	 ]*[0-9a-f]+:[	 ]+R_X86_64_8[	 ]+xtrn
 [	 ]*[0-9a-f]+:[	 ]+66 b8 00 00[	 ]+movw?[	 ]+\$(0x)?0,%ax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_16[	 ]+xtrn
 [	 ]*[0-9a-f]+:[	 ]+b8( 00){4}[	 ]+movl?[	 ]+\$(0x)?0,%eax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_32[	 ]+xtrn
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-rip.d binutils-2.17/gas/testsuite/gas/i386/x86-64-rip.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-rip.d	2004-07-21 18:09:43.000000000 +0200
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-rip.d	2006-09-06 12:59:43.000000000 +0200
@@ -2,7 +2,7 @@
 #objdump: -drw
 #name: x86-64 rip addressing
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -11,3 +11,4 @@
 [	 ]*6:[	 ]+8d 05 11 11 11 11[	 ]+lea[	 ]+286331153\(%rip\),%eax[ 	]*(#.*)?
 [	 ]*c:[	 ]+8d 05 01 00 00 00[	 ]+lea[	 ]+1\(%rip\),%eax[ 	]*(#.*)?
 [	 ]*12:[	 ]+8d 05 00 00 00 00[	 ]+lea[	 ]+0\(%rip\),%eax[ 	]*(#.*)?
+#pass
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-stack-intel.d binutils-2.17/gas/testsuite/gas/i386/x86-64-stack-intel.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-stack-intel.d	2005-09-28 17:34:51.000000000 +0200
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-stack-intel.d	2006-09-06 13:01:26.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 stack-related opcodes (Intel mode)
 #source: x86-64-stack.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-stack-suffix.d binutils-2.17/gas/testsuite/gas/i386/x86-64-stack-suffix.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-stack-suffix.d	2005-09-28 17:34:51.000000000 +0200
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-stack-suffix.d	2006-09-06 13:01:42.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 stack-related opcodes (with suffixes)
 #source: x86-64-stack.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86-64-stack.d binutils-2.17/gas/testsuite/gas/i386/x86-64-stack.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86-64-stack.d	2005-09-28 17:34:51.000000000 +0200
+++ binutils-2.17/gas/testsuite/gas/i386/x86-64-stack.d	2006-09-06 13:01:06.000000000 +0200
@@ -1,7 +1,7 @@
 #objdump: -dw
 #name: x86-64 stack-related opcodes
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils-2.17_org/gas/testsuite/gas/i386/x86_64.d binutils-2.17/gas/testsuite/gas/i386/x86_64.d
--- binutils-2.17_org/gas/testsuite/gas/i386/x86_64.d	2006-03-07 21:18:05.000000000 +0100
+++ binutils-2.17/gas/testsuite/gas/i386/x86_64.d	2006-09-06 10:56:33.000000000 +0200
@@ -6,7 +6,7 @@
 
 Disassembly of section .text:
 
-0+ <bar-0x1a7>:
+0+ <.text>:
 [ 	]+0:	01 ca[ 	]+add[ 	]+%ecx,%edx
 [ 	]+2:	44 01 ca[ 	]+add[ 	]+%r9d,%edx
 [ 	]+5:	41 01 ca[ 	]+add[ 	]+%ecx,%r10d
diff -rNbu binutils-2.17_org/include/ChangeLog binutils-2.17/include/ChangeLog
--- binutils-2.17_org/include/ChangeLog	2006-04-12 20:41:45.000000000 +0200
+++ binutils-2.17/include/ChangeLog	2006-09-07 13:01:19.000000000 +0200
@@ -1,3 +1,14 @@
+2006-09-07	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* include/coff/external.h:	Add proper external_aouthdr64 structure (without data_start member)
+		AOUTHDRSZ64:	Set according structure size
+		AOUTHDR64:		As typedef of external_aouthdr64 structure
+	* include/coff/internal.h:	Add relocation identifiers for coff
+	* include/coff/pe.h:	Add define IMAGE_FILE_MACHINE_AMD64 the coff signature
+		PEPAOUTHDR:		Adjust structure to have proper size (using AOUTHDR64)
+		PEPAOUTSZ:		Calculated size of 240
+	* include/coff/x86_64.h:	Coff information for x86_64 (AMD64)
+
 2006-04-11  Jim Blandy  <jimb@codesourcery.com>
 
 	* libiberty.h (pex_input_file, pex_input_pipe): New declarations.
diff -rNbu binutils-2.17_org/include/coff/external.h binutils-2.17/include/coff/external.h
--- binutils-2.17_org/include/coff/external.h	2005-05-10 12:21:09.000000000 +0200
+++ binutils-2.17/include/coff/external.h	2006-08-07 13:08:59.000000000 +0200
@@ -55,6 +55,20 @@
 
 #define AOUTHDRSZ 28
 #define AOUTSZ 28
+
+typedef struct external_aouthdr64
+  {
+    char magic[2];	/* type of file				*/
+    char vstamp[2];	/* version stamp			*/
+    char tsize[4];	/* text size in bytes, padded to FW bdry*/
+    char dsize[4];	/* initialized data "  "		*/
+    char bsize[4];	/* uninitialized data "   "		*/
+    char entry[4];	/* entry pt.				*/
+    char text_start[4];	/* base of text used for this file 	*/
+  }
+AOUTHDR64;
+#define AOUTHDRSZ64	24
+
 #endif
 
 #ifndef DO_NOT_DEFINE_SCNHDR
diff -rNbu binutils-2.17_org/include/coff/internal.h binutils-2.17/include/coff/internal.h
--- binutils-2.17_org/include/coff/internal.h	2006-02-05 12:57:34.000000000 +0100
+++ binutils-2.17/include/coff/internal.h	2006-09-06 12:14:25.000000000 +0200
@@ -604,6 +604,24 @@
   unsigned long r_offset;	/* Used by Alpha ECOFF, SPARC, others */
 };
 
+/* X86-64 relocations */
+#define R_AMD64_ABS 0 /* Reference is absolute, no relocation is necessary */
+#define R_AMD64_DIR64	1 /* 64-bit address (VA) */
+#define R_AMD64_DIR32	2 /* 32-bit address (VA) R_DIR32 */
+#define R_AMD64_IMAGEBASE	 3 /* 32-bit absolute ref w/o base R_IMAGEBASE */
+#define R_AMD64_PCRLONG		 4 /* 32-bit relative address from byte following reloc R_PCRLONG */
+#define R_AMD64_PCRLONG_1		 5 /* 32-bit relative address from byte distance 1 from reloc */
+#define R_AMD64_PCRLONG_2		 6 /* 32-bit relative address from byte distance 2 from reloc */
+#define R_AMD64_PCRLONG_3		 7 /* 32-bit relative address from byte distance 3 from reloc */
+#define R_AMD64_PCRLONG_4		 8 /* 32-bit relative address from byte distance 4 from reloc */
+#define R_AMD64_PCRLONG_5		 9 /* 32-bit relative address from byte distance 5 from reloc */
+#define R_AMD64_SECTION	10 /* Section index */
+#define R_AMD64_SECREL	11 /* 32 bit offset from base of section containing target R_SECREL*/
+#define R_AMD64_SECREL7	12 /* 7 bit unsigned offset from base of section containing target */
+#define R_AMD64_TOKEN	13 /* 32 bit metadata token */
+/* Pseude PC64 relocation - note not specified by MS/AMD but need for gas */
+#define R_AMD64_PCRQUAD	14
+
 #define R_DIR16 	 1
 #define R_REL24          5
 #define R_DIR32 	 6
diff -rNbu binutils-2.17_org/include/coff/pe.h binutils-2.17/include/coff/pe.h
--- binutils-2.17_org/include/coff/pe.h	2005-05-10 12:21:09.000000000 +0200
+++ binutils-2.17/include/coff/pe.h	2006-08-07 13:08:12.000000000 +0200
@@ -119,6 +119,7 @@
 #define IMAGE_FILE_MACHINE_THUMB             0x01c2
 #define IMAGE_FILE_MACHINE_TRICORE           0x0520
 #define IMAGE_FILE_MACHINE_WCEMIPSV2         0x0169
+#define IMAGE_FILE_MACHINE_AMD64             0x8664  // AMD64 (K8)
 
 #define IMAGE_SUBSYSTEM_UNKNOWN			 0
 #define IMAGE_SUBSYSTEM_NATIVE			 1
@@ -233,7 +234,6 @@
 typedef struct 
 {
   AOUTHDR standard;
-
   /* NT extra fields; see internal.h for descriptions.  */
   char  ImageBase[4];
   char  SectionAlignment[4];
@@ -267,7 +267,7 @@
    of just 4 bytes long.  */
 typedef struct 
 {
-  AOUTHDR standard;
+  AOUTHDR64 standard;
 
   /* NT extra fields; see internal.h for descriptions.  */
   char  ImageBase[8];
@@ -294,7 +294,7 @@
   /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];  */
   char  DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars.  */
 } PEPAOUTHDR;
-#define PEPAOUTSZ	240
+#define PEPAOUTSZ	(AOUTHDRSZ64+196+5*4) /* 240 */
   
 #undef  E_FILNMLEN
 #define E_FILNMLEN	18	/* # characters in a file name.  */
diff -rNbu binutils-2.17_org/include/coff/x86_64.h binutils-2.17/include/coff/x86_64.h
--- binutils-2.17_org/include/coff/x86_64.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/include/coff/x86_64.h	2006-08-17 09:12:24.000000000 +0200
@@ -0,0 +1,67 @@
+/* coff information for AMD 64.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#define L_LNNO_SIZE 2
+#define INCLUDE_COMDAT_FIELDS_IN_AUXENT
+#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
+ 	F_AR32WR	file has byte ordering of an AR32WR machine (e.g. vax).  */
+
+#define F_RELFLG	(0x0001)
+#define F_EXEC		(0x0002)
+#define F_LNNO		(0x0004)
+#define F_LSYMS		(0x0008)
+
+#define AMD64MAGIC	0x8664
+
+#define AMD64BADMAG(x)	( (x).f_magic != AMD64MAGIC)
+#define IMAGE_NT_OPTIONAL_HDR64_MAGIC      0x20b
+
+#define OMAGIC          0404    /* object files, eg as output */
+#define ZMAGIC          IMAGE_NT_OPTIONAL_HDR64_MAGIC    /* demand load format, eg normal ld output 0x10b */
+#define STMAGIC		0401	/* target shlib */
+#define SHMAGIC		0443	/* host   shlib */
+
+/* define some NT default values */
+/*  #define NT_IMAGE_BASE        0x400000 moved to internal.h */
+#define NT_SECTION_ALIGNMENT 0x1000
+#define NT_FILE_ALIGNMENT    0x200
+#define NT_DEF_RESERVE       0x100000
+#define NT_DEF_COMMIT        0x1000
+
+/********************** 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 -rNbu binutils-2.17_org/ld/ChangeLog binutils-2.17/ld/ChangeLog
--- binutils-2.17_org/ld/ChangeLog	2006-06-12 15:07:28.000000000 +0200
+++ binutils-2.17/ld/ChangeLog	2006-09-07 14:20:04.000000000 +0200
@@ -1,3 +1,25 @@
+2006-09-07	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* ld/configure:		Add new target x86_64-pc-mingw64
+	* ld/configure.tgt:	Add definition of target emulation i386pep
+	* ld/makefile.am:		Add new target files for target-all
+	* ld/makefile.in:		Add new target files for target-all
+	* ld/pep_dll.c:		Add target specific shared object handling
+	* ld/pep_dll.h:		Add target specific definitions for shared object handling
+	* ld/emulparams/i386pep.sh: Add new emulation params for target x86_64 coff
+	* ld/emultempl/pep.em:	Add new emulation file for target x86_64 coff
+	* ld/po/potfiles.in:		Add pepdll.c and pepdll.h
+	* ld/scripttempl/pep.sc: Add linker script template for target x86_64 coff
+	* ld/testsuite/bootstrap/bootstrap.exp:		Enable target test
+	* ld/testsuite/ld-fastcall/fastcall.exp:		Enable target test
+	* ld/testsuite/ld-scripts/align.exp:		Enable target test
+	* ld/testsuite/ld-scripts/align2a.d:		Enable target test
+	* ld/testsuite/ld-scripts/defined.exp:		Enable target test
+	* ld/testsuite/ld-scripts/provide.exp:		Enable target test
+	* ld/testsuite/ld-scripts/script.exp:		Enable target test
+	* ld/testsuite/ld-scripts/weak.exp:		Enable target test
+	* ld/testsuite/lib/ld-lib.exp:		Detect target as pecoff file format
+	
 2006-06-12  Fred Fish  <fnf@specifix.com>
 
 	* emulparams/elf32bmip.sh (OTHER_SECTIONS): Keep the
diff -rNbu binutils-2.17_org/ld/Makefile.am binutils-2.17/ld/Makefile.am
--- binutils-2.17_org/ld/Makefile.am	2006-06-03 06:45:50.000000000 +0200
+++ binutils-2.17/ld/Makefile.am	2006-08-02 10:30:06.000000000 +0200
@@ -240,6 +240,7 @@
 	ei386nto.o \
 	ei386nw.o \
 	ei386pe.o \
+	ei386pep.o \
 	ei386pe_posix.o \
 	elnk960.o \
 	em32relf.o \
@@ -410,15 +411,16 @@
 
 ALL_EMUL_EXTRA_OFILES = \
 	deffilep.o \
-	pe-dll.o
+	pe-dll.o \
+	pep-dll.o
 
 CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \
 	ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \
-	mri.c ldcref.c pe-dll.c
+	mri.c ldcref.c pe-dll.c pep-dll.c
 
 HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
 	ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
-	ldwrite.h mri.h deffile.h pe-dll.h elf-hints-local.h
+	ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h elf-hints-local.h
 
 GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
 GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
@@ -1069,6 +1071,9 @@
 ei386pe.c: $(srcdir)/emulparams/i386pe.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe "$(tdir_i386pe)"
+ei386pep.c: $(srcdir)/emulparams/i386pep.sh \
+  $(srcdir)/emultempl/pep.em $(srcdir)/scripttempl/pep.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} i386pep "$(tdir_i386pe)"
 ei386pe_posix.c: $(srcdir)/emulparams/i386pe_posix.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe_posix "$(tdir_i386pe_posix)"
@@ -1937,6 +1942,12 @@
   ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
   ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
   $(BFDDIR)/libcoff.h deffile.h pe-dll.h
+pep-dll.o: pep-dll.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h $(INCDIR)/safe-ctype.h \
+  ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
+  ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
+  $(BFDDIR)/libcoff.h deffile.h pep-dll.h
 ldgram.o: ldgram.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
   $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
   $(INCDIR)/bfdlink.h ld.h $(INCDIR)/bin-bugs.h ldexp.h \
diff -rNbu binutils-2.17_org/ld/Makefile.in binutils-2.17/ld/Makefile.in
--- binutils-2.17_org/ld/Makefile.in	2006-06-03 06:45:50.000000000 +0200
+++ binutils-2.17/ld/Makefile.in	2006-08-02 10:31:08.000000000 +0200
@@ -464,6 +464,7 @@
 	ei386nto.o \
 	ei386nw.o \
 	ei386pe.o \
+	ei386pep.o \
 	ei386pe_posix.o \
 	elnk960.o \
 	em32relf.o \
@@ -634,15 +635,16 @@
 
 ALL_EMUL_EXTRA_OFILES = \
 	deffilep.o \
-	pe-dll.o
+	pe-dll.o \
+	pep-dll.o
 
 CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \
 	ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \
-	mri.c ldcref.c pe-dll.c
+	mri.c ldcref.c pe-dll.c pep-dll.c
 
 HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
 	ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
-	ldwrite.h mri.h deffile.h pe-dll.h elf-hints-local.h
+	ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h elf-hints-local.h
 
 GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
 GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
@@ -1880,6 +1882,9 @@
 ei386pe.c: $(srcdir)/emulparams/i386pe.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe "$(tdir_i386pe)"
+ei386pep.c: $(srcdir)/emulparams/i386pep.sh \
+  $(srcdir)/emultempl/pep.em $(srcdir)/scripttempl/pep.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} i386pep "$(tdir_i386pe)"
 ei386pe_posix.c: $(srcdir)/emulparams/i386pe_posix.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe_posix "$(tdir_i386pe_posix)"
@@ -2718,6 +2723,12 @@
   ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
   ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
   $(BFDDIR)/libcoff.h deffile.h pe-dll.h
+pep-dll.o: pep-dll.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h $(INCDIR)/safe-ctype.h \
+  ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
+  ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
+  $(BFDDIR)/libcoff.h deffile.h pep-dll.h
 ldgram.o: ldgram.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
   $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
   $(INCDIR)/bfdlink.h ld.h $(INCDIR)/bin-bugs.h ldexp.h \
diff -rNbu binutils-2.17_org/ld/configure binutils-2.17/ld/configure
--- binutils-2.17_org/ld/configure	2006-04-11 12:36:26.000000000 +0200
+++ binutils-2.17/ld/configure	2006-07-27 10:58:44.000000000 +0200
@@ -3924,7 +3924,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -3951,6 +3951,9 @@
       ;;
     *64-bit*)
       case $host in
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
diff -rNbu binutils-2.17_org/ld/configure.tgt binutils-2.17/ld/configure.tgt
--- binutils-2.17_org/ld/configure.tgt	2006-04-05 14:41:57.000000000 +0200
+++ binutils-2.17/ld/configure.tgt	2006-08-02 10:27:25.000000000 +0200
@@ -155,6 +155,8 @@
 			  targ_extra_emuls="$targ_extra_emuls elf_x86_64"
 			fi
 			tdir_i386linux=${targ_alias}aout ;;
+x86_64-*-mingw64*) targ_emul=i386pep ;
+			targ_extra_ofiles="deffilep.o pep-dll.o" ;;
 x86_64-*-linux-*)	targ_emul=elf_x86_64
 			targ_extra_emuls="elf_i386 i386linux"
 			targ_extra_libpath=elf_i386
diff -rNbu binutils-2.17_org/ld/emulparams/i386pep.sh binutils-2.17/ld/emulparams/i386pep.sh
--- binutils-2.17_org/ld/emulparams/i386pep.sh	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/ld/emulparams/i386pep.sh	2006-07-28 12:43:22.000000000 +0200
@@ -0,0 +1,9 @@
+ARCH="i386:x86-64"
+SCRIPT_NAME=pep
+OUTPUT_FORMAT="pei-x86-64"
+RELOCATEABLE_OUTPUT_FORMAT="pe-x86-64"
+TEMPLATE_NAME=pep
+ENTRY="_mainCRTStartup"
+SUBSYSTEM=PE_DEF_SUBSYSTEM
+INITIAL_SYMBOL_CHAR=\"_\"
+TARGET_PAGE_SIZE=0x1000
diff -rNbu binutils-2.17_org/ld/emultempl/pep.em binutils-2.17/ld/emultempl/pep.em
--- binutils-2.17_org/ld/emultempl/pep.em	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/ld/emultempl/pep.em	2006-09-06 14:26:51.000000000 +0200
@@ -0,0 +1,1749 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+test -z "${ENTRY}" && ENTRY="_mainCRTStartup"
+if [ -z "$MACHINE" ]; then
+  OUTPUT_ARCH=${ARCH}
+else
+  OUTPUT_ARCH=${ARCH}:${MACHINE}
+fi
+rm -f e${EMULATION_NAME}.c
+(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
+cat >>e${EMULATION_NAME}.c <<EOF
+/* This file is part of GLD, the Gnu Linker.
+   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+   */
+
+/* For WINDOWS_XP64 and higher */
+/* The original file generated returned different default scripts depending
+   on whether certain switches were set, but these switches pertain to the
+   Linux system and that particular version of coff.  In the NT case, we
+   only determine if the subsystem is console or windows in order to select
+   the correct entry point by default. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "getopt.h"
+#include "libiberty.h"
+#include "ld.h"
+#include "ldmain.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+#include <ldgram.h>
+#include "ldlex.h"
+#include "ldmisc.h"
+#include "ldctor.h"
+#include "coff/internal.h"
+
+/* FIXME: See bfd/peXXigen.c for why we include an architecture specific
+   header in generic PE code.  */
+#include "coff/x86_64.h"
+#include "coff/pe.h"
+
+/* FIXME: This is a BFD internal header file, and we should not be
+   using it here.  */
+#include "../bfd/libcoff.h"
+
+#undef AOUTSZ
+#define AOUTSZ		PEPAOUTSZ
+#define PEAOUTHDR	PEPAOUTHDR
+
+#include "deffile.h"
+#include "pep-dll.h"
+#include "safe-ctype.h"
+
+/* Permit the emulation parameters to override the default section
+   alignment by setting OVERRIDE_SECTION_ALIGNMENT.  FIXME: This makes
+   it seem that include/coff/internal.h should not define
+   PE_DEF_SECTION_ALIGNMENT.  */
+#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT}
+#undef PE_DEF_SECTION_ALIGNMENT
+#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT}
+#endif
+
+#ifdef TARGET_IS_i386pep
+#define DLL_SUPPORT
+#endif
+
+#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT)
+#define	PE_DEF_SUBSYSTEM		3
+#else
+#undef NT_EXE_IMAGE_BASE
+#undef PE_DEF_SECTION_ALIGNMENT
+#undef PE_DEF_FILE_ALIGNMENT
+#define NT_EXE_IMAGE_BASE		0x00010000
+#define PE_DEF_SECTION_ALIGNMENT	0x00000400
+#define	PE_DEF_SUBSYSTEM		2
+#define PE_DEF_FILE_ALIGNMENT		0x00000200
+#endif
+
+
+static struct internal_extra_pe_aouthdr pep;
+static int dll;
+static flagword real_flags = IMAGE_FILE_LARGE_ADDRESS_AWARE;
+static int support_old_code = 0;
+static char * thumb_entry_symbol = NULL;
+static lang_assignment_statement_type *image_base_statement = 0;
+
+#ifdef DLL_SUPPORT
+static int pep_enable_stdcall_fixup = -1; /* 0=disable 1=enable.  */
+static char *pep_out_def_filename = NULL;
+static char *pep_implib_filename = NULL;
+static int pep_enable_auto_image_base = 0;
+static char *pep_dll_search_prefix = NULL;
+#endif
+
+extern const char *output_filename;
+
+static void
+gld_${EMULATION_NAME}_before_parse (void)
+{
+  ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
+  output_filename = "${EXECUTABLE_NAME:-a.exe}";
+#ifdef DLL_SUPPORT
+  config.dynamic_link = TRUE;
+  config.has_shared = 1;
+  link_info.pei386_auto_import = -1;
+  link_info.pei386_runtime_pseudo_reloc = -1;
+
+#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
+#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
+  lang_default_entry ("WinMainCRTStartup");
+#else
+  lang_default_entry ("_WinMainCRTStartup");
+#endif
+#else
+  lang_default_entry ("${ENTRY}");
+#endif
+#endif
+}
+\f
+/* PE format extra command line options.  */
+
+/* Used for setting flags in the PE header.  */
+#define OPTION_BASE_FILE		(300  + 1)
+#define OPTION_DLL			(OPTION_BASE_FILE + 1)
+#define OPTION_FILE_ALIGNMENT		(OPTION_DLL + 1)
+#define OPTION_IMAGE_BASE		(OPTION_FILE_ALIGNMENT + 1)
+#define OPTION_MAJOR_IMAGE_VERSION	(OPTION_IMAGE_BASE + 1)
+#define OPTION_MAJOR_OS_VERSION		(OPTION_MAJOR_IMAGE_VERSION + 1)
+#define OPTION_MAJOR_SUBSYSTEM_VERSION	(OPTION_MAJOR_OS_VERSION + 1)
+#define OPTION_MINOR_IMAGE_VERSION	(OPTION_MAJOR_SUBSYSTEM_VERSION + 1)
+#define OPTION_MINOR_OS_VERSION		(OPTION_MINOR_IMAGE_VERSION + 1)
+#define OPTION_MINOR_SUBSYSTEM_VERSION	(OPTION_MINOR_OS_VERSION + 1)
+#define OPTION_SECTION_ALIGNMENT	(OPTION_MINOR_SUBSYSTEM_VERSION + 1)
+#define OPTION_STACK			(OPTION_SECTION_ALIGNMENT + 1)
+#define OPTION_SUBSYSTEM		(OPTION_STACK + 1)
+#define OPTION_HEAP			(OPTION_SUBSYSTEM + 1)
+#define OPTION_SUPPORT_OLD_CODE		(OPTION_HEAP + 1)
+#define OPTION_OUT_DEF			(OPTION_SUPPORT_OLD_CODE + 1)
+#define OPTION_EXPORT_ALL		(OPTION_OUT_DEF + 1)
+#define OPTION_EXCLUDE_SYMBOLS		(OPTION_EXPORT_ALL + 1)
+#define OPTION_KILL_ATS			(OPTION_EXCLUDE_SYMBOLS + 1)
+#define OPTION_STDCALL_ALIASES		(OPTION_KILL_ATS + 1)
+#define OPTION_ENABLE_STDCALL_FIXUP	(OPTION_STDCALL_ALIASES + 1)
+#define OPTION_DISABLE_STDCALL_FIXUP	(OPTION_ENABLE_STDCALL_FIXUP + 1)
+#define OPTION_IMPLIB_FILENAME		(OPTION_DISABLE_STDCALL_FIXUP + 1)
+#define OPTION_THUMB_ENTRY		(OPTION_IMPLIB_FILENAME + 1)
+#define OPTION_WARN_DUPLICATE_EXPORTS	(OPTION_THUMB_ENTRY + 1)
+#define OPTION_IMP_COMPAT		(OPTION_WARN_DUPLICATE_EXPORTS + 1)
+#define OPTION_ENABLE_AUTO_IMAGE_BASE	(OPTION_IMP_COMPAT + 1)
+#define OPTION_DISABLE_AUTO_IMAGE_BASE	(OPTION_ENABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_DLL_SEARCH_PREFIX	(OPTION_DISABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_NO_DEFAULT_EXCLUDES	(OPTION_DLL_SEARCH_PREFIX + 1)
+#define OPTION_DLL_ENABLE_AUTO_IMPORT	(OPTION_NO_DEFAULT_EXCLUDES + 1)
+#define OPTION_DLL_DISABLE_AUTO_IMPORT	(OPTION_DLL_ENABLE_AUTO_IMPORT + 1)
+#define OPTION_ENABLE_EXTRA_PE_DEBUG	(OPTION_DLL_DISABLE_AUTO_IMPORT + 1)
+#define OPTION_EXCLUDE_LIBS		(OPTION_ENABLE_EXTRA_PE_DEBUG + 1)
+#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC	\
+					(OPTION_EXCLUDE_LIBS + 1)
+#define OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC	\
+					(OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC + 1)
+
+static void
+gld${EMULATION_NAME}_add_options
+  (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl,
+    struct option **longopts, int nrl ATTRIBUTE_UNUSED,
+    struct option **really_longopts ATTRIBUTE_UNUSED)
+{
+  static const struct option xtra_long[] = {
+    /* PE options */
+    {"base-file", required_argument, NULL, OPTION_BASE_FILE},
+    {"dll", no_argument, NULL, OPTION_DLL},
+    {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
+    {"heap", required_argument, NULL, OPTION_HEAP},
+    {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
+    {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
+    {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
+    {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},
+    {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION},
+    {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION},
+    {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION},
+    {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT},
+    {"stack", required_argument, NULL, OPTION_STACK},
+    {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
+    {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
+    {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
+#ifdef DLL_SUPPORT
+    /* getopt allows abbreviations, so we do this to stop it from treating -o
+       as an abbreviation for this option */
+    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
+    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
+    {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
+    {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
+    {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
+    {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
+    {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
+    {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
+    {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
+    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
+    {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
+    /* getopt() allows abbreviations, so we do this to stop it from
+       treating -c as an abbreviation for these --compat-implib.  */
+    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
+    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
+    {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE},
+    {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE},
+    {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX},
+    {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
+    {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT},
+    {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT},
+    {"enable-extra-pep-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG},
+    {"enable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC},
+    {"disable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC},
+#endif
+    {NULL, no_argument, NULL, 0}
+  };
+
+  *longopts = (struct option *)
+    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
+  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
+
+/* PE/WIN32; added routines to get the subsystem type, heap and/or stack
+   parameters which may be input from the command line.  */
+
+typedef struct
+{
+  void *ptr;
+  int size;
+  int value;
+  char *symbol;
+  int inited;
+} definfo;
+
+#define D(field,symbol,def)  {&pep.field,sizeof(pep.field), def, symbol,0}
+
+static definfo init[] =
+{
+  /* imagebase must be first */
+#define IMAGEBASEOFF 0
+  D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE),
+#define DLLOFF 1
+  {&dll, sizeof(dll), 0, "__dll__", 0},
+#define MSIMAGEBASEOFF	2
+  D(ImageBase,"__ImageBase", NT_EXE_IMAGE_BASE),
+  D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT),
+  D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT),
+  D(MajorOperatingSystemVersion,"__major_os_version__", 4),
+  D(MinorOperatingSystemVersion,"__minor_os_version__", 0),
+  D(MajorImageVersion,"__major_image_version__", 0),
+  D(MinorImageVersion,"__minor_image_version__", 0),
+  D(MajorSubsystemVersion,"__major_subsystem_version__", 5),
+  D(MinorSubsystemVersion,"__minor_subsystem_version__", 2),
+  D(Subsystem,"__subsystem__", ${SUBSYSTEM}),
+  D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000),
+  D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
+  D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
+  D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000),
+  D(LoaderFlags,"__loader_flags__", 0x0),
+  { NULL, 0, 0, NULL, 0 }
+};
+
+
+static void
+gld_${EMULATION_NAME}_list_options (FILE *file)
+{
+  fprintf (file, _("  --base_file <basefile>             Generate a base file for relocatable DLLs\n"));
+  fprintf (file, _("  --dll                              Set image base to the default for DLLs\n"));
+  fprintf (file, _("  --file-alignment <size>            Set file alignment\n"));
+  fprintf (file, _("  --heap <size>                      Set initial size of the heap\n"));
+  fprintf (file, _("  --image-base <address>             Set start address of the executable\n"));
+  fprintf (file, _("  --major-image-version <number>     Set version number of the executable\n"));
+  fprintf (file, _("  --major-os-version <number>        Set minimum required OS version\n"));
+  fprintf (file, _("  --major-subsystem-version <number> Set minimum required OS subsystem version\n"));
+  fprintf (file, _("  --minor-image-version <number>     Set revision number of the executable\n"));
+  fprintf (file, _("  --minor-os-version <number>        Set minimum required OS revision\n"));
+  fprintf (file, _("  --minor-subsystem-version <number> Set minimum required OS subsystem revision\n"));
+  fprintf (file, _("  --section-alignment <size>         Set section alignment\n"));
+  fprintf (file, _("  --stack <size>                     Set size of the initial stack\n"));
+  fprintf (file, _("  --subsystem <name>[:<version>]     Set required OS subsystem [& version]\n"));
+  fprintf (file, _("  --support-old-code                 Support interworking with old code\n"));
+  fprintf (file, _("  --thumb-entry=<symbol>             Set the entry point to be Thumb <symbol>\n"));
+#ifdef DLL_SUPPORT
+  fprintf (file, _("  --add-stdcall-alias                Export symbols with and without @nn\n"));
+  fprintf (file, _("  --disable-stdcall-fixup            Don't link _sym to _sym@nn\n"));
+  fprintf (file, _("  --enable-stdcall-fixup             Link _sym to _sym@nn without warnings\n"));
+  fprintf (file, _("  --exclude-symbols sym,sym,...      Exclude symbols from automatic export\n"));
+  fprintf (file, _("  --exclude-libs lib,lib,...         Exclude libraries from automatic export\n"));
+  fprintf (file, _("  --export-all-symbols               Automatically export all globals to DLL\n"));
+  fprintf (file, _("  --kill-at                          Remove @nn from exported symbols\n"));
+  fprintf (file, _("  --out-implib <file>                Generate import library\n"));
+  fprintf (file, _("  --output-def <file>                Generate a .DEF file for the built DLL\n"));
+  fprintf (file, _("  --warn-duplicate-exports           Warn about duplicate exports.\n"));
+  fprintf (file, _("  --compat-implib                    Create backward compatible import libs;\n\
+                                       create __imp_<SYMBOL> as well.\n"));
+  fprintf (file, _("  --enable-auto-image-base           Automatically choose image base for DLLs\n\
+                                       unless user specifies one\n"));
+  fprintf (file, _("  --disable-auto-image-base          Do not auto-choose image base. (default)\n"));
+  fprintf (file, _("  --dll-search-prefix=<string>       When linking dynamically to a dll without\n\
+                                       an importlib, use <string><basename>.dll\n\
+                                       in preference to lib<basename>.dll \n"));
+  fprintf (file, _("  --enable-auto-import               Do sophistcated linking of _sym to\n\
+                                       __imp_sym for DATA references\n"));
+  fprintf (file, _("  --disable-auto-import              Do not auto-import DATA items from DLLs\n"));
+  fprintf (file, _("  --enable-runtime-pseudo-reloc      Work around auto-import limitations by\n\
+                                       adding pseudo-relocations resolved at\n\
+                                       runtime.\n"));
+  fprintf (file, _("  --disable-runtime-pseudo-reloc     Do not add runtime pseudo-relocations for\n\
+                                       auto-imported DATA.\n"));
+  fprintf (file, _("  --enable-extra-pep-debug            Enable verbose debug output when building\n\
+                                       or linking to DLLs (esp. auto-import)\n"));
+#endif
+}
+
+
+static void
+set_pep_name (char *name, long val)
+{
+  int i;
+
+  /* Find the name and set it.  */
+  for (i = 0; init[i].ptr; i++)
+    {
+      if (strcmp (name, init[i].symbol) == 0)
+	{
+	  init[i].value = val;
+	  init[i].inited = 1;
+	  if(!strcmp(name,"__image_base__")) set_pep_name("__ImageBase",val);
+	  return;
+	}
+    }
+  abort ();
+}
+
+
+static void
+set_pep_subsystem (void)
+{
+  const char *sver;
+  const char *entry;
+  const char *initial_symbol_char;
+  char *end;
+  int len;
+  int i;
+  int subsystem;
+  unsigned long temp_subsystem;
+  static const struct
+    {
+      const char *name;
+      const int value;
+      const char *entry;
+    }
+  v[] =
+    {
+      { "native",  1, "NtProcessStartup" },
+      { "windows", 2, "WinMainCRTStartup" },
+      { "console", 3, "mainCRTStartup" },
+      { "posix",   7, "__PosixProcessStartup"},
+      { "wince",   9, "_WinMainCRTStartup" },
+      { "xbox",   14, "mainCRTStartup" },
+      { NULL, 0, NULL }
+    };
+  /* Entry point name for arbitrary subsystem numbers.  */
+  static const char default_entry[] = "mainCRTStartup";
+
+  /* Check for the presence of a version number.  */
+  sver = strchr (optarg, ':');
+  if (sver == NULL)
+    len = strlen (optarg);
+  else
+    {
+      len = sver - optarg;
+      set_pep_name ("__major_subsystem_version__",
+		   strtoul (sver + 1, &end, 0));
+      if (*end == '.')
+	set_pep_name ("__minor_subsystem_version__",
+		     strtoul (end + 1, &end, 0));
+      if (*end != '\0')
+	einfo (_("%P: warning: bad version number in -subsystem option\n"));
+    }
+
+  /* Check for numeric subsystem.  */
+  temp_subsystem = strtoul (optarg, & end, 0);
+  if ((*end == ':' || *end == '\0') && (temp_subsystem < 65536))
+    {
+      /* Search list for a numeric match to use its entry point.  */
+      for (i = 0; v[i].name; i++)
+	if (v[i].value == (int) temp_subsystem)
+	  break;
+
+      /* If no match, use the default.  */
+      if (v[i].name != NULL)
+	entry = v[i].entry;
+      else
+	entry = default_entry;
+
+      /* Use this subsystem.  */
+      subsystem = (int) temp_subsystem;
+    }
+  else
+    {
+      /* Search for subsystem by name.  */
+      for (i = 0; v[i].name; i++)
+	if (strncmp (optarg, v[i].name, len) == 0
+	    && v[i].name[len] == '\0')
+	  break;
+
+      if (v[i].name == NULL)
+	{
+	  einfo (_("%P%F: invalid subsystem type %s\n"), optarg);
+	  return;
+	}
+
+      entry = v[i].entry;
+      subsystem = v[i].value;
+    }
+
+  set_pep_name ("__subsystem__", subsystem);
+
+  initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
+  if (*initial_symbol_char != '\0')
+    {
+      char *alc_entry;
+
+      /* lang_default_entry expects its argument to be permanently
+	 allocated, so we don't free this string.  */
+      alc_entry = xmalloc (strlen (initial_symbol_char)
+			   + strlen (entry)
+			   + 1);
+      strcpy (alc_entry, initial_symbol_char);
+      strcat (alc_entry, entry);
+      entry = alc_entry;
+    }
+
+  lang_default_entry (entry);
+
+  return;
+}
+
+
+static void
+set_pep_value (char *name)
+{
+  char *end;
+
+  set_pep_name (name,  strtoul (optarg, &end, 0));
+
+  if (end == optarg)
+    einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg);
+
+  optarg = end;
+}
+
+
+static void
+set_pep_stack_heap (char *resname, char *comname)
+{
+  set_pep_value (resname);
+
+  if (*optarg == ',')
+    {
+      optarg++;
+      set_pep_value (comname);
+    }
+  else if (*optarg)
+    einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg);
+}
+
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+  switch (optc)
+    {
+    default:
+      return FALSE;
+
+    case OPTION_BASE_FILE:
+      link_info.base_file = fopen (optarg, FOPEN_WB);
+      if (link_info.base_file == NULL)
+	{
+	  /* xgettext:c-format */
+	  fprintf (stderr, _("%s: Can't open base file %s\n"),
+		   program_name, optarg);
+	  xexit (1);
+	}
+      break;
+
+      /* PE options.  */
+    case OPTION_HEAP:
+      set_pep_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__");
+      break;
+    case OPTION_STACK:
+      set_pep_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__");
+      break;
+    case OPTION_SUBSYSTEM:
+      set_pep_subsystem ();
+      break;
+    case OPTION_MAJOR_OS_VERSION:
+      set_pep_value ("__major_os_version__");
+      break;
+    case OPTION_MINOR_OS_VERSION:
+      set_pep_value ("__minor_os_version__");
+      break;
+    case OPTION_MAJOR_SUBSYSTEM_VERSION:
+      set_pep_value ("__major_subsystem_version__");
+      break;
+    case OPTION_MINOR_SUBSYSTEM_VERSION:
+      set_pep_value ("__minor_subsystem_version__");
+      break;
+    case OPTION_MAJOR_IMAGE_VERSION:
+      set_pep_value ("__major_image_version__");
+      break;
+    case OPTION_MINOR_IMAGE_VERSION:
+      set_pep_value ("__minor_image_version__");
+      break;
+    case OPTION_FILE_ALIGNMENT:
+      set_pep_value ("__file_alignment__");
+      break;
+    case OPTION_SECTION_ALIGNMENT:
+      set_pep_value ("__section_alignment__");
+      break;
+    case OPTION_DLL:
+      set_pep_name ("__dll__", 1);
+      break;
+    case OPTION_IMAGE_BASE:
+      set_pep_value ("__image_base__");
+      break;
+    case OPTION_SUPPORT_OLD_CODE:
+      support_old_code = 1;
+      break;
+    case OPTION_THUMB_ENTRY:
+      thumb_entry_symbol = optarg;
+      break;
+#ifdef DLL_SUPPORT
+    case OPTION_OUT_DEF:
+      pep_out_def_filename = xstrdup (optarg);
+      break;
+    case OPTION_EXPORT_ALL:
+      pep_dll_export_everything = 1;
+      break;
+    case OPTION_EXCLUDE_SYMBOLS:
+      pep_dll_add_excludes (optarg, 0);
+      break;
+    case OPTION_EXCLUDE_LIBS:
+      pep_dll_add_excludes (optarg, 1);
+      break;
+    case OPTION_KILL_ATS:
+      pep_dll_kill_ats = 1;
+      break;
+    case OPTION_STDCALL_ALIASES:
+      pep_dll_stdcall_aliases = 1;
+      break;
+    case OPTION_ENABLE_STDCALL_FIXUP:
+      pep_enable_stdcall_fixup = 1;
+      break;
+    case OPTION_DISABLE_STDCALL_FIXUP:
+      pep_enable_stdcall_fixup = 0;
+      break;
+    case OPTION_IMPLIB_FILENAME:
+      pep_implib_filename = xstrdup (optarg);
+      break;
+    case OPTION_WARN_DUPLICATE_EXPORTS:
+      pep_dll_warn_dup_exports = 1;
+      break;
+    case OPTION_IMP_COMPAT:
+      pep_dll_compat_implib = 1;
+      break;
+    case OPTION_ENABLE_AUTO_IMAGE_BASE:
+      pep_enable_auto_image_base = 1;
+      break;
+    case OPTION_DISABLE_AUTO_IMAGE_BASE:
+      pep_enable_auto_image_base = 0;
+      break;
+    case OPTION_DLL_SEARCH_PREFIX:
+      pep_dll_search_prefix = xstrdup (optarg);
+      break;
+    case OPTION_NO_DEFAULT_EXCLUDES:
+      pep_dll_do_default_excludes = 0;
+      break;
+    case OPTION_DLL_ENABLE_AUTO_IMPORT:
+      link_info.pei386_auto_import = 1;
+      break;
+    case OPTION_DLL_DISABLE_AUTO_IMPORT:
+      link_info.pei386_auto_import = 0;
+      break;
+    case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC:
+      link_info.pei386_runtime_pseudo_reloc = 1;
+      break;
+    case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC:
+      link_info.pei386_runtime_pseudo_reloc = 0;
+      break;
+    case OPTION_ENABLE_EXTRA_PE_DEBUG:
+      pep_dll_extra_pe_debug = 1;
+      break;
+#endif
+    }
+  return TRUE;
+}
+\f
+
+#ifdef DLL_SUPPORT
+static unsigned long
+strhash (const char *str)
+{
+  const unsigned char *s;
+  unsigned long hash;
+  unsigned int c;
+  unsigned int len;
+
+  hash = 0;
+  len = 0;
+  s = (const unsigned char *) str;
+  while ((c = *s++) != '\0')
+    {
+      hash += c + (c << 17);
+      hash ^= hash >> 2;
+      ++len;
+    }
+  hash += len + (len << 17);
+  hash ^= hash >> 2;
+
+  return hash;
+}
+
+/* Use the output file to create a image base for relocatable DLLs.  */
+
+static unsigned long
+compute_dll_image_base (const char *ofile)
+{
+  unsigned long hash = strhash (ofile);
+  return 0x61300000 + ((hash << 16) & 0x0FFC0000);
+}
+#endif
+
+/* Assign values to the special symbols before the linker script is
+   read.  */
+
+static void
+gld_${EMULATION_NAME}_set_symbols (void)
+{
+  /* Run through and invent symbols for all the
+     names and insert the defaults.  */
+  int j;
+  lang_statement_list_type *save;
+
+  if (!init[IMAGEBASEOFF].inited)
+    {
+      if (link_info.relocatable)
+	init[IMAGEBASEOFF].value = 0;
+      else if (init[DLLOFF].value || (link_info.shared && !link_info.pie))
+#ifdef DLL_SUPPORT
+	init[IMAGEBASEOFF].value = (pep_enable_auto_image_base) ?
+	  compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE;
+#else
+	init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE;
+#endif
+      else
+	init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE;
+	init[MSIMAGEBASEOFF].value=init[IMAGEBASEOFF].value;
+    }
+
+  /* Don't do any symbol assignments if this is a relocatable link.  */
+  if (link_info.relocatable)
+    return;
+
+  /* Glue the assignments into the abs section.  */
+  save = stat_ptr;
+
+  stat_ptr = &(abs_output_section->children);
+
+  for (j = 0; init[j].ptr; j++)
+    {
+      long val = init[j].value;
+      lang_assignment_statement_type *rv;
+      rv = lang_add_assignment (exp_assop ('=', init[j].symbol,
+					   exp_intop (val)));
+      if (init[j].size == sizeof (short))
+	*(short *) init[j].ptr = val;
+      else if (init[j].size == sizeof (int))
+	*(int *) init[j].ptr = val;
+      else if (init[j].size == sizeof (long))
+	*(long *) init[j].ptr = val;
+      /* This might be a long long or other special type.  */
+      else if (init[j].size == sizeof (bfd_vma))
+	*(bfd_vma *) init[j].ptr = val;
+      else	abort ();
+      if (j == IMAGEBASEOFF)
+	image_base_statement = rv;
+    }
+	/* Restore the pointer.  */
+  stat_ptr = save;
+
+  if (pep.FileAlignment >
+      pep.SectionAlignment)
+    {
+      einfo (_("%P: warning, file alignment > section alignment.\n"));
+    }
+}
+
+/* This is called after the linker script and the command line options
+   have been read.  */
+
+static void
+gld_${EMULATION_NAME}_after_parse (void)
+{
+  /* The Windows libraries are designed for the linker to treat the
+     entry point as an undefined symbol.  Otherwise, the .obj that
+     defines mainCRTStartup is brought in because it is the first
+     encountered in libc.lib and it has other symbols in it which will
+     be pulled in by the link process.  To avoid this, we act as
+     though the user specified -u with the entry point symbol.
+
+     This function is called after the linker script and command line
+     options have been read, so at this point we know the right entry
+     point.  This function is called before the input files are
+     opened, so registering the symbol as undefined will make a
+     difference.  */
+
+  if (! link_info.relocatable && entry_symbol.name != NULL)
+    ldlang_add_undef (entry_symbol.name);
+}
+
+/* pep-dll.c directly accesses pep_data_import_dll,
+   so it must be defined outside of #ifdef DLL_SUPPORT.
+   Note - this variable is deliberately not initialised.
+   This allows it to be treated as a common varaible, and only
+   exist in one incarnation in a multiple target enabled linker.  */
+char * pep_data_import_dll;
+
+#ifdef DLL_SUPPORT
+static struct bfd_link_hash_entry *pep_undef_found_sym;
+
+static bfd_boolean
+pep_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
+{
+  int sl;
+  char *string = inf;
+
+  sl = strlen (string);
+  if (h->type == bfd_link_hash_defined
+      && strncmp (h->root.string, string, sl) == 0
+      && h->root.string[sl] == '@')
+    {
+      pep_undef_found_sym = h;
+      return FALSE;
+    }
+  return TRUE;
+}
+
+static void
+pep_fixup_stdcalls (void)
+{
+  static int gave_warning_message = 0;
+  struct bfd_link_hash_entry *undef, *sym;
+
+  if (pep_dll_extra_pe_debug)
+    printf ("%s\n", __FUNCTION__);
+
+  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
+    if (undef->type == bfd_link_hash_undefined)
+      {
+	char* at = strchr (undef->root.string, '@');
+	int lead_at = (*undef->root.string == '@');
+	/* For now, don't try to fixup fastcall symbols.  */
+
+	if (at && !lead_at)
+	  {
+	    /* The symbol is a stdcall symbol, so let's look for a
+	       cdecl symbol with the same name and resolve to that.  */
+	    char *cname = xstrdup (undef->root.string /* + lead_at */);
+	    at = strchr (cname, '@');
+	    *at = 0;
+	    sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1);
+
+	    if (sym && sym->type == bfd_link_hash_defined)
+	      {
+		undef->type = bfd_link_hash_defined;
+		undef->u.def.value = sym->u.def.value;
+		undef->u.def.section = sym->u.def.section;
+
+		if (pep_enable_stdcall_fixup == -1)
+		  {
+		    einfo (_("Warning: resolving %s by linking to %s\n"),
+			   undef->root.string, cname);
+		    if (! gave_warning_message)
+		      {
+			gave_warning_message = 1;
+			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
+			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
+		      }
+		  }
+	      }
+	  }
+	else
+	  {
+	    /* The symbol is a cdecl symbol, so we look for stdcall
+	       symbols - which means scanning the whole symbol table.  */
+	    pep_undef_found_sym = 0;
+	    bfd_link_hash_traverse (link_info.hash, pep_undef_cdecl_match,
+				    (char *) undef->root.string);
+	    sym = pep_undef_found_sym;
+	    if (sym)
+	      {
+		undef->type = bfd_link_hash_defined;
+		undef->u.def.value = sym->u.def.value;
+		undef->u.def.section = sym->u.def.section;
+
+		if (pep_enable_stdcall_fixup == -1)
+		  {
+		    einfo (_("Warning: resolving %s by linking to %s\n"),
+			   undef->root.string, sym->root.string);
+		    if (! gave_warning_message)
+		      {
+			gave_warning_message = 1;
+			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
+			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
+		      }
+		  }
+	      }
+	  }
+      }
+}
+
+static int
+make_import_fixup (arelent *rel, asection *s)
+{
+  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
+  char addend[4];
+
+  if (pep_dll_extra_pe_debug)
+    printf ("arelent: %s@%#lx: add=%li\n", sym->name,
+	    (long) rel->address, (long) rel->addend);
+
+  if (! bfd_get_section_contents (s->owner, s, addend, rel->address, sizeof (addend)))
+    einfo (_("%C: Cannot get section contents - auto-import exception\n"),
+	   s->owner, s, rel->address);
+
+  pep_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend));
+
+  return 1;
+}
+
+static void
+pep_find_data_imports (void)
+{
+  struct bfd_link_hash_entry *undef, *sym;
+
+  if (link_info.pei386_auto_import == 0)
+    return;
+
+  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
+    {
+      if (undef->type == bfd_link_hash_undefined)
+	{
+	  /* C++ symbols are *long*.  */
+	  char buf[4096];
+
+	  if (pep_dll_extra_pe_debug)
+	    printf ("%s:%s\n", __FUNCTION__, undef->root.string);
+
+	  sprintf (buf, "__imp_%s", undef->root.string);
+
+	  sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
+
+	  if (sym && sym->type == bfd_link_hash_defined)
+	    {
+	      bfd *b = sym->u.def.section->owner;
+	      asymbol **symbols;
+	      int nsyms, symsize, i;
+
+	      if (link_info.pei386_auto_import == -1)
+		info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
+			  undef->root.string, buf);
+
+	      symsize = bfd_get_symtab_upper_bound (b);
+	      symbols = (asymbol **) xmalloc (symsize);
+	      nsyms = bfd_canonicalize_symtab (b, symbols);
+
+	      for (i = 0; i < nsyms; i++)
+		{
+		  if (memcmp (symbols[i]->name, "__head_",
+			      sizeof ("__head_") - 1))
+		    continue;
+
+		  if (pep_dll_extra_pe_debug)
+		    printf ("->%s\n", symbols[i]->name);
+
+		  pep_data_import_dll = (char*) (symbols[i]->name +
+						sizeof ("__head_") - 1);
+		  break;
+		}
+
+	      pep_walk_relocs_of_symbol (&link_info, undef->root.string,
+					make_import_fixup);
+
+	      /* Let's differentiate it somehow from defined.  */
+	      undef->type = bfd_link_hash_defweak;
+	      /* We replace original name with __imp_ prefixed, this
+		 1) may trash memory 2) leads to duplicate symbol generation.
+		 Still, IMHO it's better than having name poluted.  */
+	      undef->root.string = sym->root.string;
+	      undef->u.def.value = sym->u.def.value;
+	      undef->u.def.section = sym->u.def.section;
+	    }
+	}
+    }
+}
+
+static bfd_boolean
+pr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
+{
+  if (pep_dll_extra_pe_debug)
+    printf ("+%s\n", h->string);
+
+  return TRUE;
+}
+#endif /* DLL_SUPPORT */
+
+
+static void
+gld_${EMULATION_NAME}_after_open (void)
+{
+#ifdef DLL_SUPPORT
+  if (pep_dll_extra_pe_debug)
+    {
+      bfd *a;
+      struct bfd_link_hash_entry *sym;
+
+      printf ("%s()\n", __FUNCTION__);
+
+      for (sym = link_info.hash->undefs; sym; sym=sym->u.undef.next)
+	printf ("-%s\n", sym->root.string);
+      bfd_hash_traverse (&link_info.hash->table, pr_sym, NULL);
+
+      for (a = link_info.input_bfds; a; a = a->link_next)
+	printf ("*%s\n",a->filename);
+    }
+#endif
+
+  /* Pass the wacky PE command line options into the output bfd.
+     FIXME: This should be done via a function, rather than by
+     including an internal BFD header.  */
+
+  if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0)
+    einfo (_("%F%P: PE operations on non PE file.\n"));
+
+  pe_data (output_bfd)->pe_opthdr = pep;
+  pe_data (output_bfd)->dll = init[DLLOFF].value;
+  pe_data (output_bfd)->real_flags |= real_flags;
+
+#ifdef DLL_SUPPORT
+  if (pep_enable_stdcall_fixup) /* -1=warn or 1=disable */
+    pep_fixup_stdcalls ();
+
+  pep_process_import_defs (output_bfd, & link_info);
+
+  pep_find_data_imports ();
+
+#ifndef TARGET_IS_i386pep
+  if (link_info.shared)
+#else
+  if (!link_info.relocatable)
+#endif
+    pep_dll_build_sections (output_bfd, &link_info);
+
+#ifndef TARGET_IS_i386pep
+  else
+    pep_exe_build_sections (output_bfd, &link_info);
+#endif
+#endif
+
+  {
+    /* This next chunk of code tries to detect the case where you have
+       two import libraries for the same DLL (specifically,
+       symbolically linking libm.a and libc.a in cygwin to
+       libcygwin.a).  In those cases, it's possible for function
+       thunks from the second implib to be used but without the
+       head/tail objects, causing an improper import table.  We detect
+       those cases and rename the "other" import libraries to match
+       the one the head/tail come from, so that the linker will sort
+       things nicely and produce a valid import table.  */
+
+    LANG_FOR_EACH_INPUT_STATEMENT (is)
+      {
+	if (is->the_bfd->my_archive)
+	  {
+	    int idata2 = 0, reloc_count=0, is_imp = 0;
+	    asection *sec;
+
+	    /* See if this is an import library thunk.  */
+	    for (sec = is->the_bfd->sections; sec; sec = sec->next)
+	      {
+		if (strcmp (sec->name, ".idata\$2") == 0)
+		  idata2 = 1;
+		if (strncmp (sec->name, ".idata\$", 7) == 0)
+		  is_imp = 1;
+		reloc_count += sec->reloc_count;
+	      }
+
+	    if (is_imp && !idata2 && reloc_count)
+	      {
+		/* It is, look for the reference to head and see if it's
+		   from our own library.  */
+		for (sec = is->the_bfd->sections; sec; sec = sec->next)
+		  {
+		    int i;
+		    long symsize;
+		    long relsize;
+		    asymbol **symbols;
+		    arelent **relocs;
+		    int nrelocs;
+
+		    symsize = bfd_get_symtab_upper_bound (is->the_bfd);
+		    if (symsize < 1)
+		      break;
+		    relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
+		    if (relsize < 1)
+		      break;
+
+		    symbols = (asymbol **) xmalloc (symsize);
+		    symsize = bfd_canonicalize_symtab (is->the_bfd, symbols);
+		    if (symsize < 0)
+		      {
+			einfo ("%X%P: unable to process symbols: %E");
+			return;
+		      }
+
+		    relocs = (arelent **) xmalloc ((size_t) relsize);
+		    nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec,
+						      relocs, symbols);
+		    if (nrelocs < 0)
+		      {
+			free (relocs);
+			einfo ("%X%P: unable to process relocs: %E");
+			return;
+		      }
+
+		    for (i = 0; i < nrelocs; i++)
+		      {
+			struct bfd_symbol *s;
+			struct bfd_link_hash_entry * blhe;
+			char *other_bfd_filename;
+			char *n;
+
+			s = (relocs[i]->sym_ptr_ptr)[0];
+
+			if (s->flags & BSF_LOCAL)
+			  continue;
+
+			/* Thunk section with reloc to another bfd.  */
+			blhe = bfd_link_hash_lookup (link_info.hash,
+						     s->name,
+						     FALSE, FALSE, TRUE);
+
+			if (blhe == NULL
+			    || blhe->type != bfd_link_hash_defined)
+			  continue;
+
+			other_bfd_filename
+			  = blhe->u.def.section->owner->my_archive
+			    ? bfd_get_filename (blhe->u.def.section->owner->my_archive)
+			    : bfd_get_filename (blhe->u.def.section->owner);
+
+			if (strcmp (bfd_get_filename (is->the_bfd->my_archive),
+				    other_bfd_filename) == 0)
+			  continue;
+
+			/* Rename this implib to match the other one.  */
+			n = xmalloc (strlen (other_bfd_filename) + 1);
+			strcpy (n, other_bfd_filename);
+			is->the_bfd->my_archive->filename = n;
+		      }
+
+		    free (relocs);
+		    /* Note - we do not free the symbols,
+		       they are now cached in the BFD.  */
+		  }
+	      }
+	  }
+      }
+  }
+
+  {
+    int is_ms_arch = 0;
+    bfd *cur_arch = 0;
+    lang_input_statement_type *is2;
+    lang_input_statement_type *is3;
+
+    /* Careful - this is a shell script.  Watch those dollar signs! */
+    /* Microsoft import libraries have every member named the same,
+       and not in the right order for us to link them correctly.  We
+       must detect these and rename the members so that they'll link
+       correctly.  There are three types of objects: the head, the
+       thunks, and the sentinel(s).  The head is easy; it's the one
+       with idata2.  We assume that the sentinels won't have relocs,
+       and the thunks will.  It's easier than checking the symbol
+       table for external references.  */
+    LANG_FOR_EACH_INPUT_STATEMENT (is)
+      {
+	if (is->the_bfd->my_archive)
+	  {
+	    char *pnt;
+	    bfd *arch = is->the_bfd->my_archive;
+
+	    if (cur_arch != arch)
+	      {
+		cur_arch = arch;
+		is_ms_arch = 1;
+
+		for (is3 = is;
+		     is3 && is3->the_bfd->my_archive == arch;
+		     is3 = (lang_input_statement_type *) is3->next)
+		  {
+		    /* A MS dynamic import library can also contain static
+		       members, so look for the first element with a .dll
+		       extension, and use that for the remainder of the
+		       comparisons.  */
+		    pnt = strrchr (is3->the_bfd->filename, '.');
+		    if (pnt != NULL && strcmp (pnt, ".dll") == 0)
+		      break;
+		  }
+
+		if (is3 == NULL)
+		  is_ms_arch = 0;
+		else
+		  {
+		    /* OK, found one.  Now look to see if the remaining
+		       (dynamic import) members use the same name.  */
+		    for (is2 = is;
+			 is2 && is2->the_bfd->my_archive == arch;
+			 is2 = (lang_input_statement_type *) is2->next)
+		      {
+			/* Skip static members, ie anything with a .obj
+			   extension.  */
+			pnt = strrchr (is2->the_bfd->filename, '.');
+			if (pnt != NULL && strcmp (pnt, ".obj") == 0)
+			  continue;
+
+			if (strcmp (is3->the_bfd->filename,
+				    is2->the_bfd->filename))
+			  {
+			    is_ms_arch = 0;
+			    break;
+			  }
+		      }
+		  }
+	      }
+
+	    /* This fragment might have come from an .obj file in a Microsoft
+	       import, and not an actual import record. If this is the case,
+	       then leave the filename alone.  */
+	    pnt = strrchr (is->the_bfd->filename, '.');
+
+	    if (is_ms_arch && (strcmp (pnt, ".dll") == 0))
+	      {
+		int idata2 = 0, reloc_count=0;
+		asection *sec;
+		char *new_name, seq;
+
+		for (sec = is->the_bfd->sections; sec; sec = sec->next)
+		  {
+		    if (strcmp (sec->name, ".idata\$2") == 0)
+		      idata2 = 1;
+		    reloc_count += sec->reloc_count;
+		  }
+
+		if (idata2) /* .idata2 is the TOC */
+		  seq = 'a';
+		else if (reloc_count > 0) /* thunks */
+		  seq = 'b';
+		else /* sentinel */
+		  seq = 'c';
+
+		new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
+		sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
+		is->the_bfd->filename = new_name;
+
+		new_name = xmalloc (strlen (is->filename) + 3);
+		sprintf (new_name, "%s.%c", is->filename, seq);
+		is->filename = new_name;
+	      }
+	  }
+      }
+  }
+}
+
+static void
+gld_${EMULATION_NAME}_before_allocation (void)
+{
+  before_allocation_default ();
+}
+
+#ifdef DLL_SUPPORT
+/* This is called when an input file isn't recognized as a BFD.  We
+   check here for .DEF files and pull them in automatically.  */
+
+static int
+saw_option (char *option)
+{
+  int i;
+
+  for (i = 0; init[i].ptr; i++)
+    if (strcmp (init[i].symbol, option) == 0)
+      return init[i].inited;
+  return 0;
+}
+#endif /* DLL_SUPPORT */
+
+static bfd_boolean
+gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
+{
+#ifdef DLL_SUPPORT
+  const char *ext = entry->filename + strlen (entry->filename) - 4;
+
+  if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0)
+    {
+      pep_def_file = def_file_parse (entry->filename, pep_def_file);
+
+      if (pep_def_file)
+	{
+	  int i, buflen=0, len;
+	  char *buf;
+
+	  for (i = 0; i < pep_def_file->num_exports; i++)
+	    {
+	      len = strlen (pep_def_file->exports[i].internal_name);
+	      if (buflen < len + 2)
+		buflen = len + 2;
+	    }
+
+	  buf = (char *) xmalloc (buflen);
+
+	  for (i = 0; i < pep_def_file->num_exports; i++)
+	    {
+	      struct bfd_link_hash_entry *h;
+
+	      sprintf (buf, "_%s", pep_def_file->exports[i].internal_name);
+
+	      h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE);
+	      if (h == (struct bfd_link_hash_entry *) NULL)
+		einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
+	      if (h->type == bfd_link_hash_new)
+		{
+		  h->type = bfd_link_hash_undefined;
+		  h->u.undef.abfd = NULL;
+		  bfd_link_add_undef (link_info.hash, h);
+		}
+	    }
+	  free (buf);
+
+	  /* def_file_print (stdout, pep_def_file); */
+	  if (pep_def_file->is_dll == 1)
+	    link_info.shared = 1;
+
+	  if (pep_def_file->base_address != (bfd_vma)(-1))
+	    {
+	      pep.ImageBase =
+		pe_data (output_bfd)->pe_opthdr.ImageBase =
+		init[IMAGEBASEOFF].value = pep_def_file->base_address;
+	      init[IMAGEBASEOFF].inited = 1;
+	      if (image_base_statement)
+		image_base_statement->exp =
+		  exp_assop ('=', "__image_base__", exp_intop (pep.ImageBase));
+	    }
+
+	  if (pep_def_file->stack_reserve != -1
+	      && ! saw_option ("__size_of_stack_reserve__"))
+	    {
+	      pep.SizeOfStackReserve = pep_def_file->stack_reserve;
+	      if (pep_def_file->stack_commit != -1)
+		pep.SizeOfStackCommit = pep_def_file->stack_commit;
+	    }
+	  if (pep_def_file->heap_reserve != -1
+	      && ! saw_option ("__size_of_heap_reserve__"))
+	    {
+	      pep.SizeOfHeapReserve = pep_def_file->heap_reserve;
+	      if (pep_def_file->heap_commit != -1)
+		pep.SizeOfHeapCommit = pep_def_file->heap_commit;
+	    }
+	  return TRUE;
+	}
+    }
+#endif
+  return FALSE;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
+{
+#ifdef DLL_SUPPORT
+#ifdef TARGET_IS_i386pep
+  pep_dll_id_target ("pei-x86-64");
+#endif
+  if (bfd_get_format (entry->the_bfd) == bfd_object)
+    {
+      char fbuf[LD_PATHMAX + 1];
+      const char *ext;
+
+      if (REALPATH (entry->filename, fbuf) == NULL)
+	strncpy (fbuf, entry->filename, sizeof (fbuf));
+
+      ext = fbuf + strlen (fbuf) - 4;
+
+      if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0)
+	return pep_implied_import_dll (fbuf);
+    }
+#endif
+  return FALSE;
+}
+
+static void
+gld_${EMULATION_NAME}_finish (void)
+{
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe)
+  struct bfd_link_hash_entry * h;
+
+  if (thumb_entry_symbol != NULL)
+    {
+      h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
+				FALSE, FALSE, TRUE);
+
+      if (h != (struct bfd_link_hash_entry *) NULL
+	  && (h->type == bfd_link_hash_defined
+	      || h->type == bfd_link_hash_defweak)
+	  && h->u.def.section->output_section != NULL)
+	{
+	  static char buffer[32];
+	  bfd_vma val;
+
+	  /* Special procesing is required for a Thumb entry symbol.  The
+	     bottom bit of its address must be set.  */
+	  val = (h->u.def.value
+		 + bfd_get_section_vma (output_bfd,
+					h->u.def.section->output_section)
+		 + h->u.def.section->output_offset);
+
+	  val |= 1;
+
+	  /* Now convert this value into a string and store it in entry_symbol
+	     where the lang_finish() function will pick it up.  */
+	  buffer[0] = '0';
+	  buffer[1] = 'x';
+
+	  sprintf_vma (buffer + 2, val);
+
+	  if (entry_symbol.name != NULL && entry_from_cmdline)
+	    einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
+		   thumb_entry_symbol, entry_symbol.name);
+	  entry_symbol.name = buffer;
+	}
+      else
+	einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
+    }
+#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) */
+
+  finish_default ();
+
+#ifdef DLL_SUPPORT
+  if (link_info.shared
+    || (!link_info.relocatable && pep_def_file->num_exports != 0)
+    )
+    {
+      pep_dll_fill_sections (output_bfd, &link_info);
+      if (pep_implib_filename)
+	pep_dll_generate_implib (pep_def_file, pep_implib_filename);
+    }
+
+  if (pep_out_def_filename)
+    pep_dll_generate_def_file (pep_out_def_filename);
+#endif /* DLL_SUPPORT */
+
+  /* I don't know where .idata gets set as code, but it shouldn't be.  */
+  {
+    asection *asec = bfd_get_section_by_name (output_bfd, ".idata");
+
+    if (asec)
+      {
+	asec->flags &= ~SEC_CODE;
+	asec->flags |= SEC_DATA;
+      }
+  }
+}
+
+\f
+/* Place an orphan section.
+
+   We use this to put sections in a reasonable place in the file, and
+   to ensure that they are aligned as required.
+
+   We handle grouped sections here as well.  A section named .foo$nn
+   goes into the output section .foo.  All grouped sections are sorted
+   by name.
+
+   Grouped sections for the default sections are handled by the
+   default linker script using wildcards, and are sorted by
+   sort_sections.  */
+
+static bfd_boolean
+gld_${EMULATION_NAME}_place_orphan (asection *s)
+{
+  const char *secname;
+  const char *orig_secname;
+  char *dollar = NULL;
+  lang_output_section_statement_type *os;
+  lang_statement_list_type add_child;
+
+  secname = bfd_get_section_name (s->owner, s);
+
+  /* Look through the script to see where to place this section.  */
+  orig_secname = secname;
+  if (!link_info.relocatable
+      && (dollar = strchr (secname, '$')) != NULL)
+    {
+      size_t len = dollar - orig_secname;
+      char *newname = xmalloc (len + 1);
+      memcpy (newname, orig_secname, len);
+      newname[len] = '\0';
+      secname = newname;
+    }
+
+  os = lang_output_section_find (secname);
+
+  lang_list_init (&add_child);
+
+  if (os != NULL
+      && (os->bfd_section == NULL
+	  || os->bfd_section->flags == 0
+	  || ((s->flags ^ os->bfd_section->flags)
+	      & (SEC_LOAD | SEC_ALLOC)) == 0))
+    {
+      /* We already have an output section statement with this
+	 name, and its bfd section, if any, has compatible flags.
+	 If the section already exists but does not have any flags set,
+	 then it has been created by the linker, probably as a result of
+	 a --section-start command line switch.  */
+      lang_add_section (&add_child, s, os);
+    }
+  else
+    {
+      static struct orphan_save hold[] =
+	{
+	  { ".text",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
+	    0, 0, 0, 0 },
+	  { ".rdata",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+	    0, 0, 0, 0 },
+	  { ".data",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
+	    0, 0, 0, 0 },
+	  { ".bss",
+	    SEC_ALLOC,
+	    0, 0, 0, 0 }
+	};
+      enum orphan_save_index
+	{
+	  orphan_text = 0,
+	  orphan_rodata,
+	  orphan_data,
+	  orphan_bss
+	};
+      static int orphan_init_done = 0;
+      struct orphan_save *place;
+      lang_output_section_statement_type *after;
+      etree_type *address;
+
+      if (!orphan_init_done)
+	{
+	  struct orphan_save *ho;
+	  for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
+	    if (ho->name != NULL)
+	      {
+		ho->os = lang_output_section_find (ho->name);
+		if (ho->os != NULL && ho->os->flags == 0)
+		  ho->os->flags = ho->flags;
+	      }
+	  orphan_init_done = 1;
+	}
+
+      /* Try to put the new output section in a reasonable place based
+	 on the section name and section flags.  */
+
+      place = NULL;
+      if ((s->flags & SEC_ALLOC) == 0)
+	;
+      else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+	place = &hold[orphan_bss];
+      else if ((s->flags & SEC_READONLY) == 0)
+	place = &hold[orphan_data];
+      else if ((s->flags & SEC_CODE) == 0)
+	place = &hold[orphan_rodata];
+      else
+	place = &hold[orphan_text];
+
+      after = NULL;
+      if (place != NULL)
+	{
+	  if (place->os == NULL)
+	    place->os = lang_output_section_find (place->name);
+	  after = place->os;
+	  if (after == NULL)
+	    after = lang_output_section_find_by_flags (s, &place->os, NULL);
+	  if (after == NULL)
+	    /* *ABS* is always the first output section statement.  */
+	    after = (&lang_output_section_statement.head
+		     ->output_section_statement);
+	}
+
+      /* Choose a unique name for the section.  This will be needed if the
+	 same section name appears in the input file with different
+	 loadable or allocatable characteristics.  */
+      if (bfd_get_section_by_name (output_bfd, secname) != NULL)
+	{
+	  static int count = 1;
+	  secname = bfd_get_unique_section_name (output_bfd, secname, &count);
+	  if (secname == NULL)
+	    einfo ("%F%P: place_orphan failed: %E\n");
+	}
+
+      /* All sections in an executable must be aligned to a page boundary.  */
+      address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
+      os = lang_insert_orphan (s, secname, after, place, address, &add_child);
+    }
+
+  {
+    lang_statement_union_type **pl = &os->children.head;
+
+    if (dollar != NULL)
+      {
+	bfd_boolean found_dollar;
+
+	/* The section name has a '$'.  Sort it with the other '$'
+	   sections.  */
+	found_dollar = FALSE;
+	for ( ; *pl != NULL; pl = &(*pl)->header.next)
+	  {
+	    lang_input_section_type *ls;
+	    const char *lname;
+
+	    if ((*pl)->header.type != lang_input_section_enum)
+	      continue;
+
+	    ls = &(*pl)->input_section;
+
+	    lname = bfd_get_section_name (ls->section->owner, ls->section);
+	    if (strchr (lname, '$') == NULL)
+	      {
+		if (found_dollar)
+		  break;
+	      }
+	    else
+	      {
+		found_dollar = TRUE;
+		if (strcmp (orig_secname, lname) < 0)
+		  break;
+	      }
+	  }
+      }
+
+    if (add_child.head != NULL)
+      {
+	add_child.head->header.next = *pl;
+	*pl = add_child.head;
+      }
+  }
+
+  return TRUE;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_open_dynamic_archive
+  (const char *arch ATTRIBUTE_UNUSED, search_dirs_type *search,
+   lang_input_statement_type *entry)
+{
+  const char * filename;
+  char * string;
+
+  if (! entry->is_archive)
+    return FALSE;
+
+  filename = entry->filename;
+
+  string = (char *) xmalloc (strlen (search->name)
+			     + strlen (filename)
+			     + sizeof "/lib.a.dll"
+#ifdef DLL_SUPPORT
+			     + (pep_dll_search_prefix ? strlen (pep_dll_search_prefix) : 0)
+#endif
+			     + 1);
+
+  /* Try "libfoo.dll.a" first (preferred explicit import library for dll's.  */
+  sprintf (string, "%s/lib%s.dll.a", search->name, filename);
+
+  if (! ldfile_try_open_bfd (string, entry))
+    {
+      /* Try "foo.dll.a" next (alternate explicit import library for dll's.  */
+      sprintf (string, "%s/%s.dll.a", search->name, filename);
+      if (! ldfile_try_open_bfd (string, entry))
+	{
+	  /* Try libfoo.a next. Normally, this would be interpreted as a static
+	     library, but it *could* be an import library. For backwards compatibility,
+	     libfoo.a needs to ==precede== libfoo.dll and foo.dll in the search,
+	     or sometimes errors occur when building legacy packages.
+
+	     Putting libfoo.a here means that in a failure case (i.e. the library
+	     -lfoo is not found) we will search for libfoo.a twice before
+	     giving up -- once here, and once when searching for a "static" lib.
+	     for a "static" lib.  */
+	  /* Try "libfoo.a" (import lib, or static lib, but must
+	     take precedence over dll's).  */
+	  sprintf (string, "%s/lib%s.a", search->name, filename);
+	  if (! ldfile_try_open_bfd (string, entry))
+	    {
+#ifdef DLL_SUPPORT
+	      if (pep_dll_search_prefix)
+		{
+		  /* Try "<prefix>foo.dll" (preferred dll name, if specified).  */
+		  sprintf (string, "%s/%s%s.dll", search->name, pep_dll_search_prefix, filename);
+		  if (! ldfile_try_open_bfd (string, entry))
+		    {
+		      /* Try "libfoo.dll" (default preferred dll name).  */
+		      sprintf (string, "%s/lib%s.dll", search->name, filename);
+		      if (! ldfile_try_open_bfd (string, entry))
+			{
+			  /* Finally, try "foo.dll" (alternate dll name).  */
+			  sprintf (string, "%s/%s.dll", search->name, filename);
+			  if (! ldfile_try_open_bfd (string, entry))
+			    {
+			      free (string);
+			      return FALSE;
+			    }
+			}
+		    }
+		}
+	      else /* pep_dll_search_prefix not specified.  */
+#endif
+		{
+		  /* Try "libfoo.dll" (preferred dll name).  */
+		  sprintf (string, "%s/lib%s.dll", search->name, filename);
+		  if (! ldfile_try_open_bfd (string, entry))
+		    {
+		      /* Finally, try "foo.dll" (alternate dll name).  */
+		      sprintf (string, "%s/%s.dll", search->name, filename);
+		      if (! ldfile_try_open_bfd (string, entry))
+			{
+			  free (string);
+			  return FALSE;
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+  entry->filename = string;
+
+  return TRUE;
+}
+
+static int
+gld_${EMULATION_NAME}_find_potential_libraries
+  (char *name, lang_input_statement_type *entry)
+{
+  return ldfile_open_file_search (name, entry, "", ".lib");
+}
+\f
+static char *
+gld_${EMULATION_NAME}_get_script (int *isfile)
+EOF
+# Scripts compiled in.
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+  *isfile = 0;
+
+  if (link_info.relocatable && config.build_constructors)
+    return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu			>> e${EMULATION_NAME}.c
+echo '  ; else if (link_info.relocatable) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr			>> e${EMULATION_NAME}.c
+echo '  ; else if (!config.text_read_only) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn			>> e${EMULATION_NAME}.c
+echo '  ; else if (!config.magic_demand_paged) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn			>> e${EMULATION_NAME}.c
+echo '  ; else return'					>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x			>> e${EMULATION_NAME}.c
+echo '; }'						>> e${EMULATION_NAME}.c
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+  gld_${EMULATION_NAME}_before_parse,
+  syslib_default,
+  hll_default,
+  gld_${EMULATION_NAME}_after_parse,
+  gld_${EMULATION_NAME}_after_open,
+  after_allocation_default,
+  set_output_arch_default,
+  ldemul_default_target,
+  gld_${EMULATION_NAME}_before_allocation,
+  gld_${EMULATION_NAME}_get_script,
+  "${EMULATION_NAME}",
+  "${OUTPUT_FORMAT}",
+  gld_${EMULATION_NAME}_finish,
+  NULL, /* Create output section statements.  */
+  gld_${EMULATION_NAME}_open_dynamic_archive,
+  gld_${EMULATION_NAME}_place_orphan,
+  gld_${EMULATION_NAME}_set_symbols,
+  NULL, /* parse_args */
+  gld${EMULATION_NAME}_add_options,
+  gld${EMULATION_NAME}_handle_option,
+  gld_${EMULATION_NAME}_unrecognized_file,
+  gld_${EMULATION_NAME}_list_options,
+  gld_${EMULATION_NAME}_recognized_file,
+  gld_${EMULATION_NAME}_find_potential_libraries,
+  NULL	/* new_vers_pattern.  */
+};
+EOF
diff -rNbu binutils-2.17_org/ld/pep-dll.c binutils-2.17/ld/pep-dll.c
--- binutils-2.17_org/ld/pep-dll.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/ld/pep-dll.c	2006-09-04 13:26:58.000000000 +0200
@@ -0,0 +1,2688 @@
+/* Routines to help build PEPI-format DLLs (Win64 etc)
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libiberty.h"
+#include "safe-ctype.h"
+
+#include <time.h>
+
+#include "ld.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldwrite.h"
+#include "ldmisc.h"
+#include <ldgram.h>
+#include "ldmain.h"
+#include "ldfile.h"
+#include "ldemul.h"
+#include "coff/internal.h"
+#include "../bfd/libcoff.h"
+#include "deffile.h"
+#include "pep-dll.h"
+
+#undef AOUTSZ
+#define AOUTSZ		PEPAOUTSZ
+#define PEAOUTHDR	PEPAOUTHDR
+
+/*  This file turns a regular Windows PE image into a DLL.  Because of
+    the complexity of this operation, it has been broken down into a
+    number of separate modules which are all called by the main function
+    at the end of this file.  This function is not re-entrant and is
+    normally only called once, so static variables are used to reduce
+    the number of parameters and return values required.
+
+    See also: ld/emultempl/pep.em.  */
+
+/*  Auto-import feature by Paul Sokolovsky
+
+    Quick facts:
+
+    1. With this feature on, DLL clients can import variables from DLL
+    without any concern from their side (for example, without any source
+    code modifications).
+
+    2. This is done completely in bounds of the PE specification (to be fair,
+    there's a place where it pokes nose out of, but in practice it works).
+    So, resulting module can be used with any other PE compiler/linker.
+
+    3. Auto-import is fully compatible with standard import method and they
+    can be mixed together.
+
+    4. Overheads: space: 8 bytes per imported symbol, plus 20 for each
+    reference to it; load time: negligible; virtual/physical memory: should be
+    less than effect of DLL relocation, and I sincerely hope it doesn't affect
+    DLL sharability (too much).
+
+    Idea
+
+    The obvious and only way to get rid of dllimport insanity is to make client
+    access variable directly in the DLL, bypassing extra dereference. I.e.,
+    whenever client contains something like
+
+    mov dll_var,%eax,
+
+    address of dll_var in the command should be relocated to point into loaded
+    DLL. The aim is to make OS loader do so, and than make ld help with that.
+    Import section of PE made following way: there's a vector of structures
+    each describing imports from particular DLL. Each such structure points
+    to two other parallel vectors: one holding imported names, and one which
+    will hold address of corresponding imported name. So, the solution is
+    de-vectorize these structures, making import locations be sparse and
+    pointing directly into code. Before continuing, it is worth a note that,
+    while authors strives to make PE act ELF-like, there're some other people
+    make ELF act PE-like: elfvector, ;-) .
+
+    Implementation
+
+    For each reference of data symbol to be imported from DLL (to set of which
+    belong symbols with name <sym>, if __imp_<sym> is found in implib), the
+    import fixup entry is generated. That entry is of type
+    IMAGE_IMPORT_DESCRIPTOR and stored in .idata$3 subsection. Each
+    fixup entry contains pointer to symbol's address within .text section
+    (marked with __fuN_<sym> symbol, where N is integer), pointer to DLL name
+    (so, DLL name is referenced by multiple entries), and pointer to symbol
+    name thunk. Symbol name thunk is singleton vector (__nm_th_<symbol>)
+    pointing to IMAGE_IMPORT_BY_NAME structure (__nm_<symbol>) directly
+    containing imported name. Here comes that "om the edge" problem mentioned
+    above: PE specification rambles that name vector (OriginalFirstThunk)
+    should run in parallel with addresses vector (FirstThunk), i.e. that they
+    should have same number of elements and terminated with zero. We violate
+    this, since FirstThunk points directly into machine code. But in practice,
+    OS loader implemented the sane way: it goes thru OriginalFirstThunk and
+    puts addresses to FirstThunk, not something else. It once again should be
+    noted that dll and symbol name structures are reused across fixup entries
+    and should be there anyway to support standard import stuff, so sustained
+    overhead is 20 bytes per reference. Other question is whether having several
+    IMAGE_IMPORT_DESCRIPTORS for the same DLL is possible. Answer is yes, it is
+    done even by native compiler/linker (libth32's functions are in fact reside
+    in windows9x kernel32.dll, so if you use it, you have two
+    IMAGE_IMPORT_DESCRIPTORS for kernel32.dll). Yet other question is whether
+    referencing the same PE structures several times is valid. The answer is why
+    not, prohibiting that (detecting violation) would require more work on
+    behalf of loader than not doing it.
+
+    See also: ld/emultempl/pe.em.  */
+
+static void add_bfd_to_link (bfd *, const char *, struct bfd_link_info *);
+
+/* For emultempl/pe.em.  */
+
+def_file * pep_def_file = 0;
+int pep_dll_export_everything = 0;
+int pep_dll_do_default_excludes = 1;
+int pep_dll_kill_ats = 0;
+int pep_dll_stdcall_aliases = 0;
+int pep_dll_warn_dup_exports = 0;
+int pep_dll_compat_implib = 0;
+int pep_dll_extra_pe_debug = 0;
+
+/* Static variables and types.  */
+
+static bfd_vma image_base;
+static bfd *filler_bfd;
+static struct bfd_section *edata_s, *reloc_s;
+static unsigned char *edata_d, *reloc_d;
+static size_t edata_sz, reloc_sz;
+static int runtime_pseudo_relocs_created = 0;
+
+typedef struct
+  {
+    char *target_name;
+    char *object_target;
+    unsigned int imagebase_reloc;
+    int pep_arch;
+    int bfd_arch;
+    int underscored;
+  }
+pep_details_type;
+
+typedef struct
+  {
+    char *name;
+    int len;
+  }
+autofilter_entry_type;
+
+#define PE_ARCH_i386	1
+#define PE_ARCH_sh	2
+#define PE_ARCH_mips	3
+#define PE_ARCH_arm	4
+#define PE_ARCH_arm_epoc 5
+
+static pep_details_type pep_detail_list[] =
+{
+  {
+    "pei-x86-64",
+    "pe-x86-64",
+    3 /* R_IMAGEBASE */, // $$$$
+    PE_ARCH_i386,
+    bfd_arch_i386,
+    1
+  },
+  { NULL, NULL, 0, 0, 0, 0 }
+};
+
+static pep_details_type *pep_details;
+
+static autofilter_entry_type autofilter_symbollist[] =
+{
+  { "DllMain@12", 10 },
+  { "DllEntryPoint@0", 15 },
+  { "DllMainCRTStartup@12", 20 },
+  { "_cygwin_dll_entry@12", 20 },
+  { "_cygwin_crt0_common@8", 21 },
+  { "_cygwin_noncygwin_dll_entry@12", 30 },
+  { "impure_ptr", 10 },
+  { "_pei386_runtime_relocator", 25 },
+  { "do_pseudo_reloc", 15 },
+  { "cygwin_crt0", 11 },
+  { NULL, 0 }
+};
+
+/* Do not specify library suffix explicitly, to allow for dllized versions.  */
+static autofilter_entry_type autofilter_liblist[] =
+{
+  { "libcygwin", 9 },
+  { "libgcc", 6 },
+  { "libstdc++", 9 },
+  { "libmingw32", 10 },
+  { "libmingwex", 10 },
+  { "libg2c", 6 },
+  { "libsupc++", 9 },
+  { "libobjc", 7 },
+  { "libgcj", 6 },
+  { NULL, 0 }
+};
+
+static autofilter_entry_type autofilter_objlist[] =
+{
+  { "crt0.o", 6 },
+  { "crt1.o", 6 },
+  { "crt2.o", 6 },
+  { "dllcrt1.o", 9 },
+  { "dllcrt2.o", 9 },
+  { "gcrt0.o", 7 },
+  { "gcrt1.o", 7 },
+  { "gcrt2.o", 7 },
+  { "crtbegin.o", 10 },
+  { "crtend.o", 8 },
+  { NULL, 0 }
+};
+
+static autofilter_entry_type autofilter_symbolprefixlist[] =
+{
+  /* { "__imp_", 6 }, */
+  /* Do __imp_ explicitly to save time.  */
+  { "__rtti_", 7 },
+  /* Don't re-export auto-imported symbols.  */
+  { "_nm_", 4 },
+  { "__builtin_", 10 },
+  /* Don't export symbols specifying internal DLL layout.  */
+  { "_head_", 6 },
+  { "_fmode", 6 },
+  { "_impure_ptr", 11 },
+  { "cygwin_attach_dll", 17 },
+  { "cygwin_premain0", 15 },
+  { "cygwin_premain1", 15 },
+  { "cygwin_premain2", 15 },
+  { "cygwin_premain3", 15 },
+  { "environ", 7 },
+  { NULL, 0 }
+};
+
+static autofilter_entry_type autofilter_symbolsuffixlist[] =
+{
+  { "_iname", 6 },
+  { NULL, 0 }
+};
+
+#define U(str) (pep_details->underscored ? "_" str : str)
+
+void
+pep_dll_id_target (const char *target)
+{
+  int i;
+
+  for (i = 0; pep_detail_list[i].target_name; i++)
+    if (strcmp (pep_detail_list[i].target_name, target) == 0
+	|| strcmp (pep_detail_list[i].object_target, target) == 0)
+      {
+	pep_details = pep_detail_list + i;
+	return;
+      }
+  einfo (_("%XUnsupported PEI architecture: %s\n"), target);
+  exit (1);
+}
+
+/* Helper functions for qsort.  Relocs must be sorted so that we can write
+   them out by pages.  */
+
+typedef struct
+  {
+    bfd_vma vma;
+    char type;
+    short extra;
+  }
+reloc_data_type;
+
+static int
+reloc_sort (const void *va, const void *vb)
+{
+  bfd_vma a = ((const reloc_data_type *) va)->vma;
+  bfd_vma b = ((const reloc_data_type *) vb)->vma;
+
+  return (a > b) ? 1 : ((a < b) ? -1 : 0);
+}
+
+static int
+pep_export_sort (const void *va, const void *vb)
+{
+  const def_file_export *a = va;
+  const def_file_export *b = vb;
+
+  return strcmp (a->name, b->name);
+}
+
+/* Read and process the .DEF file.  */
+
+/* These correspond to the entries in pep_def_file->exports[].  I use
+   exported_symbol_sections[i] to tag whether or not the symbol was
+   defined, since we can't export symbols we don't have.  */
+
+static bfd_vma *exported_symbol_offsets;
+static struct bfd_section **exported_symbol_sections;
+static int export_table_size;
+static int count_exported;
+static int count_exported_byname;
+static int count_with_ordinals;
+static const char *dll_name;
+static int min_ordinal, max_ordinal;
+static int *exported_symbols;
+
+typedef struct exclude_list_struct
+  {
+    char *string;
+    struct exclude_list_struct *next;
+    int type;
+  }
+exclude_list_struct;
+
+static struct exclude_list_struct *excludes = 0;
+
+void
+pep_dll_add_excludes (const char *new_excludes, const int type)
+{
+  char *local_copy;
+  char *exclude_string;
+
+  local_copy = xstrdup (new_excludes);
+
+  exclude_string = strtok (local_copy, ",:");
+  for (; exclude_string; exclude_string = strtok (NULL, ",:"))
+    {
+      struct exclude_list_struct *new_exclude;
+
+      new_exclude = xmalloc (sizeof (struct exclude_list_struct));
+      new_exclude->string = xmalloc (strlen (exclude_string) + 1);
+      strcpy (new_exclude->string, exclude_string);
+      new_exclude->type = type;
+      new_exclude->next = excludes;
+      excludes = new_exclude;
+    }
+
+  free (local_copy);
+}
+
+
+/* abfd is a bfd containing n (or NULL)
+   It can be used for contextual checks.  */
+
+static int
+auto_export (bfd *abfd, def_file *d, const char *n)
+{
+  int i;
+  struct exclude_list_struct *ex;
+  autofilter_entry_type *afptr;
+  const char * libname = 0;
+  if (abfd && abfd->my_archive)
+    libname = lbasename (abfd->my_archive->filename);
+
+  /* We should not re-export imported stuff.  */
+  if (strncmp (n, "_imp_", 5) == 0)
+    return 0;
+
+  for (i = 0; i < d->num_exports; i++)
+    if (strcmp (d->exports[i].name, n) == 0)
+      return 0;
+
+  if (pep_dll_do_default_excludes)
+    {
+      const char * p;
+      int    len;
+
+      if (pep_dll_extra_pe_debug)
+	printf ("considering exporting: %s, abfd=%p, abfd->my_arc=%p\n",
+		n, abfd, abfd->my_archive);
+
+      /* First of all, make context checks:
+	 Don't export anything from standard libs.  */
+      if (libname)
+	{
+	  afptr = autofilter_liblist;
+
+	  while (afptr->name)
+	    {
+	      if (strncmp (libname, afptr->name, afptr->len) == 0 )
+		return 0;
+	      afptr++;
+	    }
+	}
+
+      /* Next, exclude symbols from certain startup objects.  */
+
+      if (abfd && (p = lbasename (abfd->filename)))
+	{
+	  afptr = autofilter_objlist;
+	  while (afptr->name)
+	    {
+	      if (strcmp (p, afptr->name) == 0)
+		return 0;
+	      afptr++;
+	    }
+	}
+
+      /* Don't try to blindly exclude all symbols
+	 that begin with '__'; this was tried and
+	 it is too restrictive.  */
+
+      /* Then, exclude specific symbols.  */
+      afptr = autofilter_symbollist;
+      while (afptr->name)
+	{
+	  if (strcmp (n, afptr->name) == 0)
+	    return 0;
+
+	  afptr++;
+	}
+
+      /* Next, exclude symbols starting with ...  */
+      afptr = autofilter_symbolprefixlist;
+      while (afptr->name)
+	{
+	  if (strncmp (n, afptr->name, afptr->len) == 0)
+	    return 0;
+
+	  afptr++;
+	}
+
+      /* Finally, exclude symbols ending with ...  */
+      len = strlen (n);
+      afptr = autofilter_symbolsuffixlist;
+      while (afptr->name)
+	{
+	  if ((len >= afptr->len)
+	      /* Add 1 to insure match with trailing '\0'.  */
+	      && strncmp (n + len - afptr->len, afptr->name,
+			  afptr->len + 1) == 0)
+	    return 0;
+
+	  afptr++;
+	}
+    }
+
+  for (ex = excludes; ex; ex = ex->next)
+    {
+      if (ex->type == 1) /* exclude-libs */
+	{
+	  if (libname
+	      && ((strcmp (libname, ex->string) == 0)
+		   || (strcasecmp ("ALL", ex->string) == 0)))
+	    return 0;
+	}
+      else if (strcmp (n, ex->string) == 0)
+	return 0;
+    }
+
+  return 1;
+}
+
+static void
+process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
+{
+  int i, j;
+  struct bfd_link_hash_entry *blhe;
+  bfd *b;
+  struct bfd_section *s;
+  def_file_export *e = 0;
+
+  if (!pep_def_file)
+    pep_def_file = def_file_empty ();
+
+  /* First, run around to all the objects looking for the .drectve
+     sections, and push those into the def file too.  */
+  for (b = info->input_bfds; b; b = b->link_next)
+    {
+      s = bfd_get_section_by_name (b, ".drectve");
+      if (s)
+	{
+	  long size = s->size;
+	  char *buf = xmalloc (size);
+
+	  bfd_get_section_contents (b, s, buf, 0, size);
+	  def_file_add_directive (pep_def_file, buf, size);
+	  free (buf);
+	}
+    }
+
+  /* If we are not building a DLL, when there are no exports
+     we do not build an export table at all.  */
+  if (!pep_dll_export_everything && pep_def_file->num_exports == 0
+      && info->executable)
+    return;
+
+  /* Now, maybe export everything else the default way.  */
+  if (pep_dll_export_everything || pep_def_file->num_exports == 0)
+    {
+      for (b = info->input_bfds; b; b = b->link_next)
+	{
+	  asymbol **symbols;
+	  int nsyms, symsize;
+
+	  symsize = bfd_get_symtab_upper_bound (b);
+	  symbols = xmalloc (symsize);
+	  nsyms = bfd_canonicalize_symtab (b, symbols);
+
+	  for (j = 0; j < nsyms; j++)
+	    {
+	      /* We should export symbols which are either global or not
+		 anything at all.  (.bss data is the latter)
+		 We should not export undefined symbols.  */
+	      if (symbols[j]->section != &bfd_und_section
+		  && ((symbols[j]->flags & BSF_GLOBAL)
+		      || (symbols[j]->flags == BFD_FORT_COMM_DEFAULT_VALUE)))
+		{
+		  const char *sn = symbols[j]->name;
+
+		  /* We should not re-export imported stuff.  */
+		  {
+		    char *name = xmalloc (strlen (sn) + 2 + 6);
+		    sprintf (name, "%s%s", U("_imp_"), sn);
+		    blhe = bfd_link_hash_lookup (info->hash, name,
+						 FALSE, FALSE, FALSE);
+		    free (name);
+
+		    if (blhe && blhe->type == bfd_link_hash_defined)
+		      continue;
+		  }
+
+		  if (*sn == '_')
+		    sn++;
+
+		  if (auto_export (b, pep_def_file, sn))
+		    {
+		      def_file_export *p;
+		      p=def_file_add_export (pep_def_file, sn, 0, -1);
+		      /* Fill data flag properly, from dlltool.c.  */
+		      p->flag_data = !(symbols[j]->flags & BSF_FUNCTION);
+		    }
+		}
+	    }
+	}
+    }
+
+#undef NE
+#define NE pep_def_file->num_exports
+
+  /* Canonicalize the export list.  */
+  if (pep_dll_kill_ats)
+    {
+      for (i = 0; i < NE; i++)
+	{
+	  if (strchr (pep_def_file->exports[i].name, '@'))
+	    {
+	      /* This will preserve internal_name, which may have been
+		 pointing to the same memory as name, or might not
+		 have.  */
+	      int lead_at = (*pep_def_file->exports[i].name == '@');
+	      char *tmp = xstrdup (pep_def_file->exports[i].name + lead_at);
+	      char *tmp_at = strchr (tmp, '@');
+
+	      if (tmp_at)
+	        *tmp_at = 0;
+	      else
+	        einfo (_("%XCannot export %s: invalid export name\n"),
+		       pep_def_file->exports[i].name);
+	      pep_def_file->exports[i].name = tmp;
+	    }
+	}
+    }
+
+  if (pep_dll_stdcall_aliases)
+    {
+      for (i = 0; i < NE; i++)
+	{
+	  if (strchr (pep_def_file->exports[i].name, '@'))
+	    {
+	      int lead_at = (*pep_def_file->exports[i].name == '@');
+	      char *tmp = xstrdup (pep_def_file->exports[i].name + lead_at);
+
+	      *(strchr (tmp, '@')) = 0;
+	      if (auto_export (NULL, pep_def_file, tmp))
+		def_file_add_export (pep_def_file, tmp,
+				     pep_def_file->exports[i].internal_name,
+				     -1);
+	      else
+		free (tmp);
+	    }
+	}
+    }
+
+  /* Convenience, but watch out for it changing.  */
+  e = pep_def_file->exports;
+
+  exported_symbol_offsets = xmalloc (NE * sizeof (bfd_vma));
+  exported_symbol_sections = xmalloc (NE * sizeof (struct bfd_section *));
+
+  memset (exported_symbol_sections, 0, NE * sizeof (struct bfd_section *));
+  max_ordinal = 0;
+  min_ordinal = 65536;
+  count_exported = 0;
+  count_exported_byname = 0;
+  count_with_ordinals = 0;
+
+  qsort (pep_def_file->exports, NE, sizeof (pep_def_file->exports[0]),
+	 pep_export_sort);
+  for (i = 0, j = 0; i < NE; i++)
+    {
+      if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0)
+	{
+	  /* This is a duplicate.  */
+	  if (e[j - 1].ordinal != -1
+	      && e[i].ordinal != -1
+	      && e[j - 1].ordinal != e[i].ordinal)
+	    {
+	      if (pep_dll_warn_dup_exports)
+		/* xgettext:c-format */
+		einfo (_("%XError, duplicate EXPORT with ordinals: %s (%d vs %d)\n"),
+		       e[j - 1].name, e[j - 1].ordinal, e[i].ordinal);
+	    }
+	  else
+	    {
+	      if (pep_dll_warn_dup_exports)
+		/* xgettext:c-format */
+		einfo (_("Warning, duplicate EXPORT: %s\n"),
+		       e[j - 1].name);
+	    }
+
+	  if (e[i].ordinal != -1)
+	    e[j - 1].ordinal = e[i].ordinal;
+	  e[j - 1].flag_private |= e[i].flag_private;
+	  e[j - 1].flag_constant |= e[i].flag_constant;
+	  e[j - 1].flag_noname |= e[i].flag_noname;
+	  e[j - 1].flag_data |= e[i].flag_data;
+	}
+      else
+	{
+	  if (i != j)
+	    e[j] = e[i];
+	  j++;
+	}
+    }
+  pep_def_file->num_exports = j;	/* == NE */
+
+  for (i = 0; i < NE; i++)
+    {
+      char *name;
+
+      /* Check for forward exports */
+      if (strchr (pep_def_file->exports[i].internal_name, '.'))
+	{
+	  count_exported++;
+	  if (!pep_def_file->exports[i].flag_noname)
+	    count_exported_byname++;
+
+	  pep_def_file->exports[i].flag_forward = 1;
+
+	  if (pep_def_file->exports[i].ordinal != -1)
+	    {
+	      if (max_ordinal < pep_def_file->exports[i].ordinal)
+		max_ordinal = pep_def_file->exports[i].ordinal;
+	      if (min_ordinal > pep_def_file->exports[i].ordinal)
+		min_ordinal = pep_def_file->exports[i].ordinal;
+	      count_with_ordinals++;
+	    }
+
+	  continue;
+	}
+
+      name = xmalloc (strlen (pep_def_file->exports[i].internal_name) + 2);
+      if (pep_details->underscored
+ 	  && (*pep_def_file->exports[i].internal_name != '@'))
+	{
+	  *name = '_';
+	  strcpy (name + 1, pep_def_file->exports[i].internal_name);
+	}
+      else
+	strcpy (name, pep_def_file->exports[i].internal_name);
+
+      blhe = bfd_link_hash_lookup (info->hash,
+				   name,
+				   FALSE, FALSE, TRUE);
+
+      if (blhe
+	  && (blhe->type == bfd_link_hash_defined
+	      || (blhe->type == bfd_link_hash_common)))
+	{
+	  count_exported++;
+	  if (!pep_def_file->exports[i].flag_noname)
+	    count_exported_byname++;
+
+	  /* Only fill in the sections. The actual offsets are computed
+	     in fill_exported_offsets() after common symbols are laid
+	     out.  */
+	  if (blhe->type == bfd_link_hash_defined)
+	    exported_symbol_sections[i] = blhe->u.def.section;
+	  else
+	    exported_symbol_sections[i] = blhe->u.c.p->section;
+
+	  if (pep_def_file->exports[i].ordinal != -1)
+	    {
+	      if (max_ordinal < pep_def_file->exports[i].ordinal)
+		max_ordinal = pep_def_file->exports[i].ordinal;
+	      if (min_ordinal > pep_def_file->exports[i].ordinal)
+		min_ordinal = pep_def_file->exports[i].ordinal;
+	      count_with_ordinals++;
+	    }
+	}
+      else if (blhe && blhe->type == bfd_link_hash_undefined)
+	{
+	  /* xgettext:c-format */
+	  einfo (_("%XCannot export %s: symbol not defined\n"),
+		 pep_def_file->exports[i].internal_name);
+	}
+      else if (blhe)
+	{
+	  /* xgettext:c-format */
+	  einfo (_("%XCannot export %s: symbol wrong type (%d vs %d)\n"),
+		 pep_def_file->exports[i].internal_name,
+		 blhe->type, bfd_link_hash_defined);
+	}
+      else
+	{
+	  /* xgettext:c-format */
+	  einfo (_("%XCannot export %s: symbol not found\n"),
+		 pep_def_file->exports[i].internal_name);
+	}
+      free (name);
+    }
+}
+
+/* Build the bfd that will contain .edata and .reloc sections.  */
+
+static void
+build_filler_bfd (int include_edata)
+{
+  lang_input_statement_type *filler_file;
+  filler_file = lang_add_input_file ("dll stuff",
+				     lang_input_file_is_fake_enum,
+				     NULL);
+  filler_file->the_bfd = filler_bfd = bfd_create ("dll stuff", output_bfd);
+  if (filler_bfd == NULL
+      || !bfd_set_arch_mach (filler_bfd,
+			     bfd_get_arch (output_bfd),
+			     bfd_get_mach (output_bfd)))
+    {
+      einfo ("%X%P: can not create BFD: %E\n");
+      return;
+    }
+
+  if (include_edata)
+    {
+      edata_s = bfd_make_section_old_way (filler_bfd, ".edata");
+      if (edata_s == NULL
+	  || !bfd_set_section_flags (filler_bfd, edata_s,
+				     (SEC_HAS_CONTENTS
+				      | SEC_ALLOC
+				      | SEC_LOAD
+				      | SEC_KEEP
+				      | SEC_IN_MEMORY)))
+	{
+	  einfo ("%X%P: can not create .edata section: %E\n");
+	  return;
+	}
+      bfd_set_section_size (filler_bfd, edata_s, edata_sz);
+    }
+
+  reloc_s = bfd_make_section_old_way (filler_bfd, ".reloc");
+  if (reloc_s == NULL
+      || !bfd_set_section_flags (filler_bfd, reloc_s,
+				 (SEC_HAS_CONTENTS
+				  | SEC_ALLOC
+				  | SEC_LOAD
+				  | SEC_KEEP
+				  | SEC_IN_MEMORY)))
+    {
+      einfo ("%X%P: can not create .reloc section: %E\n");
+      return;
+    }
+
+  bfd_set_section_size (filler_bfd, reloc_s, 0);
+
+  ldlang_add_file (filler_file);
+}
+
+/* Gather all the exported symbols and build the .edata section.  */
+
+static void
+generate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  int i, next_ordinal;
+  int name_table_size = 0;
+  const char *dlnp;
+
+  /* First, we need to know how many exported symbols there are,
+     and what the range of ordinals is.  */
+  if (pep_def_file->name)
+    dll_name = pep_def_file->name;
+  else
+    {
+      dll_name = abfd->filename;
+
+      for (dlnp = dll_name; *dlnp; dlnp++)
+	if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':')
+	  dll_name = dlnp + 1;
+    }
+
+  if (count_with_ordinals && max_ordinal > count_exported)
+    {
+      if (min_ordinal > max_ordinal - count_exported + 1)
+	min_ordinal = max_ordinal - count_exported + 1;
+    }
+  else
+    {
+      min_ordinal = 1;
+      max_ordinal = count_exported;
+    }
+
+  export_table_size = max_ordinal - min_ordinal + 1;
+  exported_symbols = xmalloc (export_table_size * sizeof (int));
+  for (i = 0; i < export_table_size; i++)
+    exported_symbols[i] = -1;
+
+  /* Now we need to assign ordinals to those that don't have them.  */
+  for (i = 0; i < NE; i++)
+    {
+      if (exported_symbol_sections[i] ||
+          pep_def_file->exports[i].flag_forward)
+	{
+	  if (pep_def_file->exports[i].ordinal != -1)
+	    {
+	      int ei = pep_def_file->exports[i].ordinal - min_ordinal;
+	      int pi = exported_symbols[ei];
+
+	      if (pi != -1)
+		{
+		  /* xgettext:c-format */
+		  einfo (_("%XError, ordinal used twice: %d (%s vs %s)\n"),
+			 pep_def_file->exports[i].ordinal,
+			 pep_def_file->exports[i].name,
+			 pep_def_file->exports[pi].name);
+		}
+	      exported_symbols[ei] = i;
+	    }
+	  name_table_size += strlen (pep_def_file->exports[i].name) + 1;
+	}
+
+      /* Reserve space for the forward name. */
+      if (pep_def_file->exports[i].flag_forward)
+	{
+	  name_table_size += strlen (pep_def_file->exports[i].internal_name) + 1;
+	}
+    }
+
+  next_ordinal = min_ordinal;
+  for (i = 0; i < NE; i++)
+    if ((exported_symbol_sections[i] ||
+         pep_def_file->exports[i].flag_forward) &&
+        pep_def_file->exports[i].ordinal == -1)
+      {
+	while (exported_symbols[next_ordinal - min_ordinal] != -1)
+	  next_ordinal++;
+
+	exported_symbols[next_ordinal - min_ordinal] = i;
+	pep_def_file->exports[i].ordinal = next_ordinal;
+      }
+
+  /* OK, now we can allocate some memory.  */
+  edata_sz = (40				/* directory */
+	      + 4 * export_table_size		/* addresses */
+	      + 4 * count_exported_byname	/* name ptrs */
+	      + 2 * count_exported_byname	/* ordinals */
+	      + name_table_size + strlen (dll_name) + 1);
+}
+
+/* Fill the exported symbol offsets. The preliminary work has already
+   been done in process_def_file().  */
+
+static void
+fill_exported_offsets (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
+{
+  int i;
+  struct bfd_link_hash_entry *blhe;
+
+  for (i = 0; i < pep_def_file->num_exports; i++)
+    {
+      char *name;
+
+      name = xmalloc (strlen (pep_def_file->exports[i].internal_name) + 2);
+      if (pep_details->underscored
+ 	  && *pep_def_file->exports[i].internal_name != '@')
+	{
+	  *name = '_';
+	  strcpy (name + 1, pep_def_file->exports[i].internal_name);
+	}
+      else
+	strcpy (name, pep_def_file->exports[i].internal_name);
+
+      blhe = bfd_link_hash_lookup (info->hash,
+				   name,
+				   FALSE, FALSE, TRUE);
+
+      if (blhe && blhe->type == bfd_link_hash_defined)
+	exported_symbol_offsets[i] = blhe->u.def.value;
+
+      free (name);
+    }
+}
+
+static void
+fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  int s, hint;
+  unsigned char *edirectory;
+  unsigned char *eaddresses;
+  unsigned char *enameptrs;
+  unsigned char *eordinals;
+  char *enamestr;
+  time_t now;
+
+  time (&now);
+
+  edata_d = xmalloc (edata_sz);
+
+  /* Note use of array pointer math here.  */
+  edirectory = edata_d;
+  eaddresses = edata_d + 40;
+  enameptrs = eaddresses + 4 * export_table_size;
+  eordinals = enameptrs + 4 * count_exported_byname;
+  enamestr = (char *) eordinals + 2 * count_exported_byname;
+
+#define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) \
+		   + edata_s->output_section->vma - image_base)
+
+  memset (edata_d, 0, edata_sz);
+  bfd_put_32 (abfd, now, edata_d + 4);
+  if (pep_def_file->version_major != -1)
+    {
+      bfd_put_16 (abfd, pep_def_file->version_major, edata_d + 8);
+      bfd_put_16 (abfd, pep_def_file->version_minor, edata_d + 10);
+    }
+
+  bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12);
+  strcpy (enamestr, dll_name);
+  enamestr += strlen (enamestr) + 1;
+  bfd_put_32 (abfd, min_ordinal, edata_d + 16);
+  bfd_put_32 (abfd, export_table_size, edata_d + 20);
+  bfd_put_32 (abfd, count_exported_byname, edata_d + 24);
+  bfd_put_32 (abfd, ERVA (eaddresses), edata_d + 28);
+  bfd_put_32 (abfd, ERVA (enameptrs), edata_d + 32);
+  bfd_put_32 (abfd, ERVA (eordinals), edata_d + 36);
+
+  fill_exported_offsets (abfd, info);
+
+  /* Ok, now for the filling in part.
+     Scan alphabetically - ie the ordering in the exports[] table,
+     rather than by ordinal - the ordering in the exported_symbol[]
+     table.  See dlltool.c and:
+        http://sources.redhat.com/ml/binutils/2003-04/msg00379.html
+     for more information.  */
+  hint = 0;
+  for (s = 0; s < NE; s++)
+    {
+      struct bfd_section *ssec = exported_symbol_sections[s];
+      if (pep_def_file->exports[s].ordinal != -1 &&
+          (pep_def_file->exports[s].flag_forward || ssec != NULL))
+	{
+	  int ord = pep_def_file->exports[s].ordinal;
+
+	  if (pep_def_file->exports[s].flag_forward)
+	    {
+	      bfd_put_32 (abfd, ERVA (enamestr),
+		          eaddresses + 4 * (ord - min_ordinal));
+
+	      strcpy (enamestr, pep_def_file->exports[s].internal_name);
+	      enamestr += strlen (pep_def_file->exports[s].internal_name) + 1;
+	    }
+	  else
+	    {
+	      unsigned long srva = (exported_symbol_offsets[s]
+				    + ssec->output_section->vma
+				    + ssec->output_offset);
+
+	      bfd_put_32 (abfd, srva - image_base,
+		          eaddresses + 4 * (ord - min_ordinal));
+	    }
+
+	  if (!pep_def_file->exports[s].flag_noname)
+	    {
+	      char *ename = pep_def_file->exports[s].name;
+
+	      bfd_put_32 (abfd, ERVA (enamestr), enameptrs);
+	      enameptrs += 4;
+	      strcpy (enamestr, ename);
+	      enamestr += strlen (enamestr) + 1;
+	      bfd_put_16 (abfd, ord - min_ordinal, eordinals);
+	      eordinals += 2;
+	      pep_def_file->exports[s].hint = hint++;
+	    }
+	}
+    }
+}
+
+
+static struct bfd_section *current_sec;
+
+void
+pep_walk_relocs_of_symbol (struct bfd_link_info *info,
+			  const char *name,
+			  int (*cb) (arelent *, asection *))
+{
+  bfd *b;
+  asection *s;
+
+  for (b = info->input_bfds; b; b = b->link_next)
+    {
+      asymbol **symbols;
+      int nsyms, symsize;
+
+      symsize = bfd_get_symtab_upper_bound (b);
+      symbols = xmalloc (symsize);
+      nsyms   = bfd_canonicalize_symtab (b, symbols);
+
+      for (s = b->sections; s; s = s->next)
+	{
+	  arelent **relocs;
+	  int relsize, nrelocs, i;
+	  int flags = bfd_get_section_flags (b, s);
+
+	  /* Skip discarded linkonce sections.  */
+	  if (flags & SEC_LINK_ONCE
+	      && s->output_section == bfd_abs_section_ptr)
+	    continue;
+
+	  current_sec = s;
+
+	  relsize = bfd_get_reloc_upper_bound (b, s);
+	  relocs = xmalloc (relsize);
+	  nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
+
+	  for (i = 0; i < nrelocs; i++)
+	    {
+	      struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
+
+	      if (!strcmp (name, sym->name))
+		cb (relocs[i], s);
+	    }
+
+	  free (relocs);
+
+	  /* Warning: the allocated symbols are remembered in BFD and reused
+	     later, so don't free them! */
+	  /* free (symbols); */
+	}
+    }
+}
+
+/* Gather all the relocations and build the .reloc section.  */
+
+static void
+generate_reloc (bfd *abfd, struct bfd_link_info *info)
+{
+
+  /* For .reloc stuff.  */
+  reloc_data_type *reloc_data;
+  int total_relocs = 0;
+  int i;
+  unsigned long sec_page = (unsigned long) -1;
+  unsigned long page_ptr, page_count;
+  int bi;
+  bfd *b;
+  struct bfd_section *s;
+
+  total_relocs = 0;
+  for (b = info->input_bfds; b; b = b->link_next)
+    for (s = b->sections; s; s = s->next)
+      total_relocs += s->reloc_count;
+
+  reloc_data = xmalloc (total_relocs * sizeof (reloc_data_type));
+
+  total_relocs = 0;
+  bi = 0;
+  for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next)
+    {
+      arelent **relocs;
+      int relsize, nrelocs, i;
+
+      for (s = b->sections; s; s = s->next)
+	{
+	  unsigned long sec_vma = s->output_section->vma + s->output_offset;
+	  asymbol **symbols;
+	  int nsyms, symsize;
+
+	  /* If it's not loaded, we don't need to relocate it this way.  */
+	  if (!(s->output_section->flags & SEC_LOAD))
+	    continue;
+
+	  /* I don't know why there would be a reloc for these, but I've
+	     seen it happen - DJ  */
+	  if (s->output_section == &bfd_abs_section)
+	    continue;
+
+	  if (s->output_section->vma == 0)
+	    {
+	      /* Huh?  Shouldn't happen, but punt if it does.  */
+	      einfo ("DJ: zero vma section reloc detected: `%s' #%d f=%d\n",
+		     s->output_section->name, s->output_section->index,
+		     s->output_section->flags);
+	      continue;
+	    }
+
+	  symsize = bfd_get_symtab_upper_bound (b);
+	  symbols = xmalloc (symsize);
+	  nsyms = bfd_canonicalize_symtab (b, symbols);
+
+	  relsize = bfd_get_reloc_upper_bound (b, s);
+	  relocs = xmalloc (relsize);
+	  nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
+
+	  for (i = 0; i < nrelocs; i++)
+	    {
+	      if (pep_dll_extra_pe_debug)
+		{
+		  struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
+		  printf ("rel: %s\n", sym->name);
+		}
+	      if (!relocs[i]->howto->pc_relative
+		  && relocs[i]->howto->type != pep_details->imagebase_reloc)
+		{
+		  bfd_vma sym_vma;
+		  struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
+
+		  sym_vma = (relocs[i]->addend
+			     + sym->value
+			     + sym->section->vma
+			     + sym->section->output_offset
+			     + sym->section->output_section->vma);
+		  reloc_data[total_relocs].vma = sec_vma + relocs[i]->address;
+
+#define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift)
+
+		  switch BITS_AND_SHIFT (relocs[i]->howto->bitsize,
+					 relocs[i]->howto->rightshift)
+		    {
+		    case BITS_AND_SHIFT (32, 0):
+		      reloc_data[total_relocs].type = 3;
+		      total_relocs++;
+		      break;
+		    case BITS_AND_SHIFT (16, 0):
+		      reloc_data[total_relocs].type = 2;
+		      total_relocs++;
+		      break;
+		    case BITS_AND_SHIFT (16, 16):
+		      reloc_data[total_relocs].type = 4;
+		      /* FIXME: we can't know the symbol's right value
+			 yet, but we probably can safely assume that
+			 CE will relocate us in 64k blocks, so leaving
+			 it zero is safe.  */
+		      reloc_data[total_relocs].extra = 0;
+		      total_relocs++;
+		      break;
+		    case BITS_AND_SHIFT (26, 2):
+		      reloc_data[total_relocs].type = 5;
+		      total_relocs++;
+			  break;
+			case BITS_AND_SHIFT (64, 0):
+				  reloc_data[total_relocs].type = 10;
+				  total_relocs++;
+				  break;
+		    case BITS_AND_SHIFT (24, 2):
+		      /* FIXME: 0 is ARM_26D, it is defined in bfd/coff-arm.c
+			 Those ARM_xxx definitions should go in proper
+			 header someday.  */
+		      if (relocs[i]->howto->type == 0
+			  /* Older GNU linkers used 5 instead of 0 for this reloc.  */
+			  || relocs[i]->howto->type == 5)
+			/* This is an ARM_26D reloc, which is an ARM_26 reloc
+			   that has already been fully processed during a
+			   previous link stage, so ignore it here.  */
+			break;
+		      /* Fall through.  */
+		    default:
+		      /* xgettext:c-format */
+		      einfo (_("%XError: %d-bit reloc in dll\n"),
+			     relocs[i]->howto->bitsize);
+		      break;
+		    }
+		}
+	    }
+	  free (relocs);
+	  /* Warning: the allocated symbols are remembered in BFD and
+	     reused later, so don't free them!  */
+	}
+    }
+
+  /* At this point, we have total_relocs relocation addresses in
+     reloc_addresses, which are all suitable for the .reloc section.
+     We must now create the new sections.  */
+  qsort (reloc_data, total_relocs, sizeof (*reloc_data), reloc_sort);
+
+  for (i = 0; i < total_relocs; i++)
+    {
+      unsigned long this_page = (reloc_data[i].vma >> 12);
+
+      if (this_page != sec_page)
+	{
+	  reloc_sz = (reloc_sz + 3) & ~3;	/* 4-byte align.  */
+	  reloc_sz += 8;
+	  sec_page = this_page;
+	}
+
+      reloc_sz += 2;
+
+      if (reloc_data[i].type == 4)
+	reloc_sz += 2;
+    }
+
+  reloc_sz = (reloc_sz + 3) & ~3;	/* 4-byte align.  */
+  reloc_d = xmalloc (reloc_sz);
+  sec_page = (unsigned long) -1;
+  reloc_sz = 0;
+  page_ptr = (unsigned long) -1;
+  page_count = 0;
+
+  for (i = 0; i < total_relocs; i++)
+    {
+      unsigned long rva = reloc_data[i].vma - image_base;
+      unsigned long this_page = (rva & ~0xfff);
+
+      if (this_page != sec_page)
+	{
+	  while (reloc_sz & 3)
+	    reloc_d[reloc_sz++] = 0;
+
+	  if (page_ptr != (unsigned long) -1)
+	    bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
+
+	  bfd_put_32 (abfd, this_page, reloc_d + reloc_sz);
+	  page_ptr = reloc_sz;
+	  reloc_sz += 8;
+	  sec_page = this_page;
+	  page_count = 0;
+	}
+
+      bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12),
+		  reloc_d + reloc_sz);
+
+      reloc_sz += 2;
+      if (reloc_data[i].type == 4)
+	{
+	  bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);
+	  reloc_sz += 2;
+	}
+
+
+      page_count++;
+    }
+
+  while (reloc_sz & 3)
+    reloc_d[reloc_sz++] = 0;
+
+  if (page_ptr != (unsigned long) -1)
+    bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
+
+  while (reloc_sz < reloc_s->size)
+    reloc_d[reloc_sz++] = 0;
+}
+
+/* Given the exiting def_file structure, print out a .DEF file that
+   corresponds to it.  */
+
+static void
+quoteput (char *s, FILE *f, int needs_quotes)
+{
+  char *cp;
+
+  for (cp = s; *cp; cp++)
+    if (*cp == '\''
+	|| *cp == '"'
+	|| *cp == '\\'
+	|| ISSPACE (*cp)
+	|| *cp == ','
+	|| *cp == ';')
+      needs_quotes = 1;
+
+  if (needs_quotes)
+    {
+      putc ('"', f);
+
+      while (*s)
+	{
+	  if (*s == '"' || *s == '\\')
+	    putc ('\\', f);
+
+	  putc (*s, f);
+	  s++;
+	}
+
+      putc ('"', f);
+    }
+  else
+    fputs (s, f);
+}
+
+void
+pep_dll_generate_def_file (const char *pep_out_def_filename)
+{
+  int i;
+  FILE *out = fopen (pep_out_def_filename, "w");
+
+  if (out == NULL)
+    /* xgettext:c-format */
+    einfo (_("%s: Can't open output def file %s\n"),
+	   program_name, pep_out_def_filename);
+
+  if (pep_def_file)
+    {
+      if (pep_def_file->name)
+	{
+	  if (pep_def_file->is_dll)
+	    fprintf (out, "LIBRARY ");
+	  else
+	    fprintf (out, "NAME ");
+
+	  quoteput (pep_def_file->name, out, 1);
+
+	  if (pe_data (output_bfd)->pe_opthdr.ImageBase)
+	    fprintf (out, " BASE=0x%lx",
+		     (unsigned long) pe_data (output_bfd)->pe_opthdr.ImageBase);
+	  fprintf (out, "\n");
+	}
+
+      if (pep_def_file->description)
+	{
+	  fprintf (out, "DESCRIPTION ");
+	  quoteput (pep_def_file->description, out, 1);
+	  fprintf (out, "\n");
+	}
+
+      if (pep_def_file->version_minor != -1)
+	fprintf (out, "VERSION %d.%d\n", pep_def_file->version_major,
+		 pep_def_file->version_minor);
+      else if (pep_def_file->version_major != -1)
+	fprintf (out, "VERSION %d\n", pep_def_file->version_major);
+
+      if (pep_def_file->stack_reserve != -1 || pep_def_file->heap_reserve != -1)
+	fprintf (out, "\n");
+
+      if (pep_def_file->stack_commit != -1)
+	fprintf (out, "STACKSIZE 0x%x,0x%x\n",
+		 pep_def_file->stack_reserve, pep_def_file->stack_commit);
+      else if (pep_def_file->stack_reserve != -1)
+	fprintf (out, "STACKSIZE 0x%x\n", pep_def_file->stack_reserve);
+
+      if (pep_def_file->heap_commit != -1)
+	fprintf (out, "HEAPSIZE 0x%x,0x%x\n",
+		 pep_def_file->heap_reserve, pep_def_file->heap_commit);
+      else if (pep_def_file->heap_reserve != -1)
+	fprintf (out, "HEAPSIZE 0x%x\n", pep_def_file->heap_reserve);
+
+      if (pep_def_file->num_section_defs > 0)
+	{
+	  fprintf (out, "\nSECTIONS\n\n");
+
+	  for (i = 0; i < pep_def_file->num_section_defs; i++)
+	    {
+	      fprintf (out, "    ");
+	      quoteput (pep_def_file->section_defs[i].name, out, 0);
+
+	      if (pep_def_file->section_defs[i].class)
+		{
+		  fprintf (out, " CLASS ");
+		  quoteput (pep_def_file->section_defs[i].class, out, 0);
+		}
+
+	      if (pep_def_file->section_defs[i].flag_read)
+		fprintf (out, " READ");
+
+	      if (pep_def_file->section_defs[i].flag_write)
+		fprintf (out, " WRITE");
+
+	      if (pep_def_file->section_defs[i].flag_execute)
+		fprintf (out, " EXECUTE");
+
+	      if (pep_def_file->section_defs[i].flag_shared)
+		fprintf (out, " SHARED");
+
+	      fprintf (out, "\n");
+	    }
+	}
+
+      if (pep_def_file->num_exports > 0)
+	{
+	  fprintf (out, "EXPORTS\n");
+
+	  for (i = 0; i < pep_def_file->num_exports; i++)
+	    {
+	      def_file_export *e = pep_def_file->exports + i;
+	      fprintf (out, "    ");
+	      quoteput (e->name, out, 0);
+
+	      if (e->internal_name && strcmp (e->internal_name, e->name))
+		{
+		  fprintf (out, " = ");
+		  quoteput (e->internal_name, out, 0);
+		}
+
+	      if (e->ordinal != -1)
+		fprintf (out, " @%d", e->ordinal);
+
+	      if (e->flag_private)
+		fprintf (out, " PRIVATE");
+
+	      if (e->flag_constant)
+		fprintf (out, " CONSTANT");
+
+	      if (e->flag_noname)
+		fprintf (out, " NONAME");
+
+	      if (e->flag_data)
+		fprintf (out, " DATA");
+
+	      fprintf (out, "\n");
+	    }
+	}
+
+      if (pep_def_file->num_imports > 0)
+	{
+	  fprintf (out, "\nIMPORTS\n\n");
+
+	  for (i = 0; i < pep_def_file->num_imports; i++)
+	    {
+	      def_file_import *im = pep_def_file->imports + i;
+	      fprintf (out, "    ");
+
+	      if (im->internal_name
+		  && (!im->name || strcmp (im->internal_name, im->name)))
+		{
+		  quoteput (im->internal_name, out, 0);
+		  fprintf (out, " = ");
+		}
+
+	      quoteput (im->module->name, out, 0);
+	      fprintf (out, ".");
+
+	      if (im->name)
+		quoteput (im->name, out, 0);
+	      else
+		fprintf (out, "%d", im->ordinal);
+
+	      fprintf (out, "\n");
+	    }
+	}
+    }
+  else
+    fprintf (out, _("; no contents available\n"));
+
+  if (fclose (out) == EOF)
+    /* xgettext:c-format */
+    einfo (_("%P: Error closing file `%s'\n"), pep_out_def_filename);
+}
+
+/* Generate the import library.  */
+
+static asymbol **symtab;
+static int symptr;
+static int tmp_seq;
+static const char *dll_filename;
+static char *dll_symname;
+
+#define UNDSEC (asection *) &bfd_und_section
+
+static asection *
+quick_section (bfd *abfd, const char *name, int flags, int align)
+{
+  asection *sec;
+  asymbol *sym;
+
+  sec = bfd_make_section_old_way (abfd, name);
+  bfd_set_section_flags (abfd, sec, flags | SEC_ALLOC | SEC_LOAD | SEC_KEEP);
+  bfd_set_section_alignment (abfd, sec, align);
+  /* Remember to undo this before trying to link internally!  */
+  sec->output_section = sec;
+
+  sym = bfd_make_empty_symbol (abfd);
+  symtab[symptr++] = sym;
+  sym->name = sec->name;
+  sym->section = sec;
+  sym->flags = BSF_LOCAL;
+  sym->value = 0;
+
+  return sec;
+}
+
+static void
+quick_symbol (bfd *abfd,
+	      const char *n1,
+	      const char *n2,
+	      const char *n3,
+	      asection *sec,
+	      int flags,
+	      int addr)
+{
+  asymbol *sym;
+  char *name = xmalloc (strlen (n1) + strlen (n2) + strlen (n3) + 1);
+
+  strcpy (name, n1);
+  strcat (name, n2);
+  strcat (name, n3);
+  sym = bfd_make_empty_symbol (abfd);
+  sym->name = name;
+  sym->section = sec;
+  sym->flags = flags;
+  sym->value = addr;
+  symtab[symptr++] = sym;
+}
+
+static arelent *reltab = 0;
+static int relcount = 0, relsize = 0;
+
+static void
+quick_reloc (bfd *abfd, int address, int which_howto, int symidx)
+{
+  if (relcount >= relsize - 1)
+    {
+      relsize += 10;
+      if (reltab)
+	reltab = xrealloc (reltab, relsize * sizeof (arelent));
+      else
+	reltab = xmalloc (relsize * sizeof (arelent));
+    }
+  reltab[relcount].address = address;
+  reltab[relcount].addend = 0;
+  reltab[relcount].howto = bfd_reloc_type_lookup (abfd, which_howto);
+  reltab[relcount].sym_ptr_ptr = symtab + symidx;
+  relcount++;
+}
+
+static void
+save_relocs (asection *sec)
+{
+  int i;
+
+  sec->relocation = reltab;
+  sec->reloc_count = relcount;
+  sec->orelocation = xmalloc ((relcount + 1) * sizeof (arelent *));
+  for (i = 0; i < relcount; i++)
+    sec->orelocation[i] = sec->relocation + i;
+  sec->orelocation[relcount] = 0;
+  sec->flags |= SEC_RELOC;
+  reltab = 0;
+  relcount = relsize = 0;
+}
+
+/*	.section	.idata$2
+ 	.global		__head_my_dll
+   __head_my_dll:
+ 	.rva		hname
+ 	.long		0
+ 	.long		0
+ 	.rva		__my_dll_iname
+ 	.rva		fthunk
+
+ 	.section	.idata$5
+ 	.long		0
+ 	.long		0
+   fthunk:
+
+ 	.section	.idata$4
+ 	.long		0
+ 	.long		0
+   hname:                              */
+
+static bfd *
+make_head (bfd *parent)
+{
+  asection *id2, *id5, *id4;
+  unsigned char *d2, *d5, *d4;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "d%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (6 * sizeof (asymbol *));
+  id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2);
+  id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
+  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
+  quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0);
+  quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
+
+  /* OK, pay attention here.  I got confused myself looking back at
+     it.  We create a four-byte section to mark the beginning of the
+     list, and we include an offset of 4 in the section, so that the
+     pointer to the list points to the *end* of this section, which is
+     the start of the list of sections from other objects.  */
+
+  bfd_set_section_size (abfd, id2, 20);
+  d2 = xmalloc (20);
+  id2->contents = d2;
+  memset (d2, 0, 20);
+  d2[0] = d2[16] = 4; /* Reloc addend.  */
+  quick_reloc (abfd,  0, BFD_RELOC_RVA, 2);
+  quick_reloc (abfd, 12, BFD_RELOC_RVA, 4);
+  quick_reloc (abfd, 16, BFD_RELOC_RVA, 1);
+  save_relocs (id2);
+
+  bfd_set_section_size (abfd, id5, 8);
+  d5 = xmalloc (8);
+  id5->contents = d5;
+  memset (d5, 0, 8);
+
+  bfd_set_section_size (abfd, id4, 8);
+  d4 = xmalloc (8);
+  id4->contents = d4;
+  memset (d4, 0, 8);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, id2, d2, 0, 20);
+  bfd_set_section_contents (abfd, id5, d5, 0, 8);
+  bfd_set_section_contents (abfd, id4, d4, 0, 8);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+/*	.section	.idata$4
+ 	.long		0
+  	.long		0
+	.section	.idata$5
+ 	.long		0
+ 	.long		0
+ 	.section	idata$7
+ 	.global		__my_dll_iname
+  __my_dll_iname:
+ 	.asciz		"my.dll"       */
+
+static bfd *
+make_tail (bfd *parent)
+{
+  asection *id4, *id5, *id7;
+  unsigned char *d4, *d5, *d7;
+  int len;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "d%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (5 * sizeof (asymbol *));
+  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
+  id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
+  id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
+  quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0);
+
+  bfd_set_section_size (abfd, id4, 8);
+  d4 = xmalloc (8);
+  id4->contents = d4;
+  memset (d4, 0, 8);
+
+  bfd_set_section_size (abfd, id5, 8);
+  d5 = xmalloc (8);
+  id5->contents = d5;
+  memset (d5, 0, 8);
+
+  len = strlen (dll_filename) + 1;
+  if (len & 1)
+    len++;
+  bfd_set_section_size (abfd, id7, len);
+  d7 = xmalloc (len);
+  id7->contents = d7;
+  strcpy ((char *) d7, dll_filename);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, id4, d4, 0, 8);
+  bfd_set_section_contents (abfd, id5, d5, 0, 8);
+  bfd_set_section_contents (abfd, id7, d7, 0, len);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+/*	.text
+ 	.global		_function
+ 	.global		___imp_function
+ 	.global		__imp__function
+  _function:
+ 	jmp		*__imp__function:
+
+ 	.section	idata$7
+ 	.long		__head_my_dll
+
+ 	.section	.idata$5
+  ___imp_function:
+  __imp__function:
+  iat?
+  	.section	.idata$4
+  iat?
+ 	.section	.idata$6
+  ID<ordinal>:
+ 	.short		<hint>
+ 	.asciz		"function" xlate? (add underscore, kill at)  */
+
+static unsigned char jmp_ix86_bytes[] =
+{
+  0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
+};
+
+static bfd *
+make_one (def_file_export *exp, bfd *parent)
+{
+  asection *tx, *id7, *id5, *id4, *id6;
+  unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL;
+  int len;
+  char *oname;
+  bfd *abfd;
+  unsigned char *jmp_bytes = NULL;
+  int jmp_byte_count = 0;
+
+  switch (pep_details->pep_arch)
+    {
+    case PE_ARCH_i386:
+      jmp_bytes = jmp_ix86_bytes;
+      jmp_byte_count = sizeof (jmp_ix86_bytes);
+      break;
+    default:
+      abort ();
+    }
+
+  oname = xmalloc (20);
+  sprintf (oname, "d%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (11 * sizeof (asymbol *));
+  tx  = quick_section (abfd, ".text",    SEC_CODE|SEC_HAS_CONTENTS, 2);
+  id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
+  id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
+  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
+  id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2);
+
+  if  (*exp->internal_name == '@')
+    {
+      quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
+		    BSF_GLOBAL, 0);
+      if (! exp->flag_data)
+	quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0);
+      quick_symbol (abfd, U ("_imp_"), exp->internal_name, "", id5,
+		    BSF_GLOBAL, 0);
+      /* Fastcall applies only to functions,
+	 so no need for auto-import symbol.  */
+    }
+  else
+    {
+      quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
+		    BSF_GLOBAL, 0);
+      if (! exp->flag_data)
+	quick_symbol (abfd, U (""), exp->internal_name, "", tx,
+		      BSF_GLOBAL, 0);
+      quick_symbol (abfd, U ("_imp__"), exp->internal_name, "", id5,
+		    BSF_GLOBAL, 0);
+      /* Symbol to reference ord/name of imported
+	 data symbol, used to implement auto-import.  */
+      if (exp->flag_data)
+	quick_symbol (abfd, U("_nm__"), exp->internal_name, "", id6,
+		      BSF_GLOBAL,0);
+    }
+  if (pep_dll_compat_implib)
+    quick_symbol (abfd, U ("__imp_"), exp->internal_name, "", id5,
+		  BSF_GLOBAL, 0);
+
+  if (! exp->flag_data)
+    {
+      bfd_set_section_size (abfd, tx, jmp_byte_count);
+      td = xmalloc (jmp_byte_count);
+      tx->contents = td;
+      memcpy (td, jmp_bytes, jmp_byte_count);
+
+      switch (pep_details->pep_arch)
+	{
+	case PE_ARCH_i386:
+	  quick_reloc (abfd, 2, BFD_RELOC_32, 2);
+	  break;
+	case PE_ARCH_sh:
+	  quick_reloc (abfd, 8, BFD_RELOC_32, 2);
+	  break;
+	case PE_ARCH_mips:
+	  quick_reloc (abfd, 0, BFD_RELOC_HI16_S, 2);
+	  quick_reloc (abfd, 0, BFD_RELOC_LO16, 0); /* MIPS_R_PAIR */
+	  quick_reloc (abfd, 4, BFD_RELOC_LO16, 2);
+	  break;
+	default:
+	  abort ();
+	}
+      save_relocs (tx);
+    }
+
+  bfd_set_section_size (abfd, id7, 4);
+  d7 = xmalloc (4);
+  id7->contents = d7;
+  memset (d7, 0, 4);
+  quick_reloc (abfd, 0, BFD_RELOC_RVA, 5);
+  save_relocs (id7);
+
+  bfd_set_section_size (abfd, id5, 8);
+  d5 = xmalloc (8);
+  id5->contents = d5;
+  memset (d5, 0, 8);
+
+  if (exp->flag_noname)
+    {
+      d5[0] = exp->ordinal;
+      d5[1] = exp->ordinal >> 8;
+      d5[7] = 0x80;
+    }
+  else
+    {
+      quick_reloc (abfd, 0, BFD_RELOC_RVA, 4);
+      save_relocs (id5);
+    }
+
+  bfd_set_section_size (abfd, id4, 8);
+  d4 = xmalloc (8);
+  id4->contents = d4;
+  memset (d4, 0, 8);
+
+  if (exp->flag_noname)
+    {
+      d4[0] = exp->ordinal;
+      d4[1] = exp->ordinal >> 8;
+      d4[7] = 0x80;
+    }
+  else
+    {
+      quick_reloc (abfd, 0, BFD_RELOC_RVA, 4);
+      save_relocs (id4);
+    }
+
+  if (exp->flag_noname)
+    {
+      len = 0;
+      bfd_set_section_size (abfd, id6, 0);
+    }
+  else
+    {
+      len = strlen (exp->name) + 3;
+      if (len & 1)
+	len++;
+      bfd_set_section_size (abfd, id6, len);
+      d6 = xmalloc (len);
+      id6->contents = d6;
+      memset (d6, 0, len);
+      d6[0] = exp->hint & 0xff;
+      d6[1] = exp->hint >> 8;
+      strcpy ((char *) d6 + 2, exp->name);
+    }
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count);
+  bfd_set_section_contents (abfd, id7, d7, 0, 4);
+  bfd_set_section_contents (abfd, id5, d5, 0, 8);
+  bfd_set_section_contents (abfd, id4, d4, 0, 8);
+  if (!exp->flag_noname)
+    bfd_set_section_contents (abfd, id6, d6, 0, len);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+static bfd *
+make_singleton_name_thunk (const char *import, bfd *parent)
+{
+  /* Name thunks go to idata$4.  */
+  asection *id4;
+  unsigned char *d4;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "nmth%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (3 * sizeof (asymbol *));
+  id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
+  quick_symbol (abfd, U ("_nm_thnk_"), import, "", id4, BSF_GLOBAL, 0);
+  quick_symbol (abfd, U ("_nm_"), import, "", UNDSEC, BSF_GLOBAL, 0);
+
+  bfd_set_section_size (abfd, id4, 8);
+  d4 = xmalloc (8);
+  id4->contents = d4;
+  memset (d4, 0, 8);
+  quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);
+  save_relocs (id4);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, id4, d4, 0, 8);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+static char *
+make_import_fixup_mark (arelent *rel)
+{
+  /* We convert reloc to symbol, for later reference.  */
+  static int counter;
+  static char *fixup_name = NULL;
+  static size_t buffer_len = 0;
+
+  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
+
+  bfd *abfd = bfd_asymbol_bfd (sym);
+  struct bfd_link_hash_entry *bh;
+
+  if (!fixup_name)
+    {
+      fixup_name = xmalloc (384);
+      buffer_len = 384;
+    }
+
+  if (strlen (sym->name) + 25 > buffer_len)
+  /* Assume 25 chars for "__fu" + counter + "_".  If counter is
+     bigger than 20 digits long, we've got worse problems than
+     overflowing this buffer...  */
+    {
+      free (fixup_name);
+      /* New buffer size is length of symbol, plus 25, but
+	 then rounded up to the nearest multiple of 128.  */
+      buffer_len = ((strlen (sym->name) + 25) + 127) & ~127;
+      fixup_name = xmalloc (buffer_len);
+    }
+
+  sprintf (fixup_name, "__fu%d_%s", counter++, sym->name);
+
+  bh = NULL;
+  bfd_coff_link_add_one_symbol (&link_info, abfd, fixup_name, BSF_GLOBAL,
+				current_sec, /* sym->section, */
+				rel->address, NULL, TRUE, FALSE, &bh);
+
+  if (0)
+    {
+      struct coff_link_hash_entry *myh;
+
+      myh = (struct coff_link_hash_entry *) bh;
+      printf ("type:%d\n", myh->type);
+      printf ("%s\n", myh->root.u.def.section->name);
+    }
+
+  return fixup_name;
+}
+
+/*	.section	.idata$3
+  	.rva		__nm_thnk_SYM (singleton thunk with name of func)
+ 	.long		0
+ 	.long		0
+ 	.rva		__my_dll_iname (name of dll)
+ 	.rva		__fuNN_SYM (pointer to reference (address) in text)  */
+
+static bfd *
+make_import_fixup_entry (const char *name,
+			 const char *fixup_name,
+			 const char *dll_symname,
+			 bfd *parent)
+{
+  asection *id3;
+  unsigned char *d3;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "fu%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (6 * sizeof (asymbol *));
+  id3 = quick_section (abfd, ".idata$3", SEC_HAS_CONTENTS, 2);
+
+  quick_symbol (abfd, U ("_nm_thnk_"), name, "", UNDSEC, BSF_GLOBAL, 0);
+  quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
+  quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
+
+  bfd_set_section_size (abfd, id3, 20);
+  d3 = xmalloc (20);
+  id3->contents = d3;
+  memset (d3, 0, 20);
+
+  quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
+  quick_reloc (abfd, 12, BFD_RELOC_RVA, 2);
+  quick_reloc (abfd, 16, BFD_RELOC_RVA, 3);
+  save_relocs (id3);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, id3, d3, 0, 20);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+/*	.section	.rdata_runtime_pseudo_reloc
+ 	.long		addend
+ 	.rva		__fuNN_SYM (pointer to reference (address) in text)  */
+
+static bfd *
+make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED,
+			   const char *fixup_name,
+			   int addend,
+			   bfd *parent)
+{
+  asection *rt_rel;
+  unsigned char *rt_rel_d;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "rtr%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (2 * sizeof (asymbol *));
+  rt_rel = quick_section (abfd, ".rdata_runtime_pseudo_reloc",
+			  SEC_HAS_CONTENTS, 2);
+
+  quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
+
+  bfd_set_section_size (abfd, rt_rel, 8);
+  rt_rel_d = xmalloc (8);
+  rt_rel->contents = rt_rel_d;
+  memset (rt_rel_d, 0, 8);
+  bfd_put_32 (abfd, addend, rt_rel_d);
+
+  quick_reloc (abfd, 4, BFD_RELOC_RVA, 1);
+  save_relocs (rt_rel);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, 8);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+/*	.section	.rdata
+ 	.rva		__pei386_runtime_relocator  */
+
+static bfd *
+pep_create_runtime_relocator_reference (bfd *parent)
+{
+  asection *extern_rt_rel;
+  unsigned char *extern_rt_rel_d;
+  char *oname;
+  bfd *abfd;
+
+  oname = xmalloc (20);
+  sprintf (oname, "ertr%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pep_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pep_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = xmalloc (2 * sizeof (asymbol *));
+  extern_rt_rel = quick_section (abfd, ".rdata", SEC_HAS_CONTENTS, 2);
+
+  quick_symbol (abfd, "", "__pei386_runtime_relocator", "", UNDSEC,
+		BSF_NO_FLAGS, 0);
+
+  bfd_set_section_size (abfd, extern_rt_rel, 4);
+  extern_rt_rel_d = xmalloc (4);
+  extern_rt_rel->contents = extern_rt_rel_d;
+
+  quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
+  save_relocs (extern_rt_rel);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, extern_rt_rel, extern_rt_rel_d, 0, 4);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+void
+pep_create_import_fixup (arelent *rel, asection *s, int addend)
+{
+  char buf[300];
+  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
+  struct bfd_link_hash_entry *name_thunk_sym;
+  const char *name = sym->name;
+  char *fixup_name = make_import_fixup_mark (rel);
+  bfd *b;
+
+  sprintf (buf, U ("_nm_thnk_%s"), name);
+
+  name_thunk_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
+
+  if (!name_thunk_sym || name_thunk_sym->type != bfd_link_hash_defined)
+    {
+      bfd *b = make_singleton_name_thunk (name, output_bfd);
+      add_bfd_to_link (b, b->filename, &link_info);
+
+      /* If we ever use autoimport, we have to cast text section writable.  */
+      config.text_read_only = FALSE;
+      output_bfd->flags &= ~WP_TEXT;   
+    }
+
+  if (addend == 0 || link_info.pei386_runtime_pseudo_reloc)
+    {
+      extern char * pep_data_import_dll;
+      char * dll_symname = pep_data_import_dll ? pep_data_import_dll : "unknown";
+
+      b = make_import_fixup_entry (name, fixup_name, dll_symname, output_bfd);
+      add_bfd_to_link (b, b->filename, &link_info);
+    }
+
+  if (addend != 0)
+    {
+      if (link_info.pei386_runtime_pseudo_reloc)
+	{
+	  if (pep_dll_extra_pe_debug)
+	    printf ("creating runtime pseudo-reloc entry for %s (addend=%d)\n",
+		   fixup_name, addend);
+	  b = make_runtime_pseudo_reloc (name, fixup_name, addend, output_bfd);
+	  add_bfd_to_link (b, b->filename, &link_info);
+
+	  if (runtime_pseudo_relocs_created == 0)
+	    {
+	      b = pep_create_runtime_relocator_reference (output_bfd);
+	      add_bfd_to_link (b, b->filename, &link_info);
+	    }
+	  runtime_pseudo_relocs_created++;
+	}
+      else
+	{
+	  einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"),
+		 s->owner, s, rel->address, sym->name);
+	  einfo ("%X");
+	}
+    }
+}
+
+
+void
+pep_dll_generate_implib (def_file *def, const char *impfilename)
+{
+  int i;
+  bfd *ar_head;
+  bfd *ar_tail;
+  bfd *outarch;
+  bfd *head = 0;
+
+  dll_filename = (def->name) ? def->name : dll_name;
+  dll_symname = xstrdup (dll_filename);
+  for (i = 0; dll_symname[i]; i++)
+    if (!ISALNUM (dll_symname[i]))
+      dll_symname[i] = '_';
+
+  unlink_if_ordinary (impfilename);
+
+  outarch = bfd_openw (impfilename, 0);
+
+  if (!outarch)
+    {
+      /* xgettext:c-format */
+      einfo (_("%XCan't open .lib file: %s\n"), impfilename);
+      return;
+    }
+
+  /* xgettext:c-format */
+  info_msg (_("Creating library file: %s\n"), impfilename);
+ 
+  bfd_set_format (outarch, bfd_archive);
+  outarch->has_armap = 1;
+
+  /* Work out a reasonable size of things to put onto one line.  */
+  ar_head = make_head (outarch);
+
+  for (i = 0; i < def->num_exports; i++)
+    {
+      /* The import library doesn't know about the internal name.  */
+      char *internal = def->exports[i].internal_name;
+      bfd *n;
+
+      /* Don't add PRIVATE entries to import lib.  */ 	
+      if (pep_def_file->exports[i].flag_private)
+	continue;
+      def->exports[i].internal_name = def->exports[i].name;
+      n = make_one (def->exports + i, outarch);
+      n->next = head;
+      head = n;
+      def->exports[i].internal_name = internal;
+    }
+
+  ar_tail = make_tail (outarch);
+
+  if (ar_head == NULL || ar_tail == NULL)
+    return;
+
+  /* Now stick them all into the archive.  */
+  ar_head->next = head;
+  ar_tail->next = ar_head;
+  head = ar_tail;
+
+  if (! bfd_set_archive_head (outarch, head))
+    einfo ("%Xbfd_set_archive_head: %E\n");
+
+  if (! bfd_close (outarch))
+    einfo ("%Xbfd_close %s: %E\n", impfilename);
+
+  while (head != NULL)
+    {
+      bfd *n = head->next;
+      bfd_close (head);
+      head = n;
+    }
+}
+
+static void
+add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *link_info)
+{
+  lang_input_statement_type *fake_file;
+
+  fake_file = lang_add_input_file (name,
+				   lang_input_file_is_fake_enum,
+				   NULL);
+  fake_file->the_bfd = abfd;
+  ldlang_add_file (fake_file);
+
+  if (!bfd_link_add_symbols (abfd, link_info))
+    einfo ("%Xaddsym %s: %E\n", name);
+}
+
+void
+pep_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
+{
+  def_file_module *module;
+
+  pep_dll_id_target (bfd_get_target (output_bfd));
+
+  if (!pep_def_file)
+    return;
+
+  for (module = pep_def_file->modules; module; module = module->next)
+    {
+      int i, do_this_dll;
+
+      dll_filename = module->name;
+      dll_symname = xstrdup (module->name);
+      for (i = 0; dll_symname[i]; i++)
+	if (!ISALNUM (dll_symname[i]))
+	  dll_symname[i] = '_';
+
+      do_this_dll = 0;
+
+      for (i = 0; i < pep_def_file->num_imports; i++)
+	if (pep_def_file->imports[i].module == module)
+	  {
+	    def_file_export exp;
+	    struct bfd_link_hash_entry *blhe;
+	    int lead_at = (*pep_def_file->imports[i].internal_name == '@');
+	    /* See if we need this import.  */
+	    size_t len = strlen (pep_def_file->imports[i].internal_name);
+	    char *name = xmalloc (len + 2 + 6);
+
+ 	    if (lead_at)
+	      sprintf (name, "%s%s", "",
+		       pep_def_file->imports[i].internal_name);
+	    else
+	      sprintf (name, "%s%s",U (""),
+		       pep_def_file->imports[i].internal_name);
+
+	    blhe = bfd_link_hash_lookup (link_info->hash, name,
+					 FALSE, FALSE, FALSE);
+
+	    if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
+	      {
+		if (lead_at)
+		  sprintf (name, "%s%s", U ("_imp_"),
+			   pep_def_file->imports[i].internal_name);
+		else
+		  sprintf (name, "%s%s", U ("_imp__"),
+			   pep_def_file->imports[i].internal_name);
+
+		blhe = bfd_link_hash_lookup (link_info->hash, name,
+					     FALSE, FALSE, FALSE);
+	      }
+	    free (name);
+
+	    if (blhe && blhe->type == bfd_link_hash_undefined)
+	      {
+		bfd *one;
+		/* We do.  */
+		if (!do_this_dll)
+		  {
+		    bfd *ar_head = make_head (output_bfd);
+		    add_bfd_to_link (ar_head, ar_head->filename, link_info);
+		    do_this_dll = 1;
+		  }
+		exp.internal_name = pep_def_file->imports[i].internal_name;
+		exp.name = pep_def_file->imports[i].name;
+		exp.ordinal = pep_def_file->imports[i].ordinal;
+		exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
+		exp.flag_private = 0;
+		exp.flag_constant = 0;
+		exp.flag_data = pep_def_file->imports[i].data;
+		exp.flag_noname = exp.name ? 0 : 1;
+		one = make_one (&exp, output_bfd);
+		add_bfd_to_link (one, one->filename, link_info);
+	      }
+	  }
+      if (do_this_dll)
+	{
+	  bfd *ar_tail = make_tail (output_bfd);
+	  add_bfd_to_link (ar_tail, ar_tail->filename, link_info);
+	}
+
+      free (dll_symname);
+    }
+}
+
+/* We were handed a *.DLL file.  Parse it and turn it into a set of
+   IMPORTS directives in the def file.  Return TRUE if the file was
+   handled, FALSE if not.  */
+
+static unsigned int
+pep_get16 (bfd *abfd, int where)
+{
+  unsigned char b[2];
+
+  bfd_seek (abfd, (file_ptr) where, SEEK_SET);
+  bfd_bread (b, (bfd_size_type) 2, abfd);
+  return b[0] + (b[1] << 8);
+}
+
+static unsigned int
+pep_get32 (bfd *abfd, int where)
+{
+  unsigned char b[4];
+
+  bfd_seek (abfd, (file_ptr) where, SEEK_SET);
+  bfd_bread (b, (bfd_size_type) 4, abfd);
+  return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
+}
+
+static unsigned int
+pep_as32 (void *ptr)
+{
+  unsigned char *b = ptr;
+
+  return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
+}
+
+bfd_boolean
+pep_implied_import_dll (const char *filename)
+{
+  bfd *dll;
+  unsigned long pep_header_offset, opthdr_ofs, num_entries, i;
+  unsigned long export_rva, export_size, nsections, secptr, expptr;
+  unsigned long exp_funcbase;
+  unsigned char *expdata;
+  char *erva;
+  unsigned long name_rvas, ordinals, nexp, ordbase;
+  const char *dll_name;
+  /* Initialization with start > end guarantees that is_data
+     will not be set by mistake, and avoids compiler warning.  */
+  unsigned long data_start = 1;
+  unsigned long data_end = 0;
+  unsigned long rdata_start = 1;
+  unsigned long rdata_end = 0;
+  unsigned long bss_start = 1;
+  unsigned long bss_end = 0;
+
+  /* No, I can't use bfd here.  kernel32.dll puts its export table in
+     the middle of the .rdata section.  */
+  dll = bfd_openr (filename, pep_details->target_name);
+  if (!dll)
+    {
+      einfo ("%Xopen %s: %E\n", filename);
+      return FALSE;
+    }
+
+  /* PEI dlls seem to be bfd_objects.  */
+  if (!bfd_check_format (dll, bfd_object))
+    {
+      einfo ("%X%s: this doesn't appear to be a DLL\n", filename);
+      return FALSE;
+    }
+
+  /* Get pe_header, optional header and numbers of export entries.  */
+  pep_header_offset = pep_get32 (dll, 0x3c);
+  opthdr_ofs = pep_header_offset + 4 + 20; // Magic of opt header
+  num_entries = pep_get32 (dll, opthdr_ofs + 92 +4*4); //  &NumberOfRvaAndSizes
+
+  if (pep_dll_extra_pe_debug)
+	  printf ("%s: Export num_entries %ld\n", __FUNCTION__,num_entries);
+
+  if (num_entries < 1) /* No exports.  */
+    return FALSE;
+
+  export_rva = pep_get32 (dll, opthdr_ofs + 96+4*4);
+  export_size = pep_get32 (dll, opthdr_ofs + 100+4*4);
+  nsections = pep_get16 (dll, pep_header_offset + 4 + 2);
+  secptr = (pep_header_offset + 4 + 20 +
+	    pep_get16 (dll, pep_header_offset + 4 + 16));
+  expptr = 0;
+
+  /* Get the rva and size of the export section.  */
+  for (i = 0; i < nsections; i++)
+    {
+      char sname[8];
+      unsigned long secptr1 = secptr + 40 * i;
+      unsigned long vaddr = pep_get32 (dll, secptr1 + 12);
+      unsigned long vsize = pep_get32 (dll, secptr1 + 16);
+      unsigned long fptr = pep_get32 (dll, secptr1 + 20);
+
+      bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
+      bfd_bread (sname, (bfd_size_type) 8, dll);
+
+      if (vaddr <= export_rva && vaddr + vsize > export_rva)
+	{
+	  expptr = fptr + (export_rva - vaddr);
+	  if (export_rva + export_size > vaddr + vsize)
+	    export_size = vsize - (export_rva - vaddr);
+	  break;
+	}
+    }
+
+  /* Scan sections and store the base and size of the
+     data and bss segments in data/base_start/end.  */
+  for (i = 0; i < nsections; i++)
+    {
+      unsigned long secptr1 = secptr + 40 * i;
+      unsigned long vsize = pep_get32 (dll, secptr1 + 8);
+      unsigned long vaddr = pep_get32 (dll, secptr1 + 12);
+      unsigned long flags = pep_get32 (dll, secptr1 + 36);
+      char sec_name[9];
+
+      sec_name[8] = '\0';
+      bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
+      bfd_bread (sec_name, (bfd_size_type) 8, dll);
+
+      if (strcmp(sec_name,".data") == 0)
+	{
+	  data_start = vaddr;
+	  data_end = vaddr + vsize;
+
+	  if (pep_dll_extra_pe_debug)
+	    printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
+		    __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
+	}
+      else if (strcmp(sec_name,".rdata") == 0)
+	{
+	  rdata_start = vaddr;
+	  rdata_end = vaddr + vsize;
+
+	  if (pep_dll_extra_pe_debug)
+	    printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
+		    __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
+	}
+      else if (strcmp (sec_name,".bss") == 0)
+	{
+	  bss_start = vaddr;
+	  bss_end = vaddr + vsize;
+
+	  if (pep_dll_extra_pe_debug)
+	    printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
+		    __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
+	}
+    }
+
+  if (pep_dll_extra_pe_debug)
+	  printf ("%s: Export size:%lu offset:0x%llx\n",
+		__FUNCTION__,export_size,(file_ptr)expptr);
+  expdata = xmalloc (export_size);
+  bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
+  bfd_bread (expdata, (bfd_size_type) export_size, dll);
+  erva = (char *) expdata - export_rva;
+
+  if (pep_def_file == 0)
+    pep_def_file = def_file_empty ();
+
+  nexp = pep_as32 (expdata + 24);
+  name_rvas = pep_as32 (expdata + 32);
+  ordinals = pep_as32 (expdata + 36);
+  ordbase = pep_as32 (expdata + 16);
+  exp_funcbase = pep_as32 (expdata + 28);
+  if (pep_dll_extra_pe_debug)
+	  printf ("%s: nexp:%lu namerva:0x%lx ord:%lu ordbase:%lu fb=0x%lx\n",
+	    __FUNCTION__,nexp,name_rvas,ordinals,ordbase,exp_funcbase);
+
+  /* Use internal dll name instead of filename
+     to enable symbolic dll linking.  */
+  dll_name = erva + pep_as32 (expdata + 12);
+
+  /* Check to see if the dll has already been added to
+     the definition list and if so return without error.
+     This avoids multiple symbol definitions.  */
+  if (def_get_module (pep_def_file, dll_name))
+    {
+      if (pep_dll_extra_pe_debug)
+	printf ("%s is already loaded\n", dll_name);
+      return TRUE;
+    }
+
+  /* Iterate through the list of symbols.  */
+  for (i = 0; i < nexp; i++)
+    {
+      /* Pointer to the names vector.  */
+      unsigned long name_rva = pep_as32 (erva + name_rvas + i * 4);
+      def_file_import *imp;
+      /* Pointer to the function address vector.  */
+      unsigned long func_rva = pep_as32 (erva + exp_funcbase + i * 4);
+      int is_data = 0;
+
+      /* Skip unwanted symbols, which are
+	 exported in buggy auto-import releases.  */
+      if (strncmp (erva + name_rva, "_nm_", 4) != 0)
+ 	{
+ 	  /* is_data is true if the address is in the data, rdata or bss
+	     segment.  */
+ 	  is_data =
+	    (func_rva >= data_start && func_rva < data_end)
+	    || (func_rva >= rdata_start && func_rva < rdata_end)
+	    || (func_rva >= bss_start && func_rva < bss_end);
+
+	  imp = def_file_add_import (pep_def_file, erva + name_rva,
+				     dll_name, i, 0);
+ 	  /* Mark symbol type.  */
+ 	  imp->data = is_data;
+
+ 	  if (pep_dll_extra_pe_debug)
+	    printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
+		    __FUNCTION__, dll_name, erva + name_rva,
+		    func_rva, is_data ? "(data)" : "");
+ 	}
+    }
+
+  return TRUE;
+}
+
+/* These are the main functions, called from the emulation.  The first
+   is called after the bfds are read, so we can guess at how much space
+   we need.  The second is called after everything is placed, so we
+   can put the right values in place.  */
+
+void
+pep_dll_build_sections (bfd *abfd, struct bfd_link_info *info)
+{
+  pep_dll_id_target (bfd_get_target (abfd));
+  process_def_file (abfd, info);
+
+  if (pep_def_file->num_exports == 0 && !info->shared)
+    return;
+
+  generate_edata (abfd, info);
+  build_filler_bfd (1);
+}
+
+void
+pep_exe_build_sections (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  pep_dll_id_target (bfd_get_target (abfd));
+  build_filler_bfd (0);
+}
+
+void
+pep_dll_fill_sections (bfd *abfd, struct bfd_link_info *info)
+{
+  pep_dll_id_target (bfd_get_target (abfd));
+  image_base = pe_data (abfd)->pe_opthdr.ImageBase;
+
+  generate_reloc (abfd, info);
+  if (reloc_sz > 0)
+    {
+      bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
+
+      /* Resize the sections.  */
+      lang_reset_memory_regions ();
+      lang_size_sections (NULL, TRUE);
+
+      /* Redo special stuff.  */
+      ldemul_after_allocation ();
+
+      /* Do the assignments again.  */
+      lang_do_assignments ();
+    }
+
+  fill_edata (abfd, info);
+
+  if (info->shared && !info->pie)
+    pe_data (abfd)->dll = 1;
+
+  edata_s->contents = edata_d;
+  reloc_s->contents = reloc_d;
+}
+
+void
+pep_exe_fill_sections (bfd *abfd, struct bfd_link_info *info)
+{
+  pep_dll_id_target (bfd_get_target (abfd));
+  image_base = pe_data (abfd)->pe_opthdr.ImageBase;
+
+  generate_reloc (abfd, info);
+  if (reloc_sz > 0)
+    {
+      bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
+
+      /* Resize the sections.  */
+      lang_reset_memory_regions ();
+      lang_size_sections (NULL, TRUE);
+
+      /* Redo special stuff.  */
+      ldemul_after_allocation ();
+
+      /* Do the assignments again.  */
+      lang_do_assignments ();
+    }
+  reloc_s->contents = reloc_d;
+}
diff -rNbu binutils-2.17_org/ld/pep-dll.h binutils-2.17/ld/pep-dll.h
--- binutils-2.17_org/ld/pep-dll.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/ld/pep-dll.h	2006-08-17 09:13:35.000000000 +0200
@@ -0,0 +1,64 @@
+/* pep-dll.h: Header file for routines used to build Windows DLLs.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#ifndef PEP_DLL_H
+#define PEP_DLL_H
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "deffile.h"
+
+extern def_file *pep_def_file;
+extern int pep_dll_export_everything;
+extern int pep_dll_do_default_excludes;
+extern int pep_dll_kill_ats;
+extern int pep_dll_stdcall_aliases;
+extern int pep_dll_warn_dup_exports;
+extern int pep_dll_compat_implib;
+extern int pep_dll_extra_pe_debug;
+
+extern void pep_dll_id_target
+  (const char *);
+extern void pep_dll_add_excludes
+  (const char *, const int);
+extern void pep_dll_generate_def_file
+  (const char *);
+extern void pep_dll_generate_implib
+  (def_file *, const char *);
+extern void pep_process_import_defs
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean pep_implied_import_dll
+  (const char *);
+extern void pep_dll_build_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_exe_build_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_dll_fill_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_exe_fill_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_walk_relocs_of_symbol
+  (struct bfd_link_info *, const char *, int (*) (arelent *, asection *));
+extern void pep_create_import_fixup
+  (arelent * rel, asection *, int);
+#endif /* PE_DLL_H */
diff -rNbu binutils-2.17_org/ld/po/POTFILES.in binutils-2.17/ld/po/POTFILES.in
--- binutils-2.17_org/ld/po/POTFILES.in	2006-04-16 20:21:51.000000000 +0200
+++ binutils-2.17/ld/po/POTFILES.in	2006-08-02 13:44:47.000000000 +0200
@@ -28,3 +28,5 @@
 mri.h
 pe-dll.c
 pe-dll.h
+pep-dll.c
+pep-dll.h
diff -rNbu binutils-2.17_org/ld/scripttempl/pep.sc binutils-2.17/ld/scripttempl/pep.sc
--- binutils-2.17_org/ld/scripttempl/pep.sc	1970-01-01 01:00:00.000000000 +0100
+++ binutils-2.17/ld/scripttempl/pep.sc	2006-07-28 14:12:23.000000000 +0200
@@ -0,0 +1,272 @@
+# Linker script for PE.
+
+if test -z "${RELOCATEABLE_OUTPUT_FORMAT}"; then
+  RELOCATEABLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+fi
+
+# We can't easily and portably get an unquoted $ in a shell
+# substitution, so we do this instead.
+# Sorting of the .foo$* sections is required by the definition of
+# grouped sections in PE.
+# Sorting of the file names in R_IDATA is required by the
+# current implementation of dlltool (this could probably be changed to
+# use grouped sections instead).
+if test "${RELOCATING}"; then
+  R_TEXT='*(SORT(.text$*))'
+  R_DATA='*(SORT(.data$*))'
+  R_RDATA='*(SORT(.rdata$*))'
+  R_IDATA='
+    SORT(*)(.idata$2)
+    SORT(*)(.idata$3)
+    /* These zeroes mark the end of the import list.  */
+    LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
+    SORT(*)(.idata$4)
+    SORT(*)(.idata$5)
+    SORT(*)(.idata$6)
+    SORT(*)(.idata$7)'
+  R_CRT_XC='*(SORT(.CRT$XC*))  /* C initialization */'
+  R_CRT_XI='*(SORT(.CRT$XI*))  /* C++ initialization */'
+  R_CRT_XL='*(SORT(.CRT$XL*))  /* TLS callbacks */'
+  R_CRT_XP='*(SORT(.CRT$XP*))  /* Pre-termination */'
+  R_CRT_XT='*(SORT(.CRT$XT*))  /* Termination */'
+  R_TLS='
+    *(.tls)
+    *(.tls$)
+    *(SORT(.tls$*))'
+  R_RSRC='*(SORT(.rsrc$*))'
+else
+  R_TEXT=
+  R_DATA=
+  R_RDATA=
+  R_IDATA=
+  R_CRT=
+  R_RSRC=
+fi
+
+cat <<EOF
+${RELOCATING+OUTPUT_FORMAT(${OUTPUT_FORMAT})}
+${RELOCATING-OUTPUT_FORMAT(${RELOCATEABLE_OUTPUT_FORMAT})}
+${OUTPUT_ARCH+OUTPUT_ARCH(${OUTPUT_ARCH})}
+
+${LIB_SEARCH_DIRS}
+
+SECTIONS
+{
+  ${RELOCATING+/* Make the virtual address and file offset synced if the alignment is}
+  ${RELOCATING+   lower than the target page size. */}
+  ${RELOCATING+. = SIZEOF_HEADERS;}
+  ${RELOCATING+. = ALIGN(__section_alignment__);}
+  .text ${RELOCATING+ __image_base__ + ( __section_alignment__ < ${TARGET_PAGE_SIZE} ? . : __section_alignment__ )} : 
+  {
+    ${RELOCATING+ *(.init)}
+    *(.text)
+    ${R_TEXT}
+    *(.glue_7t)
+    *(.glue_7)
+    ${CONSTRUCTING+ ___CTOR_LIST__ = .; __CTOR_LIST__ = . ; 
+			LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*));  LONG (0); }
+    ${CONSTRUCTING+ ___DTOR_LIST__ = .; __DTOR_LIST__ = . ; 
+			LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*));  LONG (0); }
+    ${RELOCATING+ *(.fini)}
+    /* ??? Why is .gcc_exc here?  */
+    ${RELOCATING+ *(.gcc_exc)}
+    ${RELOCATING+PROVIDE (etext = .);}
+    *(.gcc_except_table)
+  }
+
+  /* The Cygwin32 library uses a section to avoid copying certain data
+     on fork.  This used to be named ".data$nocopy".  The linker used
+     to include this between __data_start__ and __data_end__, but that
+     breaks building the cygwin32 dll.  Instead, we name the section
+     ".data_cygwin_nocopy" and explictly include it after __data_end__. */
+
+  .data ${RELOCATING+BLOCK(__section_alignment__)} : 
+  {
+    ${RELOCATING+__data_start__ = . ;}
+    *(.data)
+    *(.data2)
+    ${R_DATA}
+    *(.jcr)
+    ${RELOCATING+__data_end__ = . ;}
+    ${RELOCATING+*(.data_cygwin_nocopy)}
+  }
+
+  .rdata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.rdata)
+    ${R_RDATA}
+    *(.eh_frame)
+    ${RELOCATING+___RUNTIME_PSEUDO_RELOC_LIST__ = .;}
+    ${RELOCATING+__RUNTIME_PSEUDO_RELOC_LIST__ = .;}
+    *(.rdata_runtime_pseudo_reloc)
+    ${RELOCATING+___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;}
+    ${RELOCATING+__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;}
+  }
+
+  .pdata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.pdata)
+  }
+
+  .bss ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    ${RELOCATING+__bss_start__ = . ;}
+    *(.bss)
+    *(COMMON)
+    ${RELOCATING+__bss_end__ = . ;}
+  }
+
+  .edata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.edata)
+  }
+
+  /DISCARD/ :
+  {
+    *(.debug\$S)
+    *(.debug\$T)
+    *(.debug\$F)
+    *(.drectve)
+  }
+
+  .idata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    /* This cannot currently be handled with grouped sections.
+	See pep.em:sort_sections.  */
+    ${R_IDATA}
+  }
+  .CRT ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    ${RELOCATING+___crt_xc_start__ = . ;}
+    ${R_CRT_XC}
+    ${RELOCATING+___crt_xc_end__ = . ;}
+    ${RELOCATING+___crt_xi_start__ = . ;}
+    ${R_CRT_XI}
+    ${RELOCATING+___crt_xi_end__ = . ;}
+    ${RELOCATING+___crt_xl_start__ = . ;}
+    ${R_CRT_XL}
+    /* ___crt_xl_end__ is defined in the TLS Directory support code */
+    ${RELOCATING+___crt_xp_start__ = . ;}
+    ${R_CRT_XP}
+    ${RELOCATING+___crt_xp_end__ = . ;}
+    ${RELOCATING+___crt_xt_start__ = . ;}
+    ${R_CRT_XT}
+    ${RELOCATING+___crt_xt_end__ = . ;}
+  }
+
+  .tls ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    ${RELOCATING+___tls_start__ = . ;}
+    ${R_TLS}
+    ${RELOCATING+___tls_end__ = . ;}
+  }
+
+  .endjunk ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    /* end is deprecated, don't use it */
+    ${RELOCATING+PROVIDE (end = .);}
+    ${RELOCATING+PROVIDE ( _end = .);}
+    ${RELOCATING+ __end__ = .;}
+  }
+
+  .rsrc ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    *(.rsrc)
+    ${R_RSRC}
+  }
+
+  .reloc ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    *(.reloc)
+  }
+
+  .stab ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.stab)
+  }
+
+  .stabstr ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.stabstr)
+  }
+
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section.  Unlike other targets that fake this by putting the
+     section VMA at 0, the PE format will not allow it.  */
+     
+  /* DWARF 1.1 and DWARF 2.  */
+  .debug_aranges ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_aranges)
+  }
+
+  .debug_pubnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_pubnames)
+  }
+
+  /* DWARF 2.  */
+  .debug_info ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_info) *(.gnu.linkonce.wi.*)
+  }
+
+  .debug_abbrev ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_abbrev)
+  }
+
+  .debug_line ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_line)
+  }
+
+  .debug_frame ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_frame)
+  }
+
+  .debug_str ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_str)
+  }
+
+  .debug_loc ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_loc)
+  }
+
+  .debug_macinfo ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_macinfo)
+  }
+
+  /* SGI/MIPS DWARF 2 extensions.  */
+  .debug_weaknames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_weaknames)
+  }
+
+  .debug_funcnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_funcnames)
+  }
+
+  .debug_typenames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_typenames)
+  }
+
+  .debug_varnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_varnames)
+  }
+
+  /* DWARF 3.  */
+  .debug_ranges ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_ranges)
+  }
+}
+EOF
diff -rNbu binutils-2.17_org/ld/testsuite/ld-bootstrap/bootstrap.exp binutils-2.17/ld/testsuite/ld-bootstrap/bootstrap.exp
--- binutils-2.17_org/ld/testsuite/ld-bootstrap/bootstrap.exp	2005-11-15 09:32:01.000000000 +0100
+++ binutils-2.17/ld/testsuite/ld-bootstrap/bootstrap.exp	2006-09-06 14:03:05.000000000 +0200
@@ -140,7 +140,7 @@
 	|| [istarget "*-*-wince"]
 	|| [istarget "*-*-cygwin*"]
 	|| [istarget "*-*-winnt*"]
-	|| [istarget "*-*-mingw32*"]
+	|| [istarget "*-*-mingw*"]
 	|| [istarget "*-*-interix*"]
 	|| [istarget "*-*-beospe*"]
 	|| [istarget "*-*-netbsdpe*"]} {
diff -rNbu binutils-2.17_org/ld/testsuite/ld-fastcall/fastcall.exp binutils-2.17/ld/testsuite/ld-fastcall/fastcall.exp
--- binutils-2.17_org/ld/testsuite/ld-fastcall/fastcall.exp	2005-05-12 09:32:06.000000000 +0200
+++ binutils-2.17/ld/testsuite/ld-fastcall/fastcall.exp	2006-09-07 14:51:36.000000000 +0200
@@ -17,13 +17,13 @@
 
 set testname "ld (fastcall symbols)"
 
-if {![istarget "i*86-*-*"]} {
+if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw64*"] } {
     return
 }
 
 if {  !([istarget "i*86-*-*pe*"] && ![istarget "i*86-*-opensd*"]) \
     && ![istarget "i*86-*-cygwin*"] \
-    && ![istarget "i*86-*-mingw32*"] } {
+    && ![istarget "i*86-*-mingw*"] } {
     return
 }
 
diff -rNbu binutils-2.17_org/ld/testsuite/ld-scripts/align.exp binutils-2.17/ld/testsuite/ld-scripts/align.exp
--- binutils-2.17_org/ld/testsuite/ld-scripts/align.exp	2005-10-25 19:40:12.000000000 +0200
+++ binutils-2.17/ld/testsuite/ld-scripts/align.exp	2006-09-06 16:36:40.000000000 +0200
@@ -30,12 +30,19 @@
 }
 
 # Doesn't work on PECOFF, appears to be a genuine bug
-if [is_pecoff_format] {
+# mingw64 targets need to set the image base to 0 to avoid auto image-basing.
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+} else {
+  if [is_pecoff_format] {
   global target_triplet
   setup_xfail $target_triplet
+  }
 }
 
-if ![ld_simple_link $ld tmpdir/align "-T $srcdir/$subdir/align.t tmpdir/align.o"] {
+if ![ld_simple_link $ld tmpdir/align "$LDFLAGS -T $srcdir/$subdir/align.t tmpdir/align.o"] {
     fail $testname
 } else {
     pass $testname
@@ -50,3 +57,4 @@
     run_dump_test align2b
 }
 run_dump_test align2c
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils-2.17_org/ld/testsuite/ld-scripts/align2a.d binutils-2.17/ld/testsuite/ld-scripts/align2a.d
--- binutils-2.17_org/ld/testsuite/ld-scripts/align2a.d	2005-02-21 09:18:49.000000000 +0100
+++ binutils-2.17/ld/testsuite/ld-scripts/align2a.d	2006-09-06 15:34:33.000000000 +0200
@@ -1,12 +1,12 @@
-# ld: --defsym data_align=16 -T align2.t
-# objdump: --section-headers
+#ld: --defsym data_align=16 -T align2.t
+#objdump: --section-headers
 
 [^:]+: +file format.*
 
 Sections:
 Idx +Name +Size +VMA +LMA +File +off +Algn
- +0 +\.text +[^ ]* +0+ +0+ .*
- +CONTENTS, +ALLOC, +LOAD,.* CODE
- +1 +\.data +[^ ]* +0+10 +0+10 .*
- +CONTENTS, +ALLOC, +LOAD, +DATA
+[	 ]+0 +\.text +[^ ]* +0+ +0+ .*
+[	 ]+CONTENTS, +ALLOC, +LOAD,.* CODE
+[	 ]+1 +\.data +[^ ]* +0+10 +0+10 .*
+[	 ]+CONTENTS, +ALLOC, +LOAD, +DATA
 #pass
diff -rNbu binutils-2.17_org/ld/testsuite/ld-scripts/defined.exp binutils-2.17/ld/testsuite/ld-scripts/defined.exp
--- binutils-2.17_org/ld/testsuite/ld-scripts/defined.exp	2005-05-12 09:32:08.000000000 +0200
+++ binutils-2.17/ld/testsuite/ld-scripts/defined.exp	2006-09-06 17:02:31.000000000 +0200
@@ -20,12 +20,19 @@
 set testname "DEFINED"
 set prms_id 5699
 
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+}
+
 if ![ld_assemble $as $srcdir/$subdir/defined.s tmpdir/def.o] {
     unresolved $testname
+    set LDFLAGS "$saved_LDFLAGS"
     return
 }
 
-if ![ld_simple_link $ld tmpdir/def "-T $srcdir/$subdir/defined.t tmpdir/def.o"] {
+if ![ld_simple_link $ld tmpdir/def "$LDFLAGS -T $srcdir/$subdir/defined.t tmpdir/def.o"] {
     fail $testname
 } else {
     if ![ld_nm $nm "" tmpdir/def] {
@@ -57,3 +64,4 @@
 set prms_id 0
 run_dump_test "defined2"
 run_dump_test "defined3"
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils-2.17_org/ld/testsuite/ld-scripts/provide.exp binutils-2.17/ld/testsuite/ld-scripts/provide.exp
--- binutils-2.17_org/ld/testsuite/ld-scripts/provide.exp	2005-06-01 06:04:19.000000000 +0200
+++ binutils-2.17/ld/testsuite/ld-scripts/provide.exp	2006-09-06 17:04:31.000000000 +0200
@@ -29,7 +29,15 @@
     return
 }
 
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+}
+
+
 run_dump_test provide-1
 run_dump_test provide-2
 setup_xfail *-*-*
 run_dump_test provide-3
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils-2.17_org/ld/testsuite/ld-scripts/script.exp binutils-2.17/ld/testsuite/ld-scripts/script.exp
--- binutils-2.17_org/ld/testsuite/ld-scripts/script.exp	2005-05-12 09:32:08.000000000 +0200
+++ binutils-2.17/ld/testsuite/ld-scripts/script.exp	2006-09-06 13:58:29.000000000 +0200
@@ -95,7 +95,7 @@
 set flags ""
 if {[istarget "*-*-pe*"] \
     || [istarget "*-*-cygwin*"] \
-    || [istarget "*-*-mingw32*"] \
+    || [istarget "*-*-mingw*"] \
     || [istarget "*-*-winnt*"] \
     || [istarget "*-*-nt"] \
     || [istarget "*-*-interix*"] } then {
diff -rNbu binutils-2.17_org/ld/testsuite/ld-scripts/weak.exp binutils-2.17/ld/testsuite/ld-scripts/weak.exp
--- binutils-2.17_org/ld/testsuite/ld-scripts/weak.exp	2005-08-18 09:51:07.000000000 +0200
+++ binutils-2.17/ld/testsuite/ld-scripts/weak.exp	2006-09-06 17:33:37.000000000 +0200
@@ -29,11 +29,11 @@
 # Weak symbols are broken for non-i386 PE targets.
 if {! [istarget i?86-*-*]} {
     setup_xfail *-*-pe*
+    setup_xfail *-*-mingw64*
 }
 
 # hppa64 and or32 are incredibly broken
 setup_xfail hppa64-*-* or32-*-*
-
 if {! [ld_assemble $as $srcdir/$subdir/weak1.s tmpdir/weak1.o]
     || ! [ld_assemble $as $srcdir/$subdir/weak2.s tmpdir/weak2.o]} then {
     # It's OK if .weak doesn't work on this target.
@@ -41,6 +41,12 @@
     return
 }
 
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+}
+
 set weak_regexp_big \
 ".*Contents of section .text:.*1000 00001008 0000200c 12121212 34343434.*Contents of section .data:.*2000 00001008 0000200c 56565656 78787878.*"
 
@@ -67,3 +73,4 @@
 	fail $testname
     }
 }
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils-2.17_org/ld/testsuite/lib/ld-lib.exp binutils-2.17/ld/testsuite/lib/ld-lib.exp
--- binutils-2.17_org/ld/testsuite/lib/ld-lib.exp	2006-04-05 03:51:15.000000000 +0200
+++ binutils-2.17/ld/testsuite/lib/ld-lib.exp	2006-09-06 14:07:48.000000000 +0200
@@ -434,7 +434,7 @@
 # True if the object format is known to be PE COFF.
 #
 proc is_pecoff_format {} {
-    if { ![istarget *-*-mingw32*] \
+    if { ![istarget *-*-mingw*] \
 	 && ![istarget *-*-cygwin*] \
 	 && ![istarget *-*-pe*] } {
 	return 0

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista binaries
  2006-09-07 13:41   ` Kai Tietz
@ 2006-09-07 15:04     ` H. J. Lu
  0 siblings, 0 replies; 17+ messages in thread
From: H. J. Lu @ 2006-09-07 15:04 UTC (permalink / raw)
  To: Kai Tietz; +Cc: binutils, Roland Schwingel

On Thu, Sep 07, 2006 at 03:40:14PM +0200, Kai Tietz wrote:
> Ok, the copyright paper is on the way to FSF.
> Additionally I added the ChangeLog entries. Also the testcases of 
> binutils, gas, and ld are extended for supporting the new target.
> Most testcases work proper, just there seems to be a problem with the weak 
> alias test. It fails for some reason I didn't got it.
> Also the align test case seems to work for this new target (for pe target 
> it was defined as xfail ...).
> 

There are no need to include patches for Makefile.in and configure.
They are generated files. Please use the correct format for ChangeLog
entries and put all ChangeLog entries in the beginning. You can take
a look at existing ChangeLog entries to see how they are written.

Other people will have more comments. BTW, have you posted it to
cygwin and mingw mailing lists?

H.J.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista  binaries
  2006-08-17 16:25 PE+ and new COFF format for x86_64 target for XP64 and Vista binaries Kai Tietz
  2006-08-17 16:45 ` H. J. Lu
@ 2006-09-08  9:48 ` Pedro Alves
  2006-09-08 10:23   ` Kai Tietz
  1 sibling, 1 reply; 17+ messages in thread
From: Pedro Alves @ 2006-09-08  9:48 UTC (permalink / raw)
  To: Kai Tietz; +Cc: binutils

Hi Kai,

I'm no binutils maintainer, but I got a few sugestions.

Kai Tietz wrote:
> Hallo,
> 
> This is a port of binutils-2.17 for COFF-format x86-64 (AMD64) and the PE+ 
> for Windows XP64 and Vista EXE/DLL. The target is named x86_64-pc-mingw64. 

To get this into binutils, you will need to forward port your changes
to the current version in CVS. The 2.17 branch should only take
important bug fixes.


> I enabled windres and dlltool for this target. For the tool objdump the 
> processing and printing methods for DLL-imports are adjusted (they are now 
> 8 bytes long :( )
> 


> I made a copy of the pe_dll(.c&.h) as pep_dll(.c&.h) to minimize 
> intersections. 

Looking and diffing at the pep_dll.{c|h} and pep.em files, I notice that 
the changes related to pe_dll.{c|h} and pe.em, excluding the pe_* to
pep_* renamings, could be minimized to just a few places.
We should avoid duplicating files this size. I haven't looked at the 
other parts of the patch, but possibly, the same could apply.

>May these files can be merged.
> 

I would say, yes please.


Hope this helps,
Cheers,
Pedro Alves


> In the "include/coff/external.h" I introduced the proper PE+ external 
> aouthdr structure without the data_start member. Because this non-existing 
> member breaks the
> size of the PEPAOUT structure in include/coff/pe.h.
> 
> For the bfd/pexxigen.c template I used the pex64 name alias for 
> generation.
> 
> I added the following new files:
>         bfd/coff-x86_64.c
>         bfd/pe-x86_64.c
>         bfd/pei-x86_64.c
>         gas/config/te-pep.h
>         include/coff/x86_54.h
>         ld/pep_dll.c
>         ld/pep_dll.h
>         ld/emulparams/i386pep.sh
>         ld/emultempl/pep.em
>         ld/scripttempl/pep.sc
> 
> 
> I tested the ld of this target by MSVC object-files and by (a patched) gcc 
> object-files (using this gas) linking against MS-Runtime-libraries.
> 
> i.A. Kai Tietz
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista  binaries
  2006-09-08  9:48 ` Pedro Alves
@ 2006-09-08 10:23   ` Kai Tietz
  2006-09-08 17:46     ` Phil Lello
  0 siblings, 1 reply; 17+ messages in thread
From: Kai Tietz @ 2006-09-08 10:23 UTC (permalink / raw)
  To: Pedro Alves; +Cc: binutils

Hi Pedro,

Thank you for your sugestions.

Yes you are right, that the major changes are the sizes for .idata$ for 
the changed thumb sizes. The reason for the duplication of the code is 
that otherwise pe and pe+ won't be linkable into one ld binary reasoned by 
global method names and variables. It is more the question about 
supporting both targets together or not.
The other solution would be to make out of pep_dll.c a stub file simply 
defining the different global names and pack the implementation within 
pe_dll.c. This solution leads to a macro desert code, but it would help.

Regards,
i.A. Kai Tietz




Pedro Alves <pedro_alves@portugalmail.pt> 
Sent by: binutils-owner@sourceware.org
08.09.2006 11:50

To
Kai Tietz <Kai.Tietz@onevision.com>
cc
binutils@sourceware.org
Subject
Re: PE+ and new COFF format for x86_64 target for XP64 and Vista  binaries






Hi Kai,

I'm no binutils maintainer, but I got a few sugestions.

Kai Tietz wrote:
> Hallo,
> 
> This is a port of binutils-2.17 for COFF-format x86-64 (AMD64) and the 
PE+ 
> for Windows XP64 and Vista EXE/DLL. The target is named 
x86_64-pc-mingw64. 

To get this into binutils, you will need to forward port your changes
to the current version in CVS. The 2.17 branch should only take
important bug fixes.


> I enabled windres and dlltool for this target. For the tool objdump the 
> processing and printing methods for DLL-imports are adjusted (they are 
now 
> 8 bytes long :( )
> 


> I made a copy of the pe_dll(.c&.h) as pep_dll(.c&.h) to minimize 
> intersections. 

Looking and diffing at the pep_dll.{c|h} and pep.em files, I notice that 
the changes related to pe_dll.{c|h} and pe.em, excluding the pe_* to
pep_* renamings, could be minimized to just a few places.
We should avoid duplicating files this size. I haven't looked at the 
other parts of the patch, but possibly, the same could apply.

>May these files can be merged.
> 

I would say, yes please.


Hope this helps,
Cheers,
Pedro Alves


> In the "include/coff/external.h" I introduced the proper PE+ external 
> aouthdr structure without the data_start member. Because this 
non-existing 
> member breaks the
> size of the PEPAOUT structure in include/coff/pe.h.
> 
> For the bfd/pexxigen.c template I used the pex64 name alias for 
> generation.
> 
> I added the following new files:
>         bfd/coff-x86_64.c
>         bfd/pe-x86_64.c
>         bfd/pei-x86_64.c
>         gas/config/te-pep.h
>         include/coff/x86_54.h
>         ld/pep_dll.c
>         ld/pep_dll.h
>         ld/emulparams/i386pep.sh
>         ld/emultempl/pep.em
>         ld/scripttempl/pep.sc
> 
> 
> I tested the ld of this target by MSVC object-files and by (a patched) 
gcc 
> object-files (using this gas) linking against MS-Runtime-libraries.
> 
> i.A. Kai Tietz
> 



^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: PE+ and new COFF format for x86_64 target for XP64 and Vista  binaries
  2006-09-08 10:23   ` Kai Tietz
@ 2006-09-08 17:46     ` Phil Lello
  2006-09-11  7:26       ` Kai Tietz
  0 siblings, 1 reply; 17+ messages in thread
From: Phil Lello @ 2006-09-08 17:46 UTC (permalink / raw)
  To: 'Kai Tietz'; +Cc: binutils

Hi Kai,

I notice that there is already some support for PE/PE+ in bfd/peXXigen.c,
which conditionally generates either peigen.c or pepigen.c by substituting
XX with either pe or pep via a sed script.

A similar approach might work here too.

Just my thoughts, I am new to the binutils source code.

Phil

> -----Original Message-----
> From: binutils-owner@sourceware.org 
> [mailto:binutils-owner@sourceware.org] On Behalf Of Kai Tietz
> Sent: 08 September 2006 11:22
> To: Pedro Alves
> Cc: binutils@sourceware.org
> Subject: Re: PE+ and new COFF format for x86_64 target for 
> XP64 and Vista binaries
> 
> Hi Pedro,
> 
> Thank you for your sugestions.
> 
> Yes you are right, that the major changes are the sizes for 
> .idata$ for the changed thumb sizes. The reason for the 
> duplication of the code is that otherwise pe and pe+ won't be 
> linkable into one ld binary reasoned by global method names 
> and variables. It is more the question about supporting both 
> targets together or not.
> The other solution would be to make out of pep_dll.c a stub 
> file simply defining the different global names and pack the 
> implementation within pe_dll.c. This solution leads to a 
> macro desert code, but it would help.
> 
> Regards,
> i.A. Kai Tietz
> 
> 
> 
> 
> Pedro Alves <pedro_alves@portugalmail.pt> Sent by: 
> binutils-owner@sourceware.org
> 08.09.2006 11:50
> 
> To
> Kai Tietz <Kai.Tietz@onevision.com>
> cc
> binutils@sourceware.org
> Subject
> Re: PE+ and new COFF format for x86_64 target for XP64 and 
> Vista  binaries
> 
> 
> 
> 
> 
> 
> Hi Kai,
> 
> I'm no binutils maintainer, but I got a few sugestions.
> 
> Kai Tietz wrote:
> > Hallo,
> > 
> > This is a port of binutils-2.17 for COFF-format x86-64 
> (AMD64) and the
> PE+ 
> > for Windows XP64 and Vista EXE/DLL. The target is named
> x86_64-pc-mingw64. 
> 
> To get this into binutils, you will need to forward port your changes
> to the current version in CVS. The 2.17 branch should only take
> important bug fixes.
> 
> 
> > I enabled windres and dlltool for this target. For the tool 
> objdump the 
> > processing and printing methods for DLL-imports are 
> adjusted (they are 
> now 
> > 8 bytes long :( )
> > 
> 
> 
> > I made a copy of the pe_dll(.c&.h) as pep_dll(.c&.h) to minimize 
> > intersections. 
> 
> Looking and diffing at the pep_dll.{c|h} and pep.em files, I 
> notice that 
> the changes related to pe_dll.{c|h} and pe.em, excluding the pe_* to
> pep_* renamings, could be minimized to just a few places.
> We should avoid duplicating files this size. I haven't looked at the 
> other parts of the patch, but possibly, the same could apply.
> 
> >May these files can be merged.
> > 
> 
> I would say, yes please.
> 
> 
> Hope this helps,
> Cheers,
> Pedro Alves
> 
> 
> > In the "include/coff/external.h" I introduced the proper 
> PE+ external 
> > aouthdr structure without the data_start member. Because this 
> non-existing 
> > member breaks the
> > size of the PEPAOUT structure in include/coff/pe.h.
> > 
> > For the bfd/pexxigen.c template I used the pex64 name alias for 
> > generation.
> > 
> > I added the following new files:
> >         bfd/coff-x86_64.c
> >         bfd/pe-x86_64.c
> >         bfd/pei-x86_64.c
> >         gas/config/te-pep.h
> >         include/coff/x86_54.h
> >         ld/pep_dll.c
> >         ld/pep_dll.h
> >         ld/emulparams/i386pep.sh
> >         ld/emultempl/pep.em
> >         ld/scripttempl/pep.sc
> > 
> > 
> > I tested the ld of this target by MSVC object-files and by 
> (a patched) 
> gcc 
> > object-files (using this gas) linking against MS-Runtime-libraries.
> > 
> > i.A. Kai Tietz
> > 
> 
> 
> 
> 
> __________ NOD32 1.1743 (20060907) Information __________
> 
> This message was checked by NOD32 antivirus system.
> http://www.eset.com
> 
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: PE+ and new COFF format for x86_64 target for XP64 and Vista  binaries
  2006-09-08 17:46     ` Phil Lello
@ 2006-09-11  7:26       ` Kai Tietz
  0 siblings, 0 replies; 17+ messages in thread
From: Kai Tietz @ 2006-09-11  7:26 UTC (permalink / raw)
  To: Phil Lello; +Cc: binutils

Hi Phil,

Thank you for your remark. Yes, I substitute for this target XX by pex64 
and the file is autogenerated by peXXigen.c to avoid code duplication. 
This change was needed, because otherwise I would break the IA code. Some 
of the used structures and the dumping methods for objdump are now 
adjusted for this target. E.g. the DLL-Import section has now thumbs of 8 
bytes (under PE they are 4 byte size). Also the base PE header has no 
data_size element anymore, therefore I introduced an proper structure 
definition for this, because the old variant leads to wrong header sizes 
(May this change can be useful for IA64, too).
The new define of COFF_WITH_pex64  is necessary for the include files 
"peicode.h", "libpei.h", "coffcode.h", and the choice of the proper target 
coff header file (not mixing with i386-COFF one).
.

Regars,
 i.A. Kai Tietz




"Phil Lello" <phil.lello@homecall.co.uk> 
08.09.2006 19:48

To
"'Kai Tietz'" <Kai.Tietz@onevision.com>
cc
<binutils@sourceware.org>
Subject
RE: PE+ and new COFF format for x86_64 target for XP64 and Vista  binaries






Hi Kai,

I notice that there is already some support for PE/PE+ in bfd/peXXigen.c,
which conditionally generates either peigen.c or pepigen.c by substituting
XX with either pe or pep via a sed script.

A similar approach might work here too.

Just my thoughts, I am new to the binutils source code.

Phil

> -----Original Message-----
> From: binutils-owner@sourceware.org 
> [mailto:binutils-owner@sourceware.org] On Behalf Of Kai Tietz
> Sent: 08 September 2006 11:22
> To: Pedro Alves
> Cc: binutils@sourceware.org
> Subject: Re: PE+ and new COFF format for x86_64 target for 
> XP64 and Vista binaries
> 
> Hi Pedro,
> 
> Thank you for your sugestions.
> 
> Yes you are right, that the major changes are the sizes for 
> .idata$ for the changed thumb sizes. The reason for the 
> duplication of the code is that otherwise pe and pe+ won't be 
> linkable into one ld binary reasoned by global method names 
> and variables. It is more the question about supporting both 
> targets together or not.
> The other solution would be to make out of pep_dll.c a stub 
> file simply defining the different global names and pack the 
> implementation within pe_dll.c. This solution leads to a 
> macro desert code, but it would help.
> 
> Regards,
> i.A. Kai Tietz
> 
> 
> 
> 
> Pedro Alves <pedro_alves@portugalmail.pt> Sent by: 
> binutils-owner@sourceware.org
> 08.09.2006 11:50
> 
> To
> Kai Tietz <Kai.Tietz@onevision.com>
> cc
> binutils@sourceware.org
> Subject
> Re: PE+ and new COFF format for x86_64 target for XP64 and 
> Vista  binaries
> 
> 
> 
> 
> 
> 
> Hi Kai,
> 
> I'm no binutils maintainer, but I got a few sugestions.
> 
> Kai Tietz wrote:
> > Hallo,
> > 
> > This is a port of binutils-2.17 for COFF-format x86-64 
> (AMD64) and the
> PE+ 
> > for Windows XP64 and Vista EXE/DLL. The target is named
> x86_64-pc-mingw64. 
> 
> To get this into binutils, you will need to forward port your changes
> to the current version in CVS. The 2.17 branch should only take
> important bug fixes.
> 
> 
> > I enabled windres and dlltool for this target. For the tool 
> objdump the 
> > processing and printing methods for DLL-imports are 
> adjusted (they are 
> now 
> > 8 bytes long :( )
> > 
> 
> 
> > I made a copy of the pe_dll(.c&.h) as pep_dll(.c&.h) to minimize 
> > intersections. 
> 
> Looking and diffing at the pep_dll.{c|h} and pep.em files, I 
> notice that 
> the changes related to pe_dll.{c|h} and pe.em, excluding the pe_* to
> pep_* renamings, could be minimized to just a few places.
> We should avoid duplicating files this size. I haven't looked at the 
> other parts of the patch, but possibly, the same could apply.
> 
> >May these files can be merged.
> > 
> 
> I would say, yes please.
> 
> 
> Hope this helps,
> Cheers,
> Pedro Alves
> 
> 
> > In the "include/coff/external.h" I introduced the proper 
> PE+ external 
> > aouthdr structure without the data_start member. Because this 
> non-existing 
> > member breaks the
> > size of the PEPAOUT structure in include/coff/pe.h.
> > 
> > For the bfd/pexxigen.c template I used the pex64 name alias for 
> > generation.
> > 
> > I added the following new files:
> >         bfd/coff-x86_64.c
> >         bfd/pe-x86_64.c
> >         bfd/pei-x86_64.c
> >         gas/config/te-pep.h
> >         include/coff/x86_54.h
> >         ld/pep_dll.c
> >         ld/pep_dll.h
> >         ld/emulparams/i386pep.sh
> >         ld/emultempl/pep.em
> >         ld/scripttempl/pep.sc
> > 
> > 
> > I tested the ld of this target by MSVC object-files and by 
> (a patched) 
> gcc 
> > object-files (using this gas) linking against MS-Runtime-libraries.
> > 
> > i.A. Kai Tietz
> > 
> 
> 
> 
> 
> __________ NOD32 1.1743 (20060907) Information __________
> 
> This message was checked by NOD32 antivirus system.
> http://www.eset.com
> 
> 



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista binaries
  2006-09-20 13:06     ` Nick Clifton
@ 2006-09-20 18:49       ` Kai Tietz
  0 siblings, 0 replies; 17+ messages in thread
From: Kai Tietz @ 2006-09-20 18:49 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils, Pedro Alves

Hi Nick,

Thank you very much for your reviewing of my patches. This was not one of 
the smaller patches. I sent to gdb, gcc, binutils, and the config 
maintainer the diff's needed for configure-in, config.sub, and 
config.guess.

Thank you again for your support,
Sincerely,
 i.A. Kai Tietz





Nick Clifton <nickc@redhat.com> 
20.09.2006 13:40

To
Kai Tietz <Kai.Tietz@onevision.com>
cc
Pedro Alves <pedro_alves@portugalmail.pt>, binutils@sourceware.org
Subject
Re: PE+ and new COFF format for x86_64 target for XP64 and Vista binaries






Hi Kai,

    Thank you very much for working on these patches and taking the 
trouble to submit them.  I have now checked them in, except for the 
changes to the top level files (configure.in, config.sub, config.guess). 
  The patch to the first of these files (configure.in) needs to be 
submitted to the gcc and gdb projects as well, since we share that file, 
and the patches to the other two (config.sub, config.guess) needs to be 
submitted to the config maintainer at <config-patches@gnu.org>.

Cheers
   Nick



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista  binaries
  2006-09-13 12:07   ` Kai Tietz
@ 2006-09-20 13:06     ` Nick Clifton
  2006-09-20 18:49       ` Kai Tietz
  0 siblings, 1 reply; 17+ messages in thread
From: Nick Clifton @ 2006-09-20 13:06 UTC (permalink / raw)
  To: Kai Tietz; +Cc: Pedro Alves, binutils

Hi Kai,

    Thank you very much for working on these patches and taking the 
trouble to submit them.  I have now checked them in, except for the 
changes to the top level files (configure.in, config.sub, config.guess). 
  The patch to the first of these files (configure.in) needs to be 
submitted to the gcc and gdb projects as well, since we share that file, 
and the patches to the other two (config.sub, config.guess) needs to be 
submitted to the config maintainer at <config-patches@gnu.org>.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista binaries
  2006-09-13 10:52 ` Pedro Alves
                     ` (2 preceding siblings ...)
  2006-09-13 12:02   ` Kai Tietz
@ 2006-09-13 12:07   ` Kai Tietz
  2006-09-20 13:06     ` Nick Clifton
  3 siblings, 1 reply; 17+ messages in thread
From: Kai Tietz @ 2006-09-13 12:07 UTC (permalink / raw)
  To: Pedro Alves; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 1739 bytes --]

Hallo Pedro,

here comes the last patch (the 5th) for ld 

Change log modifications for ld:

        * configure:            Add new target x86_64-pc-mingw64
        * configure.tgt:        Add definition of target emulation i386pep
        * makefile.am:          Add new target files for target-all
        * makefile.in:          Add new target files for target-all
        * pe_dll.c:             Adjust to be inheritable by pep_dll.c as 
include. Fix memory out of bounds excess
                                for idata relocation section data.
        * pep_dll.c:            Add target specific shared object handling
        * pep_dll.h:            Add target specific definitions for shared 
object handling
        * emulparams/i386pep.sh: Add new emulation params for target 
x86_64 coff
        * emultempl/pep.em:     Add new emulation file for target x86_64 
coff
        * po/potfiles.in:               Add pepdll.c and pepdll.h
        * scripttempl/pep.sc: Add linker script template for target x86_64 
coff
Change log modifications for ld/testsuite:

        * bootstrap/bootstrap.exp:              Enable target test
        * ld-fastcall/fastcall.exp:             Enable target test
        * ld-scripts/align.exp:         Enable target test
        * ld-scripts/align2a.d:         Enable target test
        * ld-scripts/defined.exp:               Enable target test
        * ld-scripts/provide.exp:               Enable target test
        * ld-scripts/script.exp:                Enable target test
        * ld-scripts/weak.exp:          Enable target test
        * lib/ld-lib.exp:               Detect target as pecoff file 
format
Mit freundlichen Grüßen,
 i.A. Kai Tietz


[-- Attachment #2: binutils-2.17.pex-64.060913_ld.diff --]
[-- Type: application/octet-stream, Size: 91669 bytes --]

diff -rNbu binutils_060913_org/ld/Makefile.am binutils_060913/ld/Makefile.am
--- binutils_060913_org/ld/Makefile.am	2006-09-07 19:16:31.000000000 +0200
+++ binutils_060913/ld/Makefile.am	2006-09-11 14:46:32.000000000 +0200
@@ -239,6 +239,7 @@
 	ei386nto.o \
 	ei386nw.o \
 	ei386pe.o \
+	ei386pep.o \
 	ei386pe_posix.o \
 	elnk960.o \
 	em32relf.o \
@@ -411,15 +412,16 @@
 
 ALL_EMUL_EXTRA_OFILES = \
 	deffilep.o \
-	pe-dll.o
+	pe-dll.o \
+	pep-dll.o
 
 CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \
 	ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \
-	mri.c ldcref.c pe-dll.c
+	mri.c ldcref.c pe-dll.c pep-dll.c
 
 HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
 	ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
-	ldwrite.h mri.h deffile.h pe-dll.h elf-hints-local.h
+	ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h elf-hints-local.h
 
 GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
 GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
@@ -1099,6 +1101,9 @@
 ei386pe.c: $(srcdir)/emulparams/i386pe.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe "$(tdir_i386pe)"
+ei386pep.c: $(srcdir)/emulparams/i386pep.sh \
+  $(srcdir)/emultempl/pep.em $(srcdir)/scripttempl/pep.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} i386pep "$(tdir_i386pe)"
 ei386pe_posix.c: $(srcdir)/emulparams/i386pe_posix.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe_posix "$(tdir_i386pe_posix)"
@@ -1965,6 +1970,12 @@
   ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
   ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
   $(BFDDIR)/libcoff.h deffile.h pe-dll.h
+pep-dll.o: pep-dll.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h $(INCDIR)/safe-ctype.h \
+  ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
+  ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
+  $(BFDDIR)/libcoff.h deffile.h pep-dll.h
 ldgram.o: ldgram.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
   $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
   $(INCDIR)/bfdlink.h ld.h $(INCDIR)/bin-bugs.h ldexp.h \
diff -rNbu binutils_060913_org/ld/Makefile.in binutils_060913/ld/Makefile.in
--- binutils_060913_org/ld/Makefile.in	2006-09-07 19:16:32.000000000 +0200
+++ binutils_060913/ld/Makefile.in	2006-09-11 14:50:34.000000000 +0200
@@ -463,6 +463,7 @@
 	ei386nto.o \
 	ei386nw.o \
 	ei386pe.o \
+	ei386pep.o \
 	ei386pe_posix.o \
 	elnk960.o \
 	em32relf.o \
@@ -635,15 +636,16 @@
 
 ALL_EMUL_EXTRA_OFILES = \
 	deffilep.o \
-	pe-dll.o
+	pe-dll.o \
+	pep-dll.o
 
 CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \
 	ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \
-	mri.c ldcref.c pe-dll.c
+	mri.c ldcref.c pe-dll.c pep-dll.c
 
 HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
 	ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
-	ldwrite.h mri.h deffile.h pe-dll.h elf-hints-local.h
+	ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h elf-hints-local.h
 
 GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
 GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
@@ -1910,6 +1912,9 @@
 ei386pe.c: $(srcdir)/emulparams/i386pe.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe "$(tdir_i386pe)"
+ei386pep.c: $(srcdir)/emulparams/i386pep.sh \
+  $(srcdir)/emultempl/pep.em $(srcdir)/scripttempl/pep.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} i386pep "$(tdir_i386pe)"
 ei386pe_posix.c: $(srcdir)/emulparams/i386pe_posix.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe_posix "$(tdir_i386pe_posix)"
@@ -2746,6 +2751,12 @@
   ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
   ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
   $(BFDDIR)/libcoff.h deffile.h pe-dll.h
+pep-dll.o: pep-dll.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h $(INCDIR)/safe-ctype.h \
+  ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
+  ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
+  $(BFDDIR)/libcoff.h deffile.h pep-dll.h
 ldgram.o: ldgram.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
   $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
   $(INCDIR)/bfdlink.h ld.h $(INCDIR)/bin-bugs.h ldexp.h \
diff -rNbu binutils_060913_org/ld/configure binutils_060913/ld/configure
--- binutils_060913_org/ld/configure	2006-07-10 16:30:41.000000000 +0200
+++ binutils_060913/ld/configure	2006-09-11 14:47:58.000000000 +0200
@@ -3923,7 +3923,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -3953,6 +3953,9 @@
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         ppc*-*linux*|powerpc*-*linux*)
           LD="${LD-ld} -m elf64ppc"
           ;;
diff -rNbu binutils_060913_org/ld/configure.tgt binutils_060913/ld/configure.tgt
--- binutils_060913_org/ld/configure.tgt	2006-08-22 13:50:33.000000000 +0200
+++ binutils_060913/ld/configure.tgt	2006-09-11 14:43:28.000000000 +0200
@@ -155,6 +155,8 @@
 			  targ_extra_emuls="$targ_extra_emuls elf_x86_64"
 			fi
 			tdir_i386linux=${targ_alias}aout ;;
+x86_64-*-mingw64*) targ_emul=i386pep ;
+			targ_extra_ofiles="deffilep.o pep-dll.o" ;;
 x86_64-*-linux-*)	targ_emul=elf_x86_64
 			targ_extra_emuls="elf_i386 i386linux"
 			targ_extra_libpath=elf_i386
diff -rNbu binutils_060913_org/ld/emulparams/i386pep.sh binutils_060913/ld/emulparams/i386pep.sh
--- binutils_060913_org/ld/emulparams/i386pep.sh	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/ld/emulparams/i386pep.sh	2006-07-28 12:43:22.000000000 +0200
@@ -0,0 +1,9 @@
+ARCH="i386:x86-64"
+SCRIPT_NAME=pep
+OUTPUT_FORMAT="pei-x86-64"
+RELOCATEABLE_OUTPUT_FORMAT="pe-x86-64"
+TEMPLATE_NAME=pep
+ENTRY="_mainCRTStartup"
+SUBSYSTEM=PE_DEF_SUBSYSTEM
+INITIAL_SYMBOL_CHAR=\"_\"
+TARGET_PAGE_SIZE=0x1000
diff -rNbu binutils_060913_org/ld/emultempl/pep.em binutils_060913/ld/emultempl/pep.em
--- binutils_060913_org/ld/emultempl/pep.em	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/ld/emultempl/pep.em	2006-09-06 14:26:52.000000000 +0200
@@ -0,0 +1,1749 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+test -z "${ENTRY}" && ENTRY="_mainCRTStartup"
+if [ -z "$MACHINE" ]; then
+  OUTPUT_ARCH=${ARCH}
+else
+  OUTPUT_ARCH=${ARCH}:${MACHINE}
+fi
+rm -f e${EMULATION_NAME}.c
+(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
+cat >>e${EMULATION_NAME}.c <<EOF
+/* This file is part of GLD, the Gnu Linker.
+   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+   */
+
+/* For WINDOWS_XP64 and higher */
+/* The original file generated returned different default scripts depending
+   on whether certain switches were set, but these switches pertain to the
+   Linux system and that particular version of coff.  In the NT case, we
+   only determine if the subsystem is console or windows in order to select
+   the correct entry point by default. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "getopt.h"
+#include "libiberty.h"
+#include "ld.h"
+#include "ldmain.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+#include <ldgram.h>
+#include "ldlex.h"
+#include "ldmisc.h"
+#include "ldctor.h"
+#include "coff/internal.h"
+
+/* FIXME: See bfd/peXXigen.c for why we include an architecture specific
+   header in generic PE code.  */
+#include "coff/x86_64.h"
+#include "coff/pe.h"
+
+/* FIXME: This is a BFD internal header file, and we should not be
+   using it here.  */
+#include "../bfd/libcoff.h"
+
+#undef AOUTSZ
+#define AOUTSZ		PEPAOUTSZ
+#define PEAOUTHDR	PEPAOUTHDR
+
+#include "deffile.h"
+#include "pep-dll.h"
+#include "safe-ctype.h"
+
+/* Permit the emulation parameters to override the default section
+   alignment by setting OVERRIDE_SECTION_ALIGNMENT.  FIXME: This makes
+   it seem that include/coff/internal.h should not define
+   PE_DEF_SECTION_ALIGNMENT.  */
+#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT}
+#undef PE_DEF_SECTION_ALIGNMENT
+#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT}
+#endif
+
+#ifdef TARGET_IS_i386pep
+#define DLL_SUPPORT
+#endif
+
+#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT)
+#define	PE_DEF_SUBSYSTEM		3
+#else
+#undef NT_EXE_IMAGE_BASE
+#undef PE_DEF_SECTION_ALIGNMENT
+#undef PE_DEF_FILE_ALIGNMENT
+#define NT_EXE_IMAGE_BASE		0x00010000
+#define PE_DEF_SECTION_ALIGNMENT	0x00000400
+#define	PE_DEF_SUBSYSTEM		2
+#define PE_DEF_FILE_ALIGNMENT		0x00000200
+#endif
+
+
+static struct internal_extra_pe_aouthdr pep;
+static int dll;
+static flagword real_flags = IMAGE_FILE_LARGE_ADDRESS_AWARE;
+static int support_old_code = 0;
+static char * thumb_entry_symbol = NULL;
+static lang_assignment_statement_type *image_base_statement = 0;
+
+#ifdef DLL_SUPPORT
+static int pep_enable_stdcall_fixup = -1; /* 0=disable 1=enable.  */
+static char *pep_out_def_filename = NULL;
+static char *pep_implib_filename = NULL;
+static int pep_enable_auto_image_base = 0;
+static char *pep_dll_search_prefix = NULL;
+#endif
+
+extern const char *output_filename;
+
+static void
+gld_${EMULATION_NAME}_before_parse (void)
+{
+  ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
+  output_filename = "${EXECUTABLE_NAME:-a.exe}";
+#ifdef DLL_SUPPORT
+  config.dynamic_link = TRUE;
+  config.has_shared = 1;
+  link_info.pei386_auto_import = -1;
+  link_info.pei386_runtime_pseudo_reloc = -1;
+
+#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
+#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
+  lang_default_entry ("WinMainCRTStartup");
+#else
+  lang_default_entry ("_WinMainCRTStartup");
+#endif
+#else
+  lang_default_entry ("${ENTRY}");
+#endif
+#endif
+}
+\f
+/* PE format extra command line options.  */
+
+/* Used for setting flags in the PE header.  */
+#define OPTION_BASE_FILE		(300  + 1)
+#define OPTION_DLL			(OPTION_BASE_FILE + 1)
+#define OPTION_FILE_ALIGNMENT		(OPTION_DLL + 1)
+#define OPTION_IMAGE_BASE		(OPTION_FILE_ALIGNMENT + 1)
+#define OPTION_MAJOR_IMAGE_VERSION	(OPTION_IMAGE_BASE + 1)
+#define OPTION_MAJOR_OS_VERSION		(OPTION_MAJOR_IMAGE_VERSION + 1)
+#define OPTION_MAJOR_SUBSYSTEM_VERSION	(OPTION_MAJOR_OS_VERSION + 1)
+#define OPTION_MINOR_IMAGE_VERSION	(OPTION_MAJOR_SUBSYSTEM_VERSION + 1)
+#define OPTION_MINOR_OS_VERSION		(OPTION_MINOR_IMAGE_VERSION + 1)
+#define OPTION_MINOR_SUBSYSTEM_VERSION	(OPTION_MINOR_OS_VERSION + 1)
+#define OPTION_SECTION_ALIGNMENT	(OPTION_MINOR_SUBSYSTEM_VERSION + 1)
+#define OPTION_STACK			(OPTION_SECTION_ALIGNMENT + 1)
+#define OPTION_SUBSYSTEM		(OPTION_STACK + 1)
+#define OPTION_HEAP			(OPTION_SUBSYSTEM + 1)
+#define OPTION_SUPPORT_OLD_CODE		(OPTION_HEAP + 1)
+#define OPTION_OUT_DEF			(OPTION_SUPPORT_OLD_CODE + 1)
+#define OPTION_EXPORT_ALL		(OPTION_OUT_DEF + 1)
+#define OPTION_EXCLUDE_SYMBOLS		(OPTION_EXPORT_ALL + 1)
+#define OPTION_KILL_ATS			(OPTION_EXCLUDE_SYMBOLS + 1)
+#define OPTION_STDCALL_ALIASES		(OPTION_KILL_ATS + 1)
+#define OPTION_ENABLE_STDCALL_FIXUP	(OPTION_STDCALL_ALIASES + 1)
+#define OPTION_DISABLE_STDCALL_FIXUP	(OPTION_ENABLE_STDCALL_FIXUP + 1)
+#define OPTION_IMPLIB_FILENAME		(OPTION_DISABLE_STDCALL_FIXUP + 1)
+#define OPTION_THUMB_ENTRY		(OPTION_IMPLIB_FILENAME + 1)
+#define OPTION_WARN_DUPLICATE_EXPORTS	(OPTION_THUMB_ENTRY + 1)
+#define OPTION_IMP_COMPAT		(OPTION_WARN_DUPLICATE_EXPORTS + 1)
+#define OPTION_ENABLE_AUTO_IMAGE_BASE	(OPTION_IMP_COMPAT + 1)
+#define OPTION_DISABLE_AUTO_IMAGE_BASE	(OPTION_ENABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_DLL_SEARCH_PREFIX	(OPTION_DISABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_NO_DEFAULT_EXCLUDES	(OPTION_DLL_SEARCH_PREFIX + 1)
+#define OPTION_DLL_ENABLE_AUTO_IMPORT	(OPTION_NO_DEFAULT_EXCLUDES + 1)
+#define OPTION_DLL_DISABLE_AUTO_IMPORT	(OPTION_DLL_ENABLE_AUTO_IMPORT + 1)
+#define OPTION_ENABLE_EXTRA_PE_DEBUG	(OPTION_DLL_DISABLE_AUTO_IMPORT + 1)
+#define OPTION_EXCLUDE_LIBS		(OPTION_ENABLE_EXTRA_PE_DEBUG + 1)
+#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC	\
+					(OPTION_EXCLUDE_LIBS + 1)
+#define OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC	\
+					(OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC + 1)
+
+static void
+gld${EMULATION_NAME}_add_options
+  (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl,
+    struct option **longopts, int nrl ATTRIBUTE_UNUSED,
+    struct option **really_longopts ATTRIBUTE_UNUSED)
+{
+  static const struct option xtra_long[] = {
+    /* PE options */
+    {"base-file", required_argument, NULL, OPTION_BASE_FILE},
+    {"dll", no_argument, NULL, OPTION_DLL},
+    {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
+    {"heap", required_argument, NULL, OPTION_HEAP},
+    {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
+    {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
+    {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
+    {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},
+    {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION},
+    {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION},
+    {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION},
+    {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT},
+    {"stack", required_argument, NULL, OPTION_STACK},
+    {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
+    {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
+    {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
+#ifdef DLL_SUPPORT
+    /* getopt allows abbreviations, so we do this to stop it from treating -o
+       as an abbreviation for this option */
+    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
+    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
+    {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
+    {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
+    {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
+    {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
+    {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
+    {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
+    {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
+    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
+    {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
+    /* getopt() allows abbreviations, so we do this to stop it from
+       treating -c as an abbreviation for these --compat-implib.  */
+    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
+    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
+    {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE},
+    {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE},
+    {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX},
+    {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
+    {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT},
+    {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT},
+    {"enable-extra-pep-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG},
+    {"enable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC},
+    {"disable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC},
+#endif
+    {NULL, no_argument, NULL, 0}
+  };
+
+  *longopts = (struct option *)
+    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
+  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
+
+/* PE/WIN32; added routines to get the subsystem type, heap and/or stack
+   parameters which may be input from the command line.  */
+
+typedef struct
+{
+  void *ptr;
+  int size;
+  int value;
+  char *symbol;
+  int inited;
+} definfo;
+
+#define D(field,symbol,def)  {&pep.field,sizeof(pep.field), def, symbol,0}
+
+static definfo init[] =
+{
+  /* imagebase must be first */
+#define IMAGEBASEOFF 0
+  D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE),
+#define DLLOFF 1
+  {&dll, sizeof(dll), 0, "__dll__", 0},
+#define MSIMAGEBASEOFF	2
+  D(ImageBase,"__ImageBase", NT_EXE_IMAGE_BASE),
+  D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT),
+  D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT),
+  D(MajorOperatingSystemVersion,"__major_os_version__", 4),
+  D(MinorOperatingSystemVersion,"__minor_os_version__", 0),
+  D(MajorImageVersion,"__major_image_version__", 0),
+  D(MinorImageVersion,"__minor_image_version__", 0),
+  D(MajorSubsystemVersion,"__major_subsystem_version__", 5),
+  D(MinorSubsystemVersion,"__minor_subsystem_version__", 2),
+  D(Subsystem,"__subsystem__", ${SUBSYSTEM}),
+  D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000),
+  D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
+  D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
+  D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000),
+  D(LoaderFlags,"__loader_flags__", 0x0),
+  { NULL, 0, 0, NULL, 0 }
+};
+
+
+static void
+gld_${EMULATION_NAME}_list_options (FILE *file)
+{
+  fprintf (file, _("  --base_file <basefile>             Generate a base file for relocatable DLLs\n"));
+  fprintf (file, _("  --dll                              Set image base to the default for DLLs\n"));
+  fprintf (file, _("  --file-alignment <size>            Set file alignment\n"));
+  fprintf (file, _("  --heap <size>                      Set initial size of the heap\n"));
+  fprintf (file, _("  --image-base <address>             Set start address of the executable\n"));
+  fprintf (file, _("  --major-image-version <number>     Set version number of the executable\n"));
+  fprintf (file, _("  --major-os-version <number>        Set minimum required OS version\n"));
+  fprintf (file, _("  --major-subsystem-version <number> Set minimum required OS subsystem version\n"));
+  fprintf (file, _("  --minor-image-version <number>     Set revision number of the executable\n"));
+  fprintf (file, _("  --minor-os-version <number>        Set minimum required OS revision\n"));
+  fprintf (file, _("  --minor-subsystem-version <number> Set minimum required OS subsystem revision\n"));
+  fprintf (file, _("  --section-alignment <size>         Set section alignment\n"));
+  fprintf (file, _("  --stack <size>                     Set size of the initial stack\n"));
+  fprintf (file, _("  --subsystem <name>[:<version>]     Set required OS subsystem [& version]\n"));
+  fprintf (file, _("  --support-old-code                 Support interworking with old code\n"));
+  fprintf (file, _("  --thumb-entry=<symbol>             Set the entry point to be Thumb <symbol>\n"));
+#ifdef DLL_SUPPORT
+  fprintf (file, _("  --add-stdcall-alias                Export symbols with and without @nn\n"));
+  fprintf (file, _("  --disable-stdcall-fixup            Don't link _sym to _sym@nn\n"));
+  fprintf (file, _("  --enable-stdcall-fixup             Link _sym to _sym@nn without warnings\n"));
+  fprintf (file, _("  --exclude-symbols sym,sym,...      Exclude symbols from automatic export\n"));
+  fprintf (file, _("  --exclude-libs lib,lib,...         Exclude libraries from automatic export\n"));
+  fprintf (file, _("  --export-all-symbols               Automatically export all globals to DLL\n"));
+  fprintf (file, _("  --kill-at                          Remove @nn from exported symbols\n"));
+  fprintf (file, _("  --out-implib <file>                Generate import library\n"));
+  fprintf (file, _("  --output-def <file>                Generate a .DEF file for the built DLL\n"));
+  fprintf (file, _("  --warn-duplicate-exports           Warn about duplicate exports.\n"));
+  fprintf (file, _("  --compat-implib                    Create backward compatible import libs;\n\
+                                       create __imp_<SYMBOL> as well.\n"));
+  fprintf (file, _("  --enable-auto-image-base           Automatically choose image base for DLLs\n\
+                                       unless user specifies one\n"));
+  fprintf (file, _("  --disable-auto-image-base          Do not auto-choose image base. (default)\n"));
+  fprintf (file, _("  --dll-search-prefix=<string>       When linking dynamically to a dll without\n\
+                                       an importlib, use <string><basename>.dll\n\
+                                       in preference to lib<basename>.dll \n"));
+  fprintf (file, _("  --enable-auto-import               Do sophistcated linking of _sym to\n\
+                                       __imp_sym for DATA references\n"));
+  fprintf (file, _("  --disable-auto-import              Do not auto-import DATA items from DLLs\n"));
+  fprintf (file, _("  --enable-runtime-pseudo-reloc      Work around auto-import limitations by\n\
+                                       adding pseudo-relocations resolved at\n\
+                                       runtime.\n"));
+  fprintf (file, _("  --disable-runtime-pseudo-reloc     Do not add runtime pseudo-relocations for\n\
+                                       auto-imported DATA.\n"));
+  fprintf (file, _("  --enable-extra-pep-debug            Enable verbose debug output when building\n\
+                                       or linking to DLLs (esp. auto-import)\n"));
+#endif
+}
+
+
+static void
+set_pep_name (char *name, long val)
+{
+  int i;
+
+  /* Find the name and set it.  */
+  for (i = 0; init[i].ptr; i++)
+    {
+      if (strcmp (name, init[i].symbol) == 0)
+	{
+	  init[i].value = val;
+	  init[i].inited = 1;
+	  if(!strcmp(name,"__image_base__")) set_pep_name("__ImageBase",val);
+	  return;
+	}
+    }
+  abort ();
+}
+
+
+static void
+set_pep_subsystem (void)
+{
+  const char *sver;
+  const char *entry;
+  const char *initial_symbol_char;
+  char *end;
+  int len;
+  int i;
+  int subsystem;
+  unsigned long temp_subsystem;
+  static const struct
+    {
+      const char *name;
+      const int value;
+      const char *entry;
+    }
+  v[] =
+    {
+      { "native",  1, "NtProcessStartup" },
+      { "windows", 2, "WinMainCRTStartup" },
+      { "console", 3, "mainCRTStartup" },
+      { "posix",   7, "__PosixProcessStartup"},
+      { "wince",   9, "_WinMainCRTStartup" },
+      { "xbox",   14, "mainCRTStartup" },
+      { NULL, 0, NULL }
+    };
+  /* Entry point name for arbitrary subsystem numbers.  */
+  static const char default_entry[] = "mainCRTStartup";
+
+  /* Check for the presence of a version number.  */
+  sver = strchr (optarg, ':');
+  if (sver == NULL)
+    len = strlen (optarg);
+  else
+    {
+      len = sver - optarg;
+      set_pep_name ("__major_subsystem_version__",
+		   strtoul (sver + 1, &end, 0));
+      if (*end == '.')
+	set_pep_name ("__minor_subsystem_version__",
+		     strtoul (end + 1, &end, 0));
+      if (*end != '\0')
+	einfo (_("%P: warning: bad version number in -subsystem option\n"));
+    }
+
+  /* Check for numeric subsystem.  */
+  temp_subsystem = strtoul (optarg, & end, 0);
+  if ((*end == ':' || *end == '\0') && (temp_subsystem < 65536))
+    {
+      /* Search list for a numeric match to use its entry point.  */
+      for (i = 0; v[i].name; i++)
+	if (v[i].value == (int) temp_subsystem)
+	  break;
+
+      /* If no match, use the default.  */
+      if (v[i].name != NULL)
+	entry = v[i].entry;
+      else
+	entry = default_entry;
+
+      /* Use this subsystem.  */
+      subsystem = (int) temp_subsystem;
+    }
+  else
+    {
+      /* Search for subsystem by name.  */
+      for (i = 0; v[i].name; i++)
+	if (strncmp (optarg, v[i].name, len) == 0
+	    && v[i].name[len] == '\0')
+	  break;
+
+      if (v[i].name == NULL)
+	{
+	  einfo (_("%P%F: invalid subsystem type %s\n"), optarg);
+	  return;
+	}
+
+      entry = v[i].entry;
+      subsystem = v[i].value;
+    }
+
+  set_pep_name ("__subsystem__", subsystem);
+
+  initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
+  if (*initial_symbol_char != '\0')
+    {
+      char *alc_entry;
+
+      /* lang_default_entry expects its argument to be permanently
+	 allocated, so we don't free this string.  */
+      alc_entry = xmalloc (strlen (initial_symbol_char)
+			   + strlen (entry)
+			   + 1);
+      strcpy (alc_entry, initial_symbol_char);
+      strcat (alc_entry, entry);
+      entry = alc_entry;
+    }
+
+  lang_default_entry (entry);
+
+  return;
+}
+
+
+static void
+set_pep_value (char *name)
+{
+  char *end;
+
+  set_pep_name (name,  strtoul (optarg, &end, 0));
+
+  if (end == optarg)
+    einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg);
+
+  optarg = end;
+}
+
+
+static void
+set_pep_stack_heap (char *resname, char *comname)
+{
+  set_pep_value (resname);
+
+  if (*optarg == ',')
+    {
+      optarg++;
+      set_pep_value (comname);
+    }
+  else if (*optarg)
+    einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg);
+}
+
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+  switch (optc)
+    {
+    default:
+      return FALSE;
+
+    case OPTION_BASE_FILE:
+      link_info.base_file = fopen (optarg, FOPEN_WB);
+      if (link_info.base_file == NULL)
+	{
+	  /* xgettext:c-format */
+	  fprintf (stderr, _("%s: Can't open base file %s\n"),
+		   program_name, optarg);
+	  xexit (1);
+	}
+      break;
+
+      /* PE options.  */
+    case OPTION_HEAP:
+      set_pep_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__");
+      break;
+    case OPTION_STACK:
+      set_pep_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__");
+      break;
+    case OPTION_SUBSYSTEM:
+      set_pep_subsystem ();
+      break;
+    case OPTION_MAJOR_OS_VERSION:
+      set_pep_value ("__major_os_version__");
+      break;
+    case OPTION_MINOR_OS_VERSION:
+      set_pep_value ("__minor_os_version__");
+      break;
+    case OPTION_MAJOR_SUBSYSTEM_VERSION:
+      set_pep_value ("__major_subsystem_version__");
+      break;
+    case OPTION_MINOR_SUBSYSTEM_VERSION:
+      set_pep_value ("__minor_subsystem_version__");
+      break;
+    case OPTION_MAJOR_IMAGE_VERSION:
+      set_pep_value ("__major_image_version__");
+      break;
+    case OPTION_MINOR_IMAGE_VERSION:
+      set_pep_value ("__minor_image_version__");
+      break;
+    case OPTION_FILE_ALIGNMENT:
+      set_pep_value ("__file_alignment__");
+      break;
+    case OPTION_SECTION_ALIGNMENT:
+      set_pep_value ("__section_alignment__");
+      break;
+    case OPTION_DLL:
+      set_pep_name ("__dll__", 1);
+      break;
+    case OPTION_IMAGE_BASE:
+      set_pep_value ("__image_base__");
+      break;
+    case OPTION_SUPPORT_OLD_CODE:
+      support_old_code = 1;
+      break;
+    case OPTION_THUMB_ENTRY:
+      thumb_entry_symbol = optarg;
+      break;
+#ifdef DLL_SUPPORT
+    case OPTION_OUT_DEF:
+      pep_out_def_filename = xstrdup (optarg);
+      break;
+    case OPTION_EXPORT_ALL:
+      pep_dll_export_everything = 1;
+      break;
+    case OPTION_EXCLUDE_SYMBOLS:
+      pep_dll_add_excludes (optarg, 0);
+      break;
+    case OPTION_EXCLUDE_LIBS:
+      pep_dll_add_excludes (optarg, 1);
+      break;
+    case OPTION_KILL_ATS:
+      pep_dll_kill_ats = 1;
+      break;
+    case OPTION_STDCALL_ALIASES:
+      pep_dll_stdcall_aliases = 1;
+      break;
+    case OPTION_ENABLE_STDCALL_FIXUP:
+      pep_enable_stdcall_fixup = 1;
+      break;
+    case OPTION_DISABLE_STDCALL_FIXUP:
+      pep_enable_stdcall_fixup = 0;
+      break;
+    case OPTION_IMPLIB_FILENAME:
+      pep_implib_filename = xstrdup (optarg);
+      break;
+    case OPTION_WARN_DUPLICATE_EXPORTS:
+      pep_dll_warn_dup_exports = 1;
+      break;
+    case OPTION_IMP_COMPAT:
+      pep_dll_compat_implib = 1;
+      break;
+    case OPTION_ENABLE_AUTO_IMAGE_BASE:
+      pep_enable_auto_image_base = 1;
+      break;
+    case OPTION_DISABLE_AUTO_IMAGE_BASE:
+      pep_enable_auto_image_base = 0;
+      break;
+    case OPTION_DLL_SEARCH_PREFIX:
+      pep_dll_search_prefix = xstrdup (optarg);
+      break;
+    case OPTION_NO_DEFAULT_EXCLUDES:
+      pep_dll_do_default_excludes = 0;
+      break;
+    case OPTION_DLL_ENABLE_AUTO_IMPORT:
+      link_info.pei386_auto_import = 1;
+      break;
+    case OPTION_DLL_DISABLE_AUTO_IMPORT:
+      link_info.pei386_auto_import = 0;
+      break;
+    case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC:
+      link_info.pei386_runtime_pseudo_reloc = 1;
+      break;
+    case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC:
+      link_info.pei386_runtime_pseudo_reloc = 0;
+      break;
+    case OPTION_ENABLE_EXTRA_PE_DEBUG:
+      pep_dll_extra_pe_debug = 1;
+      break;
+#endif
+    }
+  return TRUE;
+}
+\f
+
+#ifdef DLL_SUPPORT
+static unsigned long
+strhash (const char *str)
+{
+  const unsigned char *s;
+  unsigned long hash;
+  unsigned int c;
+  unsigned int len;
+
+  hash = 0;
+  len = 0;
+  s = (const unsigned char *) str;
+  while ((c = *s++) != '\0')
+    {
+      hash += c + (c << 17);
+      hash ^= hash >> 2;
+      ++len;
+    }
+  hash += len + (len << 17);
+  hash ^= hash >> 2;
+
+  return hash;
+}
+
+/* Use the output file to create a image base for relocatable DLLs.  */
+
+static unsigned long
+compute_dll_image_base (const char *ofile)
+{
+  unsigned long hash = strhash (ofile);
+  return 0x61300000 + ((hash << 16) & 0x0FFC0000);
+}
+#endif
+
+/* Assign values to the special symbols before the linker script is
+   read.  */
+
+static void
+gld_${EMULATION_NAME}_set_symbols (void)
+{
+  /* Run through and invent symbols for all the
+     names and insert the defaults.  */
+  int j;
+  lang_statement_list_type *save;
+
+  if (!init[IMAGEBASEOFF].inited)
+    {
+      if (link_info.relocatable)
+	init[IMAGEBASEOFF].value = 0;
+      else if (init[DLLOFF].value || (link_info.shared && !link_info.pie))
+#ifdef DLL_SUPPORT
+	init[IMAGEBASEOFF].value = (pep_enable_auto_image_base) ?
+	  compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE;
+#else
+	init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE;
+#endif
+      else
+	init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE;
+	init[MSIMAGEBASEOFF].value=init[IMAGEBASEOFF].value;
+    }
+
+  /* Don't do any symbol assignments if this is a relocatable link.  */
+  if (link_info.relocatable)
+    return;
+
+  /* Glue the assignments into the abs section.  */
+  save = stat_ptr;
+
+  stat_ptr = &(abs_output_section->children);
+
+  for (j = 0; init[j].ptr; j++)
+    {
+      long val = init[j].value;
+      lang_assignment_statement_type *rv;
+      rv = lang_add_assignment (exp_assop ('=', init[j].symbol,
+					   exp_intop (val)));
+      if (init[j].size == sizeof (short))
+	*(short *) init[j].ptr = val;
+      else if (init[j].size == sizeof (int))
+	*(int *) init[j].ptr = val;
+      else if (init[j].size == sizeof (long))
+	*(long *) init[j].ptr = val;
+      /* This might be a long long or other special type.  */
+      else if (init[j].size == sizeof (bfd_vma))
+	*(bfd_vma *) init[j].ptr = val;
+      else	abort ();
+      if (j == IMAGEBASEOFF)
+	image_base_statement = rv;
+    }
+	/* Restore the pointer.  */
+  stat_ptr = save;
+
+  if (pep.FileAlignment >
+      pep.SectionAlignment)
+    {
+      einfo (_("%P: warning, file alignment > section alignment.\n"));
+    }
+}
+
+/* This is called after the linker script and the command line options
+   have been read.  */
+
+static void
+gld_${EMULATION_NAME}_after_parse (void)
+{
+  /* The Windows libraries are designed for the linker to treat the
+     entry point as an undefined symbol.  Otherwise, the .obj that
+     defines mainCRTStartup is brought in because it is the first
+     encountered in libc.lib and it has other symbols in it which will
+     be pulled in by the link process.  To avoid this, we act as
+     though the user specified -u with the entry point symbol.
+
+     This function is called after the linker script and command line
+     options have been read, so at this point we know the right entry
+     point.  This function is called before the input files are
+     opened, so registering the symbol as undefined will make a
+     difference.  */
+
+  if (! link_info.relocatable && entry_symbol.name != NULL)
+    ldlang_add_undef (entry_symbol.name);
+}
+
+/* pep-dll.c directly accesses pep_data_import_dll,
+   so it must be defined outside of #ifdef DLL_SUPPORT.
+   Note - this variable is deliberately not initialised.
+   This allows it to be treated as a common varaible, and only
+   exist in one incarnation in a multiple target enabled linker.  */
+char * pep_data_import_dll;
+
+#ifdef DLL_SUPPORT
+static struct bfd_link_hash_entry *pep_undef_found_sym;
+
+static bfd_boolean
+pep_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
+{
+  int sl;
+  char *string = inf;
+
+  sl = strlen (string);
+  if (h->type == bfd_link_hash_defined
+      && strncmp (h->root.string, string, sl) == 0
+      && h->root.string[sl] == '@')
+    {
+      pep_undef_found_sym = h;
+      return FALSE;
+    }
+  return TRUE;
+}
+
+static void
+pep_fixup_stdcalls (void)
+{
+  static int gave_warning_message = 0;
+  struct bfd_link_hash_entry *undef, *sym;
+
+  if (pep_dll_extra_pe_debug)
+    printf ("%s\n", __FUNCTION__);
+
+  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
+    if (undef->type == bfd_link_hash_undefined)
+      {
+	char* at = strchr (undef->root.string, '@');
+	int lead_at = (*undef->root.string == '@');
+	/* For now, don't try to fixup fastcall symbols.  */
+
+	if (at && !lead_at)
+	  {
+	    /* The symbol is a stdcall symbol, so let's look for a
+	       cdecl symbol with the same name and resolve to that.  */
+	    char *cname = xstrdup (undef->root.string /* + lead_at */);
+	    at = strchr (cname, '@');
+	    *at = 0;
+	    sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1);
+
+	    if (sym && sym->type == bfd_link_hash_defined)
+	      {
+		undef->type = bfd_link_hash_defined;
+		undef->u.def.value = sym->u.def.value;
+		undef->u.def.section = sym->u.def.section;
+
+		if (pep_enable_stdcall_fixup == -1)
+		  {
+		    einfo (_("Warning: resolving %s by linking to %s\n"),
+			   undef->root.string, cname);
+		    if (! gave_warning_message)
+		      {
+			gave_warning_message = 1;
+			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
+			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
+		      }
+		  }
+	      }
+	  }
+	else
+	  {
+	    /* The symbol is a cdecl symbol, so we look for stdcall
+	       symbols - which means scanning the whole symbol table.  */
+	    pep_undef_found_sym = 0;
+	    bfd_link_hash_traverse (link_info.hash, pep_undef_cdecl_match,
+				    (char *) undef->root.string);
+	    sym = pep_undef_found_sym;
+	    if (sym)
+	      {
+		undef->type = bfd_link_hash_defined;
+		undef->u.def.value = sym->u.def.value;
+		undef->u.def.section = sym->u.def.section;
+
+		if (pep_enable_stdcall_fixup == -1)
+		  {
+		    einfo (_("Warning: resolving %s by linking to %s\n"),
+			   undef->root.string, sym->root.string);
+		    if (! gave_warning_message)
+		      {
+			gave_warning_message = 1;
+			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
+			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
+		      }
+		  }
+	      }
+	  }
+      }
+}
+
+static int
+make_import_fixup (arelent *rel, asection *s)
+{
+  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
+  char addend[4];
+
+  if (pep_dll_extra_pe_debug)
+    printf ("arelent: %s@%#lx: add=%li\n", sym->name,
+	    (long) rel->address, (long) rel->addend);
+
+  if (! bfd_get_section_contents (s->owner, s, addend, rel->address, sizeof (addend)))
+    einfo (_("%C: Cannot get section contents - auto-import exception\n"),
+	   s->owner, s, rel->address);
+
+  pep_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend));
+
+  return 1;
+}
+
+static void
+pep_find_data_imports (void)
+{
+  struct bfd_link_hash_entry *undef, *sym;
+
+  if (link_info.pei386_auto_import == 0)
+    return;
+
+  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
+    {
+      if (undef->type == bfd_link_hash_undefined)
+	{
+	  /* C++ symbols are *long*.  */
+	  char buf[4096];
+
+	  if (pep_dll_extra_pe_debug)
+	    printf ("%s:%s\n", __FUNCTION__, undef->root.string);
+
+	  sprintf (buf, "__imp_%s", undef->root.string);
+
+	  sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
+
+	  if (sym && sym->type == bfd_link_hash_defined)
+	    {
+	      bfd *b = sym->u.def.section->owner;
+	      asymbol **symbols;
+	      int nsyms, symsize, i;
+
+	      if (link_info.pei386_auto_import == -1)
+		info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
+			  undef->root.string, buf);
+
+	      symsize = bfd_get_symtab_upper_bound (b);
+	      symbols = (asymbol **) xmalloc (symsize);
+	      nsyms = bfd_canonicalize_symtab (b, symbols);
+
+	      for (i = 0; i < nsyms; i++)
+		{
+		  if (memcmp (symbols[i]->name, "__head_",
+			      sizeof ("__head_") - 1))
+		    continue;
+
+		  if (pep_dll_extra_pe_debug)
+		    printf ("->%s\n", symbols[i]->name);
+
+		  pep_data_import_dll = (char*) (symbols[i]->name +
+						sizeof ("__head_") - 1);
+		  break;
+		}
+
+	      pep_walk_relocs_of_symbol (&link_info, undef->root.string,
+					make_import_fixup);
+
+	      /* Let's differentiate it somehow from defined.  */
+	      undef->type = bfd_link_hash_defweak;
+	      /* We replace original name with __imp_ prefixed, this
+		 1) may trash memory 2) leads to duplicate symbol generation.
+		 Still, IMHO it's better than having name poluted.  */
+	      undef->root.string = sym->root.string;
+	      undef->u.def.value = sym->u.def.value;
+	      undef->u.def.section = sym->u.def.section;
+	    }
+	}
+    }
+}
+
+static bfd_boolean
+pr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
+{
+  if (pep_dll_extra_pe_debug)
+    printf ("+%s\n", h->string);
+
+  return TRUE;
+}
+#endif /* DLL_SUPPORT */
+
+
+static void
+gld_${EMULATION_NAME}_after_open (void)
+{
+#ifdef DLL_SUPPORT
+  if (pep_dll_extra_pe_debug)
+    {
+      bfd *a;
+      struct bfd_link_hash_entry *sym;
+
+      printf ("%s()\n", __FUNCTION__);
+
+      for (sym = link_info.hash->undefs; sym; sym=sym->u.undef.next)
+	printf ("-%s\n", sym->root.string);
+      bfd_hash_traverse (&link_info.hash->table, pr_sym, NULL);
+
+      for (a = link_info.input_bfds; a; a = a->link_next)
+	printf ("*%s\n",a->filename);
+    }
+#endif
+
+  /* Pass the wacky PE command line options into the output bfd.
+     FIXME: This should be done via a function, rather than by
+     including an internal BFD header.  */
+
+  if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0)
+    einfo (_("%F%P: PE operations on non PE file.\n"));
+
+  pe_data (output_bfd)->pe_opthdr = pep;
+  pe_data (output_bfd)->dll = init[DLLOFF].value;
+  pe_data (output_bfd)->real_flags |= real_flags;
+
+#ifdef DLL_SUPPORT
+  if (pep_enable_stdcall_fixup) /* -1=warn or 1=disable */
+    pep_fixup_stdcalls ();
+
+  pep_process_import_defs (output_bfd, & link_info);
+
+  pep_find_data_imports ();
+
+#ifndef TARGET_IS_i386pep
+  if (link_info.shared)
+#else
+  if (!link_info.relocatable)
+#endif
+    pep_dll_build_sections (output_bfd, &link_info);
+
+#ifndef TARGET_IS_i386pep
+  else
+    pep_exe_build_sections (output_bfd, &link_info);
+#endif
+#endif
+
+  {
+    /* This next chunk of code tries to detect the case where you have
+       two import libraries for the same DLL (specifically,
+       symbolically linking libm.a and libc.a in cygwin to
+       libcygwin.a).  In those cases, it's possible for function
+       thunks from the second implib to be used but without the
+       head/tail objects, causing an improper import table.  We detect
+       those cases and rename the "other" import libraries to match
+       the one the head/tail come from, so that the linker will sort
+       things nicely and produce a valid import table.  */
+
+    LANG_FOR_EACH_INPUT_STATEMENT (is)
+      {
+	if (is->the_bfd->my_archive)
+	  {
+	    int idata2 = 0, reloc_count=0, is_imp = 0;
+	    asection *sec;
+
+	    /* See if this is an import library thunk.  */
+	    for (sec = is->the_bfd->sections; sec; sec = sec->next)
+	      {
+		if (strcmp (sec->name, ".idata\$2") == 0)
+		  idata2 = 1;
+		if (strncmp (sec->name, ".idata\$", 7) == 0)
+		  is_imp = 1;
+		reloc_count += sec->reloc_count;
+	      }
+
+	    if (is_imp && !idata2 && reloc_count)
+	      {
+		/* It is, look for the reference to head and see if it's
+		   from our own library.  */
+		for (sec = is->the_bfd->sections; sec; sec = sec->next)
+		  {
+		    int i;
+		    long symsize;
+		    long relsize;
+		    asymbol **symbols;
+		    arelent **relocs;
+		    int nrelocs;
+
+		    symsize = bfd_get_symtab_upper_bound (is->the_bfd);
+		    if (symsize < 1)
+		      break;
+		    relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
+		    if (relsize < 1)
+		      break;
+
+		    symbols = (asymbol **) xmalloc (symsize);
+		    symsize = bfd_canonicalize_symtab (is->the_bfd, symbols);
+		    if (symsize < 0)
+		      {
+			einfo ("%X%P: unable to process symbols: %E");
+			return;
+		      }
+
+		    relocs = (arelent **) xmalloc ((size_t) relsize);
+		    nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec,
+						      relocs, symbols);
+		    if (nrelocs < 0)
+		      {
+			free (relocs);
+			einfo ("%X%P: unable to process relocs: %E");
+			return;
+		      }
+
+		    for (i = 0; i < nrelocs; i++)
+		      {
+			struct bfd_symbol *s;
+			struct bfd_link_hash_entry * blhe;
+			char *other_bfd_filename;
+			char *n;
+
+			s = (relocs[i]->sym_ptr_ptr)[0];
+
+			if (s->flags & BSF_LOCAL)
+			  continue;
+
+			/* Thunk section with reloc to another bfd.  */
+			blhe = bfd_link_hash_lookup (link_info.hash,
+						     s->name,
+						     FALSE, FALSE, TRUE);
+
+			if (blhe == NULL
+			    || blhe->type != bfd_link_hash_defined)
+			  continue;
+
+			other_bfd_filename
+			  = blhe->u.def.section->owner->my_archive
+			    ? bfd_get_filename (blhe->u.def.section->owner->my_archive)
+			    : bfd_get_filename (blhe->u.def.section->owner);
+
+			if (strcmp (bfd_get_filename (is->the_bfd->my_archive),
+				    other_bfd_filename) == 0)
+			  continue;
+
+			/* Rename this implib to match the other one.  */
+			n = xmalloc (strlen (other_bfd_filename) + 1);
+			strcpy (n, other_bfd_filename);
+			is->the_bfd->my_archive->filename = n;
+		      }
+
+		    free (relocs);
+		    /* Note - we do not free the symbols,
+		       they are now cached in the BFD.  */
+		  }
+	      }
+	  }
+      }
+  }
+
+  {
+    int is_ms_arch = 0;
+    bfd *cur_arch = 0;
+    lang_input_statement_type *is2;
+    lang_input_statement_type *is3;
+
+    /* Careful - this is a shell script.  Watch those dollar signs! */
+    /* Microsoft import libraries have every member named the same,
+       and not in the right order for us to link them correctly.  We
+       must detect these and rename the members so that they'll link
+       correctly.  There are three types of objects: the head, the
+       thunks, and the sentinel(s).  The head is easy; it's the one
+       with idata2.  We assume that the sentinels won't have relocs,
+       and the thunks will.  It's easier than checking the symbol
+       table for external references.  */
+    LANG_FOR_EACH_INPUT_STATEMENT (is)
+      {
+	if (is->the_bfd->my_archive)
+	  {
+	    char *pnt;
+	    bfd *arch = is->the_bfd->my_archive;
+
+	    if (cur_arch != arch)
+	      {
+		cur_arch = arch;
+		is_ms_arch = 1;
+
+		for (is3 = is;
+		     is3 && is3->the_bfd->my_archive == arch;
+		     is3 = (lang_input_statement_type *) is3->next)
+		  {
+		    /* A MS dynamic import library can also contain static
+		       members, so look for the first element with a .dll
+		       extension, and use that for the remainder of the
+		       comparisons.  */
+		    pnt = strrchr (is3->the_bfd->filename, '.');
+		    if (pnt != NULL && strcmp (pnt, ".dll") == 0)
+		      break;
+		  }
+
+		if (is3 == NULL)
+		  is_ms_arch = 0;
+		else
+		  {
+		    /* OK, found one.  Now look to see if the remaining
+		       (dynamic import) members use the same name.  */
+		    for (is2 = is;
+			 is2 && is2->the_bfd->my_archive == arch;
+			 is2 = (lang_input_statement_type *) is2->next)
+		      {
+			/* Skip static members, ie anything with a .obj
+			   extension.  */
+			pnt = strrchr (is2->the_bfd->filename, '.');
+			if (pnt != NULL && strcmp (pnt, ".obj") == 0)
+			  continue;
+
+			if (strcmp (is3->the_bfd->filename,
+				    is2->the_bfd->filename))
+			  {
+			    is_ms_arch = 0;
+			    break;
+			  }
+		      }
+		  }
+	      }
+
+	    /* This fragment might have come from an .obj file in a Microsoft
+	       import, and not an actual import record. If this is the case,
+	       then leave the filename alone.  */
+	    pnt = strrchr (is->the_bfd->filename, '.');
+
+	    if (is_ms_arch && (strcmp (pnt, ".dll") == 0))
+	      {
+		int idata2 = 0, reloc_count=0;
+		asection *sec;
+		char *new_name, seq;
+
+		for (sec = is->the_bfd->sections; sec; sec = sec->next)
+		  {
+		    if (strcmp (sec->name, ".idata\$2") == 0)
+		      idata2 = 1;
+		    reloc_count += sec->reloc_count;
+		  }
+
+		if (idata2) /* .idata2 is the TOC */
+		  seq = 'a';
+		else if (reloc_count > 0) /* thunks */
+		  seq = 'b';
+		else /* sentinel */
+		  seq = 'c';
+
+		new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
+		sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
+		is->the_bfd->filename = new_name;
+
+		new_name = xmalloc (strlen (is->filename) + 3);
+		sprintf (new_name, "%s.%c", is->filename, seq);
+		is->filename = new_name;
+	      }
+	  }
+      }
+  }
+}
+
+static void
+gld_${EMULATION_NAME}_before_allocation (void)
+{
+  before_allocation_default ();
+}
+
+#ifdef DLL_SUPPORT
+/* This is called when an input file isn't recognized as a BFD.  We
+   check here for .DEF files and pull them in automatically.  */
+
+static int
+saw_option (char *option)
+{
+  int i;
+
+  for (i = 0; init[i].ptr; i++)
+    if (strcmp (init[i].symbol, option) == 0)
+      return init[i].inited;
+  return 0;
+}
+#endif /* DLL_SUPPORT */
+
+static bfd_boolean
+gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
+{
+#ifdef DLL_SUPPORT
+  const char *ext = entry->filename + strlen (entry->filename) - 4;
+
+  if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0)
+    {
+      pep_def_file = def_file_parse (entry->filename, pep_def_file);
+
+      if (pep_def_file)
+	{
+	  int i, buflen=0, len;
+	  char *buf;
+
+	  for (i = 0; i < pep_def_file->num_exports; i++)
+	    {
+	      len = strlen (pep_def_file->exports[i].internal_name);
+	      if (buflen < len + 2)
+		buflen = len + 2;
+	    }
+
+	  buf = (char *) xmalloc (buflen);
+
+	  for (i = 0; i < pep_def_file->num_exports; i++)
+	    {
+	      struct bfd_link_hash_entry *h;
+
+	      sprintf (buf, "_%s", pep_def_file->exports[i].internal_name);
+
+	      h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE);
+	      if (h == (struct bfd_link_hash_entry *) NULL)
+		einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
+	      if (h->type == bfd_link_hash_new)
+		{
+		  h->type = bfd_link_hash_undefined;
+		  h->u.undef.abfd = NULL;
+		  bfd_link_add_undef (link_info.hash, h);
+		}
+	    }
+	  free (buf);
+
+	  /* def_file_print (stdout, pep_def_file); */
+	  if (pep_def_file->is_dll == 1)
+	    link_info.shared = 1;
+
+	  if (pep_def_file->base_address != (bfd_vma)(-1))
+	    {
+	      pep.ImageBase =
+		pe_data (output_bfd)->pe_opthdr.ImageBase =
+		init[IMAGEBASEOFF].value = pep_def_file->base_address;
+	      init[IMAGEBASEOFF].inited = 1;
+	      if (image_base_statement)
+		image_base_statement->exp =
+		  exp_assop ('=', "__image_base__", exp_intop (pep.ImageBase));
+	    }
+
+	  if (pep_def_file->stack_reserve != -1
+	      && ! saw_option ("__size_of_stack_reserve__"))
+	    {
+	      pep.SizeOfStackReserve = pep_def_file->stack_reserve;
+	      if (pep_def_file->stack_commit != -1)
+		pep.SizeOfStackCommit = pep_def_file->stack_commit;
+	    }
+	  if (pep_def_file->heap_reserve != -1
+	      && ! saw_option ("__size_of_heap_reserve__"))
+	    {
+	      pep.SizeOfHeapReserve = pep_def_file->heap_reserve;
+	      if (pep_def_file->heap_commit != -1)
+		pep.SizeOfHeapCommit = pep_def_file->heap_commit;
+	    }
+	  return TRUE;
+	}
+    }
+#endif
+  return FALSE;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
+{
+#ifdef DLL_SUPPORT
+#ifdef TARGET_IS_i386pep
+  pep_dll_id_target ("pei-x86-64");
+#endif
+  if (bfd_get_format (entry->the_bfd) == bfd_object)
+    {
+      char fbuf[LD_PATHMAX + 1];
+      const char *ext;
+
+      if (REALPATH (entry->filename, fbuf) == NULL)
+	strncpy (fbuf, entry->filename, sizeof (fbuf));
+
+      ext = fbuf + strlen (fbuf) - 4;
+
+      if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0)
+	return pep_implied_import_dll (fbuf);
+    }
+#endif
+  return FALSE;
+}
+
+static void
+gld_${EMULATION_NAME}_finish (void)
+{
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe)
+  struct bfd_link_hash_entry * h;
+
+  if (thumb_entry_symbol != NULL)
+    {
+      h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
+				FALSE, FALSE, TRUE);
+
+      if (h != (struct bfd_link_hash_entry *) NULL
+	  && (h->type == bfd_link_hash_defined
+	      || h->type == bfd_link_hash_defweak)
+	  && h->u.def.section->output_section != NULL)
+	{
+	  static char buffer[32];
+	  bfd_vma val;
+
+	  /* Special procesing is required for a Thumb entry symbol.  The
+	     bottom bit of its address must be set.  */
+	  val = (h->u.def.value
+		 + bfd_get_section_vma (output_bfd,
+					h->u.def.section->output_section)
+		 + h->u.def.section->output_offset);
+
+	  val |= 1;
+
+	  /* Now convert this value into a string and store it in entry_symbol
+	     where the lang_finish() function will pick it up.  */
+	  buffer[0] = '0';
+	  buffer[1] = 'x';
+
+	  sprintf_vma (buffer + 2, val);
+
+	  if (entry_symbol.name != NULL && entry_from_cmdline)
+	    einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
+		   thumb_entry_symbol, entry_symbol.name);
+	  entry_symbol.name = buffer;
+	}
+      else
+	einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
+    }
+#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) */
+
+  finish_default ();
+
+#ifdef DLL_SUPPORT
+  if (link_info.shared
+    || (!link_info.relocatable && pep_def_file->num_exports != 0)
+    )
+    {
+      pep_dll_fill_sections (output_bfd, &link_info);
+      if (pep_implib_filename)
+	pep_dll_generate_implib (pep_def_file, pep_implib_filename);
+    }
+
+  if (pep_out_def_filename)
+    pep_dll_generate_def_file (pep_out_def_filename);
+#endif /* DLL_SUPPORT */
+
+  /* I don't know where .idata gets set as code, but it shouldn't be.  */
+  {
+    asection *asec = bfd_get_section_by_name (output_bfd, ".idata");
+
+    if (asec)
+      {
+	asec->flags &= ~SEC_CODE;
+	asec->flags |= SEC_DATA;
+      }
+  }
+}
+
+\f
+/* Place an orphan section.
+
+   We use this to put sections in a reasonable place in the file, and
+   to ensure that they are aligned as required.
+
+   We handle grouped sections here as well.  A section named .foo$nn
+   goes into the output section .foo.  All grouped sections are sorted
+   by name.
+
+   Grouped sections for the default sections are handled by the
+   default linker script using wildcards, and are sorted by
+   sort_sections.  */
+
+static bfd_boolean
+gld_${EMULATION_NAME}_place_orphan (asection *s)
+{
+  const char *secname;
+  const char *orig_secname;
+  char *dollar = NULL;
+  lang_output_section_statement_type *os;
+  lang_statement_list_type add_child;
+
+  secname = bfd_get_section_name (s->owner, s);
+
+  /* Look through the script to see where to place this section.  */
+  orig_secname = secname;
+  if (!link_info.relocatable
+      && (dollar = strchr (secname, '$')) != NULL)
+    {
+      size_t len = dollar - orig_secname;
+      char *newname = xmalloc (len + 1);
+      memcpy (newname, orig_secname, len);
+      newname[len] = '\0';
+      secname = newname;
+    }
+
+  os = lang_output_section_find (secname);
+
+  lang_list_init (&add_child);
+
+  if (os != NULL
+      && (os->bfd_section == NULL
+	  || os->bfd_section->flags == 0
+	  || ((s->flags ^ os->bfd_section->flags)
+	      & (SEC_LOAD | SEC_ALLOC)) == 0))
+    {
+      /* We already have an output section statement with this
+	 name, and its bfd section, if any, has compatible flags.
+	 If the section already exists but does not have any flags set,
+	 then it has been created by the linker, probably as a result of
+	 a --section-start command line switch.  */
+      lang_add_section (&add_child, s, os);
+    }
+  else
+    {
+      static struct orphan_save hold[] =
+	{
+	  { ".text",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
+	    0, 0, 0, 0 },
+	  { ".rdata",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+	    0, 0, 0, 0 },
+	  { ".data",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
+	    0, 0, 0, 0 },
+	  { ".bss",
+	    SEC_ALLOC,
+	    0, 0, 0, 0 }
+	};
+      enum orphan_save_index
+	{
+	  orphan_text = 0,
+	  orphan_rodata,
+	  orphan_data,
+	  orphan_bss
+	};
+      static int orphan_init_done = 0;
+      struct orphan_save *place;
+      lang_output_section_statement_type *after;
+      etree_type *address;
+
+      if (!orphan_init_done)
+	{
+	  struct orphan_save *ho;
+	  for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
+	    if (ho->name != NULL)
+	      {
+		ho->os = lang_output_section_find (ho->name);
+		if (ho->os != NULL && ho->os->flags == 0)
+		  ho->os->flags = ho->flags;
+	      }
+	  orphan_init_done = 1;
+	}
+
+      /* Try to put the new output section in a reasonable place based
+	 on the section name and section flags.  */
+
+      place = NULL;
+      if ((s->flags & SEC_ALLOC) == 0)
+	;
+      else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+	place = &hold[orphan_bss];
+      else if ((s->flags & SEC_READONLY) == 0)
+	place = &hold[orphan_data];
+      else if ((s->flags & SEC_CODE) == 0)
+	place = &hold[orphan_rodata];
+      else
+	place = &hold[orphan_text];
+
+      after = NULL;
+      if (place != NULL)
+	{
+	  if (place->os == NULL)
+	    place->os = lang_output_section_find (place->name);
+	  after = place->os;
+	  if (after == NULL)
+	    after = lang_output_section_find_by_flags (s, &place->os, NULL);
+	  if (after == NULL)
+	    /* *ABS* is always the first output section statement.  */
+	    after = (&lang_output_section_statement.head
+		     ->output_section_statement);
+	}
+
+      /* Choose a unique name for the section.  This will be needed if the
+	 same section name appears in the input file with different
+	 loadable or allocatable characteristics.  */
+      if (bfd_get_section_by_name (output_bfd, secname) != NULL)
+	{
+	  static int count = 1;
+	  secname = bfd_get_unique_section_name (output_bfd, secname, &count);
+	  if (secname == NULL)
+	    einfo ("%F%P: place_orphan failed: %E\n");
+	}
+
+      /* All sections in an executable must be aligned to a page boundary.  */
+      address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
+      os = lang_insert_orphan (s, secname, after, place, address, &add_child);
+    }
+
+  {
+    lang_statement_union_type **pl = &os->children.head;
+
+    if (dollar != NULL)
+      {
+	bfd_boolean found_dollar;
+
+	/* The section name has a '$'.  Sort it with the other '$'
+	   sections.  */
+	found_dollar = FALSE;
+	for ( ; *pl != NULL; pl = &(*pl)->header.next)
+	  {
+	    lang_input_section_type *ls;
+	    const char *lname;
+
+	    if ((*pl)->header.type != lang_input_section_enum)
+	      continue;
+
+	    ls = &(*pl)->input_section;
+
+	    lname = bfd_get_section_name (ls->section->owner, ls->section);
+	    if (strchr (lname, '$') == NULL)
+	      {
+		if (found_dollar)
+		  break;
+	      }
+	    else
+	      {
+		found_dollar = TRUE;
+		if (strcmp (orig_secname, lname) < 0)
+		  break;
+	      }
+	  }
+      }
+
+    if (add_child.head != NULL)
+      {
+	add_child.head->header.next = *pl;
+	*pl = add_child.head;
+      }
+  }
+
+  return TRUE;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_open_dynamic_archive
+  (const char *arch ATTRIBUTE_UNUSED, search_dirs_type *search,
+   lang_input_statement_type *entry)
+{
+  const char * filename;
+  char * string;
+
+  if (! entry->is_archive)
+    return FALSE;
+
+  filename = entry->filename;
+
+  string = (char *) xmalloc (strlen (search->name)
+			     + strlen (filename)
+			     + sizeof "/lib.a.dll"
+#ifdef DLL_SUPPORT
+			     + (pep_dll_search_prefix ? strlen (pep_dll_search_prefix) : 0)
+#endif
+			     + 1);
+
+  /* Try "libfoo.dll.a" first (preferred explicit import library for dll's.  */
+  sprintf (string, "%s/lib%s.dll.a", search->name, filename);
+
+  if (! ldfile_try_open_bfd (string, entry))
+    {
+      /* Try "foo.dll.a" next (alternate explicit import library for dll's.  */
+      sprintf (string, "%s/%s.dll.a", search->name, filename);
+      if (! ldfile_try_open_bfd (string, entry))
+	{
+	  /* Try libfoo.a next. Normally, this would be interpreted as a static
+	     library, but it *could* be an import library. For backwards compatibility,
+	     libfoo.a needs to ==precede== libfoo.dll and foo.dll in the search,
+	     or sometimes errors occur when building legacy packages.
+
+	     Putting libfoo.a here means that in a failure case (i.e. the library
+	     -lfoo is not found) we will search for libfoo.a twice before
+	     giving up -- once here, and once when searching for a "static" lib.
+	     for a "static" lib.  */
+	  /* Try "libfoo.a" (import lib, or static lib, but must
+	     take precedence over dll's).  */
+	  sprintf (string, "%s/lib%s.a", search->name, filename);
+	  if (! ldfile_try_open_bfd (string, entry))
+	    {
+#ifdef DLL_SUPPORT
+	      if (pep_dll_search_prefix)
+		{
+		  /* Try "<prefix>foo.dll" (preferred dll name, if specified).  */
+		  sprintf (string, "%s/%s%s.dll", search->name, pep_dll_search_prefix, filename);
+		  if (! ldfile_try_open_bfd (string, entry))
+		    {
+		      /* Try "libfoo.dll" (default preferred dll name).  */
+		      sprintf (string, "%s/lib%s.dll", search->name, filename);
+		      if (! ldfile_try_open_bfd (string, entry))
+			{
+			  /* Finally, try "foo.dll" (alternate dll name).  */
+			  sprintf (string, "%s/%s.dll", search->name, filename);
+			  if (! ldfile_try_open_bfd (string, entry))
+			    {
+			      free (string);
+			      return FALSE;
+			    }
+			}
+		    }
+		}
+	      else /* pep_dll_search_prefix not specified.  */
+#endif
+		{
+		  /* Try "libfoo.dll" (preferred dll name).  */
+		  sprintf (string, "%s/lib%s.dll", search->name, filename);
+		  if (! ldfile_try_open_bfd (string, entry))
+		    {
+		      /* Finally, try "foo.dll" (alternate dll name).  */
+		      sprintf (string, "%s/%s.dll", search->name, filename);
+		      if (! ldfile_try_open_bfd (string, entry))
+			{
+			  free (string);
+			  return FALSE;
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+  entry->filename = string;
+
+  return TRUE;
+}
+
+static int
+gld_${EMULATION_NAME}_find_potential_libraries
+  (char *name, lang_input_statement_type *entry)
+{
+  return ldfile_open_file_search (name, entry, "", ".lib");
+}
+\f
+static char *
+gld_${EMULATION_NAME}_get_script (int *isfile)
+EOF
+# Scripts compiled in.
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+  *isfile = 0;
+
+  if (link_info.relocatable && config.build_constructors)
+    return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu			>> e${EMULATION_NAME}.c
+echo '  ; else if (link_info.relocatable) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr			>> e${EMULATION_NAME}.c
+echo '  ; else if (!config.text_read_only) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn			>> e${EMULATION_NAME}.c
+echo '  ; else if (!config.magic_demand_paged) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn			>> e${EMULATION_NAME}.c
+echo '  ; else return'					>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x			>> e${EMULATION_NAME}.c
+echo '; }'						>> e${EMULATION_NAME}.c
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+  gld_${EMULATION_NAME}_before_parse,
+  syslib_default,
+  hll_default,
+  gld_${EMULATION_NAME}_after_parse,
+  gld_${EMULATION_NAME}_after_open,
+  after_allocation_default,
+  set_output_arch_default,
+  ldemul_default_target,
+  gld_${EMULATION_NAME}_before_allocation,
+  gld_${EMULATION_NAME}_get_script,
+  "${EMULATION_NAME}",
+  "${OUTPUT_FORMAT}",
+  gld_${EMULATION_NAME}_finish,
+  NULL, /* Create output section statements.  */
+  gld_${EMULATION_NAME}_open_dynamic_archive,
+  gld_${EMULATION_NAME}_place_orphan,
+  gld_${EMULATION_NAME}_set_symbols,
+  NULL, /* parse_args */
+  gld${EMULATION_NAME}_add_options,
+  gld${EMULATION_NAME}_handle_option,
+  gld_${EMULATION_NAME}_unrecognized_file,
+  gld_${EMULATION_NAME}_list_options,
+  gld_${EMULATION_NAME}_recognized_file,
+  gld_${EMULATION_NAME}_find_potential_libraries,
+  NULL	/* new_vers_pattern.  */
+};
+EOF
diff -rNbu binutils_060913_org/ld/pe-dll.c binutils_060913/ld/pe-dll.c
--- binutils_060913_org/ld/pe-dll.c	2006-08-21 10:12:46.000000000 +0200
+++ binutils_060913/ld/pe-dll.c	2006-09-11 18:04:18.000000000 +0200
@@ -40,7 +40,27 @@
 #include "coff/internal.h"
 #include "../bfd/libcoff.h"
 #include "deffile.h"
+
+#ifdef pe_use_x86_64
+#define PE_IDATA4_SIZE	8
+#define PE_IDATA5_SIZE	8
+
+#include "pep-dll.h"
+
+#undef AOUTSZ
+#define AOUTSZ		PEPAOUTSZ
+#define PEAOUTHDR	PEPAOUTHDR
+#else
 #include "pe-dll.h"
+#endif
+
+#ifndef PE_IDATA4_SIZE
+#define PE_IDATA4_SIZE	4
+#endif
+
+#ifndef PE_IDATA4_SIZE
+#define PE_IDATA4_SIZE	4
+#endif
 
 /*  This file turns a regular Windows PE image into a DLL.  Because of
     the complexity of this operation, it has been broken down into a
@@ -49,7 +69,7 @@
     normally only called once, so static variables are used to reduce
     the number of parameters and return values required.
 
-    See also: ld/emultempl/pe.em.  */
+    See also: ld/emultempl/pe.em and ld/emultempl/pep.em.  */
 
 /*  Auto-import feature by Paul Sokolovsky
 
@@ -144,14 +164,14 @@
 static int runtime_pseudo_relocs_created = 0;
 
 typedef struct
-{
+  {
   char *name;
   int len;
-}
+  }
 autofilter_entry_type;
 
 typedef struct
-{
+  {
   char *target_name;
   char *object_target;
   unsigned int imagebase_reloc;
@@ -159,7 +179,7 @@
   int bfd_arch;
   bfd_boolean underscored;
   autofilter_entry_type* autofilter_symbollist; 
-}
+  }
 pe_details_type;
 
 static autofilter_entry_type autofilter_symbollist_generic[] =
@@ -212,9 +232,15 @@
 static pe_details_type pe_detail_list[] =
 {
   {
+#ifndef pe_use_x86_64
     "pei-i386",
     "pe-i386",
     7 /* R_IMAGEBASE */,
+#else    
+	"pei-x86-64",
+    "pe-x86-64",
+    3 /* R_IMAGEBASE */,
+#endif
     PE_ARCH_i386,
     bfd_arch_i386,
     TRUE,
@@ -480,6 +506,7 @@
 	 it is too restrictive.  Instead we have
 	 a target specific list to use:  */
       afptr = pe_details->autofilter_symbollist; 
+
       while (afptr->name)
 	{
 	  if (strcmp (n, afptr->name) == 0)
@@ -590,7 +617,6 @@
 		  {
 		    char *name = xmalloc (strlen (sn) + 2 + 6);
 		    sprintf (name, "%s%s", U("_imp_"), sn);
-
 		    blhe = bfd_link_hash_lookup (info->hash, name,
 						 FALSE, FALSE, FALSE);
 		    free (name);
@@ -1235,6 +1261,12 @@
 		      reloc_data[total_relocs].type = 5;
 		      total_relocs++;
 		      break;
+#ifdef pe_use_x86_64
+			case BITS_AND_SHIFT (64, 0):
+				  reloc_data[total_relocs].type = 10;
+				  total_relocs++;
+				  break;
+#endif
 		    case BITS_AND_SHIFT (24, 2):
 		      /* FIXME: 0 is ARM_26D, it is defined in bfd/coff-arm.c
 			 Those ARM_xxx definitions should go in proper
@@ -1312,14 +1344,15 @@
 
       bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12),
 		  reloc_d + reloc_sz);
-      reloc_sz += 2;
 
+      reloc_sz += 2;
       if (reloc_data[i].type == 4)
 	{
 	  bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);
 	  reloc_sz += 2;
 	}
 
+
       page_count++;
     }
 
@@ -1630,10 +1663,12 @@
 
  	.section	.idata$5
  	.long		0
+ 	[ .long		0] for PE+
    fthunk:
 
  	.section	.idata$4
  	.long		0
+ 	[ .long		0] for PE+
    hname:                              */
 
 static bfd *
@@ -1679,21 +1714,21 @@
   quick_reloc (abfd, 16, BFD_RELOC_RVA, 1);
   save_relocs (id2);
 
-  bfd_set_section_size (abfd, id5, 4);
-  d5 = xmalloc (4);
+  bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
+  d5 = xmalloc (PE_IDATA5_SIZE);
   id5->contents = d5;
-  memset (d5, 0, 4);
+  memset (d5, 0, PE_IDATA5_SIZE);
 
-  bfd_set_section_size (abfd, id4, 4);
-  d4 = xmalloc (4);
+  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
+  d4 = xmalloc (PE_IDATA4_SIZE);
   id4->contents = d4;
-  memset (d4, 0, 4);
+  memset (d4, 0, PE_IDATA4_SIZE);
 
   bfd_set_symtab (abfd, symtab, symptr);
 
   bfd_set_section_contents (abfd, id2, d2, 0, 20);
-  bfd_set_section_contents (abfd, id5, d5, 0, 4);
-  bfd_set_section_contents (abfd, id4, d4, 0, 4);
+  bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
+  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
 
   bfd_make_readable (abfd);
   return abfd;
@@ -1701,8 +1736,10 @@
 
 /*	.section	.idata$4
  	.long		0
+  	[.long		0] for PE+
  	.section	.idata$5
  	.long		0
+ 	[.long		0] for PE+
  	.section	idata$7
  	.global		__my_dll_iname
   __my_dll_iname:
@@ -1735,15 +1772,15 @@
   id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
   quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0);
 
-  bfd_set_section_size (abfd, id4, 4);
-  d4 = xmalloc (4);
+  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
+  d4 = xmalloc (PE_IDATA4_SIZE);
   id4->contents = d4;
-  memset (d4, 0, 4);
+  memset (d4, 0, PE_IDATA4_SIZE);
 
-  bfd_set_section_size (abfd, id5, 4);
-  d5 = xmalloc (4);
+  bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
+  d5 = xmalloc (PE_IDATA5_SIZE);
   id5->contents = d5;
-  memset (d5, 0, 4);
+  memset (d5, 0, PE_IDATA5_SIZE);
 
   len = strlen (dll_filename) + 1;
   if (len & 1)
@@ -1755,8 +1792,8 @@
 
   bfd_set_symtab (abfd, symtab, symptr);
 
-  bfd_set_section_contents (abfd, id4, d4, 0, 4);
-  bfd_set_section_contents (abfd, id5, d5, 0, 4);
+  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
+  bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
   bfd_set_section_contents (abfd, id7, d7, 0, len);
 
   bfd_make_readable (abfd);
@@ -1820,7 +1857,6 @@
   0,    0,    0,    0
 };
 
-
 static bfd *
 make_one (def_file_export *exp, bfd *parent)
 {
@@ -1943,16 +1979,16 @@
   quick_reloc (abfd, 0, BFD_RELOC_RVA, 5);
   save_relocs (id7);
 
-  bfd_set_section_size (abfd, id5, 4);
-  d5 = xmalloc (4);
+  bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
+  d5 = xmalloc (PE_IDATA5_SIZE);
   id5->contents = d5;
-  memset (d5, 0, 4);
+  memset (d5, 0, PE_IDATA5_SIZE);
 
   if (exp->flag_noname)
     {
       d5[0] = exp->ordinal;
       d5[1] = exp->ordinal >> 8;
-      d5[3] = 0x80;
+      d5[PE_IDATA5_SIZE-1] = 0x80;
     }
   else
     {
@@ -1960,16 +1996,16 @@
       save_relocs (id5);
     }
 
-  bfd_set_section_size (abfd, id4, 4);
-  d4 = xmalloc (4);
+  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
+  d4 = xmalloc (PE_IDATA4_SIZE);
   id4->contents = d4;
-  memset (d4, 0, 4);
+  memset (d4, 0, PE_IDATA4_SIZE);
 
   if (exp->flag_noname)
     {
       d4[0] = exp->ordinal;
       d4[1] = exp->ordinal >> 8;
-      d4[3] = 0x80;
+      d4[PE_IDATA4_SIZE-1] = 0x80;
     }
   else
     {
@@ -2000,8 +2036,8 @@
 
   bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count);
   bfd_set_section_contents (abfd, id7, d7, 0, 4);
-  bfd_set_section_contents (abfd, id5, d5, 0, 4);
-  bfd_set_section_contents (abfd, id4, d4, 0, 4);
+  bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
+  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
   if (!exp->flag_noname)
     bfd_set_section_contents (abfd, id6, d6, 0, len);
 
@@ -2035,16 +2071,16 @@
   quick_symbol (abfd, U ("_nm_thnk_"), import, "", id4, BSF_GLOBAL, 0);
   quick_symbol (abfd, U ("_nm_"), import, "", UNDSEC, BSF_GLOBAL, 0);
 
-  bfd_set_section_size (abfd, id4, 8);
-  d4 = xmalloc (4);
+  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
+  d4 = xmalloc (PE_IDATA4_SIZE);
   id4->contents = d4;
-  memset (d4, 0, 8);
+  memset (d4, 0, PE_IDATA4_SIZE);
   quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);
   save_relocs (id4);
 
   bfd_set_symtab (abfd, symtab, symptr);
 
-  bfd_set_section_contents (abfd, id4, d4, 0, 8);
+  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
 
   bfd_make_readable (abfd);
   return abfd;
@@ -2557,14 +2593,21 @@
 
   /* Get pe_header, optional header and numbers of export entries.  */
   pe_header_offset = pe_get32 (dll, 0x3c);
-  opthdr_ofs = pe_header_offset + 4 + 20;
+  opthdr_ofs = pe_header_offset + 4 + 20; // Magic of opt header
+#ifndef pe_use_x86_64
   num_entries = pe_get32 (dll, opthdr_ofs + 92);
-
+#else
+  num_entries = pe_get32 (dll, opthdr_ofs + 92 +4*4); //  &NumberOfRvaAndSizes
+#endif
   if (num_entries < 1) /* No exports.  */
     return FALSE;
-
+#ifndef pe_use_x86_64
   export_rva = pe_get32 (dll, opthdr_ofs + 96);
   export_size = pe_get32 (dll, opthdr_ofs + 100);
+#else
+  export_rva = pe_get32 (dll, opthdr_ofs + 96+4*4);
+  export_size = pe_get32 (dll, opthdr_ofs + 100+4*4);
+#endif
   nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
   secptr = (pe_header_offset + 4 + 20 +
 	    pe_get16 (dll, pe_header_offset + 4 + 16));
diff -rNbu binutils_060913_org/ld/pep-dll.c binutils_060913/ld/pep-dll.c
--- binutils_060913_org/ld/pep-dll.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/ld/pep-dll.c	2006-09-11 18:04:06.000000000 +0200
@@ -0,0 +1,58 @@
+/* Routines to help build PEPI-format DLLs (Win64 etc)
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+
+/* Local defined globals */
+#define pe_def_file	pep_def_file
+#define pe_details	pep_details
+#define pe_dll_compat_implib pep_dll_compat_implib
+#define pe_dll_extra_pe_debug pep_dll_extra_pe_debug
+#define pe_dll_export_everything pep_dll_export_everything
+#define pe_dll_do_default_excludes pep_dll_do_default_excludes
+#define pe_dll_kill_ats pep_dll_kill_ats
+#define pe_dll_stdcall_aliases pep_dll_stdcall_aliases
+#define pe_dll_warn_dup_exports pep_dll_warn_dup_exports
+
+/* external globals */
+#define pe_data_import_dll pep_data_import_dll
+
+/* Unique global name for functions to avoid double defined symbols */
+#define pe_create_import_fixup pep_create_import_fixup
+#define pe_dll_generate_def_file pep_dll_generate_def_file
+#define pe_process_import_defs pep_process_import_defs
+#define pe_dll_id_target pep_dll_id_target
+#define pe_implied_import_dll pep_implied_import_dll
+#define pe_dll_build_sections pep_dll_build_sections
+#define pe_exe_build_sections pep_exe_build_sections
+#define pe_dll_fill_sections pep_dll_fill_sections
+#define pe_exe_fill_sections pep_exe_fill_sections
+#define pe_dll_generate_implib pep_dll_generate_implib
+#define pe_dll_add_excludes pep_dll_add_excludes
+#define pe_walk_relocs_of_symbol pep_walk_relocs_of_symbol
+
+// Uses x86_64 PE+
+#define pe_use_x86_64
+
+#include "pe-dll.c"
diff -rNbu binutils_060913_org/ld/pep-dll.h binutils_060913/ld/pep-dll.h
--- binutils_060913_org/ld/pep-dll.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/ld/pep-dll.h	2006-08-17 09:13:36.000000000 +0200
@@ -0,0 +1,64 @@
+/* pep-dll.h: Header file for routines used to build Windows DLLs.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#ifndef PEP_DLL_H
+#define PEP_DLL_H
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "deffile.h"
+
+extern def_file *pep_def_file;
+extern int pep_dll_export_everything;
+extern int pep_dll_do_default_excludes;
+extern int pep_dll_kill_ats;
+extern int pep_dll_stdcall_aliases;
+extern int pep_dll_warn_dup_exports;
+extern int pep_dll_compat_implib;
+extern int pep_dll_extra_pe_debug;
+
+extern void pep_dll_id_target
+  (const char *);
+extern void pep_dll_add_excludes
+  (const char *, const int);
+extern void pep_dll_generate_def_file
+  (const char *);
+extern void pep_dll_generate_implib
+  (def_file *, const char *);
+extern void pep_process_import_defs
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean pep_implied_import_dll
+  (const char *);
+extern void pep_dll_build_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_exe_build_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_dll_fill_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_exe_fill_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_walk_relocs_of_symbol
+  (struct bfd_link_info *, const char *, int (*) (arelent *, asection *));
+extern void pep_create_import_fixup
+  (arelent * rel, asection *, int);
+#endif /* PE_DLL_H */
diff -rNbu binutils_060913_org/ld/scripttempl/pep.sc binutils_060913/ld/scripttempl/pep.sc
--- binutils_060913_org/ld/scripttempl/pep.sc	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/ld/scripttempl/pep.sc	2006-07-28 14:12:24.000000000 +0200
@@ -0,0 +1,272 @@
+# Linker script for PE.
+
+if test -z "${RELOCATEABLE_OUTPUT_FORMAT}"; then
+  RELOCATEABLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+fi
+
+# We can't easily and portably get an unquoted $ in a shell
+# substitution, so we do this instead.
+# Sorting of the .foo$* sections is required by the definition of
+# grouped sections in PE.
+# Sorting of the file names in R_IDATA is required by the
+# current implementation of dlltool (this could probably be changed to
+# use grouped sections instead).
+if test "${RELOCATING}"; then
+  R_TEXT='*(SORT(.text$*))'
+  R_DATA='*(SORT(.data$*))'
+  R_RDATA='*(SORT(.rdata$*))'
+  R_IDATA='
+    SORT(*)(.idata$2)
+    SORT(*)(.idata$3)
+    /* These zeroes mark the end of the import list.  */
+    LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
+    SORT(*)(.idata$4)
+    SORT(*)(.idata$5)
+    SORT(*)(.idata$6)
+    SORT(*)(.idata$7)'
+  R_CRT_XC='*(SORT(.CRT$XC*))  /* C initialization */'
+  R_CRT_XI='*(SORT(.CRT$XI*))  /* C++ initialization */'
+  R_CRT_XL='*(SORT(.CRT$XL*))  /* TLS callbacks */'
+  R_CRT_XP='*(SORT(.CRT$XP*))  /* Pre-termination */'
+  R_CRT_XT='*(SORT(.CRT$XT*))  /* Termination */'
+  R_TLS='
+    *(.tls)
+    *(.tls$)
+    *(SORT(.tls$*))'
+  R_RSRC='*(SORT(.rsrc$*))'
+else
+  R_TEXT=
+  R_DATA=
+  R_RDATA=
+  R_IDATA=
+  R_CRT=
+  R_RSRC=
+fi
+
+cat <<EOF
+${RELOCATING+OUTPUT_FORMAT(${OUTPUT_FORMAT})}
+${RELOCATING-OUTPUT_FORMAT(${RELOCATEABLE_OUTPUT_FORMAT})}
+${OUTPUT_ARCH+OUTPUT_ARCH(${OUTPUT_ARCH})}
+
+${LIB_SEARCH_DIRS}
+
+SECTIONS
+{
+  ${RELOCATING+/* Make the virtual address and file offset synced if the alignment is}
+  ${RELOCATING+   lower than the target page size. */}
+  ${RELOCATING+. = SIZEOF_HEADERS;}
+  ${RELOCATING+. = ALIGN(__section_alignment__);}
+  .text ${RELOCATING+ __image_base__ + ( __section_alignment__ < ${TARGET_PAGE_SIZE} ? . : __section_alignment__ )} : 
+  {
+    ${RELOCATING+ *(.init)}
+    *(.text)
+    ${R_TEXT}
+    *(.glue_7t)
+    *(.glue_7)
+    ${CONSTRUCTING+ ___CTOR_LIST__ = .; __CTOR_LIST__ = . ; 
+			LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*));  LONG (0); }
+    ${CONSTRUCTING+ ___DTOR_LIST__ = .; __DTOR_LIST__ = . ; 
+			LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*));  LONG (0); }
+    ${RELOCATING+ *(.fini)}
+    /* ??? Why is .gcc_exc here?  */
+    ${RELOCATING+ *(.gcc_exc)}
+    ${RELOCATING+PROVIDE (etext = .);}
+    *(.gcc_except_table)
+  }
+
+  /* The Cygwin32 library uses a section to avoid copying certain data
+     on fork.  This used to be named ".data$nocopy".  The linker used
+     to include this between __data_start__ and __data_end__, but that
+     breaks building the cygwin32 dll.  Instead, we name the section
+     ".data_cygwin_nocopy" and explictly include it after __data_end__. */
+
+  .data ${RELOCATING+BLOCK(__section_alignment__)} : 
+  {
+    ${RELOCATING+__data_start__ = . ;}
+    *(.data)
+    *(.data2)
+    ${R_DATA}
+    *(.jcr)
+    ${RELOCATING+__data_end__ = . ;}
+    ${RELOCATING+*(.data_cygwin_nocopy)}
+  }
+
+  .rdata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.rdata)
+    ${R_RDATA}
+    *(.eh_frame)
+    ${RELOCATING+___RUNTIME_PSEUDO_RELOC_LIST__ = .;}
+    ${RELOCATING+__RUNTIME_PSEUDO_RELOC_LIST__ = .;}
+    *(.rdata_runtime_pseudo_reloc)
+    ${RELOCATING+___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;}
+    ${RELOCATING+__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;}
+  }
+
+  .pdata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.pdata)
+  }
+
+  .bss ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    ${RELOCATING+__bss_start__ = . ;}
+    *(.bss)
+    *(COMMON)
+    ${RELOCATING+__bss_end__ = . ;}
+  }
+
+  .edata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.edata)
+  }
+
+  /DISCARD/ :
+  {
+    *(.debug\$S)
+    *(.debug\$T)
+    *(.debug\$F)
+    *(.drectve)
+  }
+
+  .idata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    /* This cannot currently be handled with grouped sections.
+	See pep.em:sort_sections.  */
+    ${R_IDATA}
+  }
+  .CRT ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    ${RELOCATING+___crt_xc_start__ = . ;}
+    ${R_CRT_XC}
+    ${RELOCATING+___crt_xc_end__ = . ;}
+    ${RELOCATING+___crt_xi_start__ = . ;}
+    ${R_CRT_XI}
+    ${RELOCATING+___crt_xi_end__ = . ;}
+    ${RELOCATING+___crt_xl_start__ = . ;}
+    ${R_CRT_XL}
+    /* ___crt_xl_end__ is defined in the TLS Directory support code */
+    ${RELOCATING+___crt_xp_start__ = . ;}
+    ${R_CRT_XP}
+    ${RELOCATING+___crt_xp_end__ = . ;}
+    ${RELOCATING+___crt_xt_start__ = . ;}
+    ${R_CRT_XT}
+    ${RELOCATING+___crt_xt_end__ = . ;}
+  }
+
+  .tls ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    ${RELOCATING+___tls_start__ = . ;}
+    ${R_TLS}
+    ${RELOCATING+___tls_end__ = . ;}
+  }
+
+  .endjunk ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    /* end is deprecated, don't use it */
+    ${RELOCATING+PROVIDE (end = .);}
+    ${RELOCATING+PROVIDE ( _end = .);}
+    ${RELOCATING+ __end__ = .;}
+  }
+
+  .rsrc ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    *(.rsrc)
+    ${R_RSRC}
+  }
+
+  .reloc ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    *(.reloc)
+  }
+
+  .stab ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.stab)
+  }
+
+  .stabstr ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.stabstr)
+  }
+
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section.  Unlike other targets that fake this by putting the
+     section VMA at 0, the PE format will not allow it.  */
+     
+  /* DWARF 1.1 and DWARF 2.  */
+  .debug_aranges ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_aranges)
+  }
+
+  .debug_pubnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_pubnames)
+  }
+
+  /* DWARF 2.  */
+  .debug_info ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_info) *(.gnu.linkonce.wi.*)
+  }
+
+  .debug_abbrev ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_abbrev)
+  }
+
+  .debug_line ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_line)
+  }
+
+  .debug_frame ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_frame)
+  }
+
+  .debug_str ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_str)
+  }
+
+  .debug_loc ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_loc)
+  }
+
+  .debug_macinfo ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_macinfo)
+  }
+
+  /* SGI/MIPS DWARF 2 extensions.  */
+  .debug_weaknames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_weaknames)
+  }
+
+  .debug_funcnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_funcnames)
+  }
+
+  .debug_typenames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_typenames)
+  }
+
+  .debug_varnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_varnames)
+  }
+
+  /* DWARF 3.  */
+  .debug_ranges ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_ranges)
+  }
+}
+EOF
diff -rNbu binutils_060913_org/ld/testsuite/ld-bootstrap/bootstrap.exp binutils_060913/ld/testsuite/ld-bootstrap/bootstrap.exp
--- binutils_060913_org/ld/testsuite/ld-bootstrap/bootstrap.exp	2005-11-15 09:32:01.000000000 +0100
+++ binutils_060913/ld/testsuite/ld-bootstrap/bootstrap.exp	2006-09-11 14:54:48.000000000 +0200
@@ -140,7 +140,7 @@
 	|| [istarget "*-*-wince"]
 	|| [istarget "*-*-cygwin*"]
 	|| [istarget "*-*-winnt*"]
-	|| [istarget "*-*-mingw32*"]
+	|| [istarget "*-*-mingw*"]
 	|| [istarget "*-*-interix*"]
 	|| [istarget "*-*-beospe*"]
 	|| [istarget "*-*-netbsdpe*"]} {
diff -rNbu binutils_060913_org/ld/testsuite/ld-fastcall/fastcall.exp binutils_060913/ld/testsuite/ld-fastcall/fastcall.exp
--- binutils_060913_org/ld/testsuite/ld-fastcall/fastcall.exp	2005-05-12 09:32:06.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-fastcall/fastcall.exp	2006-09-11 14:55:40.000000000 +0200
@@ -17,13 +17,13 @@
 
 set testname "ld (fastcall symbols)"
 
-if {![istarget "i*86-*-*"]} {
+if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw64*"] } {
     return
 }
 
 if {  !([istarget "i*86-*-*pe*"] && ![istarget "i*86-*-opensd*"]) \
     && ![istarget "i*86-*-cygwin*"] \
-    && ![istarget "i*86-*-mingw32*"] } {
+    && ![istarget "i*86-*-mingw*"] } {
     return
 }
 
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/align.exp binutils_060913/ld/testsuite/ld-scripts/align.exp
--- binutils_060913_org/ld/testsuite/ld-scripts/align.exp	2005-10-25 19:40:12.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-scripts/align.exp	2006-09-11 14:57:56.000000000 +0200
@@ -30,12 +30,19 @@
 }
 
 # Doesn't work on PECOFF, appears to be a genuine bug
-if [is_pecoff_format] {
+# mingw64 targets need to set the image base to 0 to avoid auto image-basing.
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+} else {
+  if [is_pecoff_format] {
   global target_triplet
   setup_xfail $target_triplet
+  }
 }
 
-if ![ld_simple_link $ld tmpdir/align "-T $srcdir/$subdir/align.t tmpdir/align.o"] {
+if ![ld_simple_link $ld tmpdir/align "$LDFLAGS -T $srcdir/$subdir/align.t tmpdir/align.o"] {
     fail $testname
 } else {
     pass $testname
@@ -50,3 +57,4 @@
     run_dump_test align2b
 }
 run_dump_test align2c
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/align2a.d binutils_060913/ld/testsuite/ld-scripts/align2a.d
--- binutils_060913_org/ld/testsuite/ld-scripts/align2a.d	2005-02-21 09:18:49.000000000 +0100
+++ binutils_060913/ld/testsuite/ld-scripts/align2a.d	2006-09-06 15:34:34.000000000 +0200
@@ -1,12 +1,12 @@
-# ld: --defsym data_align=16 -T align2.t
-# objdump: --section-headers
+#ld: --defsym data_align=16 -T align2.t
+#objdump: --section-headers
 
 [^:]+: +file format.*
 
 Sections:
 Idx +Name +Size +VMA +LMA +File +off +Algn
- +0 +\.text +[^ ]* +0+ +0+ .*
- +CONTENTS, +ALLOC, +LOAD,.* CODE
- +1 +\.data +[^ ]* +0+10 +0+10 .*
- +CONTENTS, +ALLOC, +LOAD, +DATA
+[	 ]+0 +\.text +[^ ]* +0+ +0+ .*
+[	 ]+CONTENTS, +ALLOC, +LOAD,.* CODE
+[	 ]+1 +\.data +[^ ]* +0+10 +0+10 .*
+[	 ]+CONTENTS, +ALLOC, +LOAD, +DATA
 #pass
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/defined.exp binutils_060913/ld/testsuite/ld-scripts/defined.exp
--- binutils_060913_org/ld/testsuite/ld-scripts/defined.exp	2005-05-12 09:32:08.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-scripts/defined.exp	2006-09-06 17:02:32.000000000 +0200
@@ -20,12 +20,19 @@
 set testname "DEFINED"
 set prms_id 5699
 
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+}
+
 if ![ld_assemble $as $srcdir/$subdir/defined.s tmpdir/def.o] {
     unresolved $testname
+    set LDFLAGS "$saved_LDFLAGS"
     return
 }
 
-if ![ld_simple_link $ld tmpdir/def "-T $srcdir/$subdir/defined.t tmpdir/def.o"] {
+if ![ld_simple_link $ld tmpdir/def "$LDFLAGS -T $srcdir/$subdir/defined.t tmpdir/def.o"] {
     fail $testname
 } else {
     if ![ld_nm $nm "" tmpdir/def] {
@@ -57,3 +64,4 @@
 set prms_id 0
 run_dump_test "defined2"
 run_dump_test "defined3"
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/provide.exp binutils_060913/ld/testsuite/ld-scripts/provide.exp
--- binutils_060913_org/ld/testsuite/ld-scripts/provide.exp	2005-06-01 06:04:19.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-scripts/provide.exp	2006-09-06 17:04:32.000000000 +0200
@@ -29,7 +29,15 @@
     return
 }
 
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+}
+
+
 run_dump_test provide-1
 run_dump_test provide-2
 setup_xfail *-*-*
 run_dump_test provide-3
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/script.exp binutils_060913/ld/testsuite/ld-scripts/script.exp
--- binutils_060913_org/ld/testsuite/ld-scripts/script.exp	2005-05-12 09:32:08.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-scripts/script.exp	2006-09-11 15:00:32.000000000 +0200
@@ -95,7 +95,7 @@
 set flags ""
 if {[istarget "*-*-pe*"] \
     || [istarget "*-*-cygwin*"] \
-    || [istarget "*-*-mingw32*"] \
+    || [istarget "*-*-mingw*"] \
     || [istarget "*-*-winnt*"] \
     || [istarget "*-*-nt"] \
     || [istarget "*-*-interix*"] } then {
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/weak.exp binutils_060913/ld/testsuite/ld-scripts/weak.exp
--- binutils_060913_org/ld/testsuite/ld-scripts/weak.exp	2005-08-18 09:51:07.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-scripts/weak.exp	2006-09-06 17:33:38.000000000 +0200
@@ -29,11 +29,11 @@
 # Weak symbols are broken for non-i386 PE targets.
 if {! [istarget i?86-*-*]} {
     setup_xfail *-*-pe*
+    setup_xfail *-*-mingw64*
 }
 
 # hppa64 and or32 are incredibly broken
 setup_xfail hppa64-*-* or32-*-*
-
 if {! [ld_assemble $as $srcdir/$subdir/weak1.s tmpdir/weak1.o]
     || ! [ld_assemble $as $srcdir/$subdir/weak2.s tmpdir/weak2.o]} then {
     # It's OK if .weak doesn't work on this target.
@@ -41,6 +41,12 @@
     return
 }
 
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+}
+
 set weak_regexp_big \
 ".*Contents of section .text:.*1000 00001008 0000200c 12121212 34343434.*Contents of section .data:.*2000 00001008 0000200c 56565656 78787878.*"
 
@@ -67,3 +73,4 @@
 	fail $testname
     }
 }
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils_060913_org/ld/testsuite/lib/ld-lib.exp binutils_060913/ld/testsuite/lib/ld-lib.exp
--- binutils_060913_org/ld/testsuite/lib/ld-lib.exp	2006-09-07 19:16:34.000000000 +0200
+++ binutils_060913/ld/testsuite/lib/ld-lib.exp	2006-09-11 15:02:02.000000000 +0200
@@ -434,7 +434,7 @@
 # True if the object format is known to be PE COFF.
 #
 proc is_pecoff_format {} {
-    if { ![istarget *-*-mingw32*] \
+    if { ![istarget *-*-mingw*] \
 	 && ![istarget *-*-cygwin*] \
 	 && ![istarget *-*-pe*] } {
 	return 0

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista binaries
  2006-09-13 10:52 ` Pedro Alves
  2006-09-13 11:50   ` Kai Tietz
  2006-09-13 11:54   ` Kai Tietz
@ 2006-09-13 12:02   ` Kai Tietz
  2006-09-13 12:07   ` Kai Tietz
  3 siblings, 0 replies; 17+ messages in thread
From: Kai Tietz @ 2006-09-13 12:02 UTC (permalink / raw)
  To: Pedro Alves; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 1939 bytes --]

Hello Pedro,

here comes the fourth one for gas

Change log modifications for gas:

        * configure.in: Add new target x86_64-pc-mingw64
        * configure.tgt:        Add new target x86_64-pc-mingw64
        * config/obj-coff.h:    Add handling for TE_PEP target specific 
code and definitions
        * config/tc-i386.c:             Add new targets
                md_parse_option:                        Add targets to 
OPTION_64
                x86_64_target_format:   Add new method for setup proper 
default target cpu mode
        * config/te-pep.h:              Add new target definition header
                TE_PEP:                         Identifies new target 
architecture
                COFF_WITH_pex64:        Set proper includes in bfd
Change log modifications for gas/testsuite:

        * i386/immed64.d:       Add #pass for avoid proplems with 
alignment paddings
        * i386/rex.d:           Changed for target matching
        * i386/x86-64-addr32.d: Changed for target matching and padding
        * i386/x86-64-branch.d: Changed for target matching and padding
        * i386/x86-64-crx-suffix.d:     Changed for target matching and 
padding
        * i386/x86-64-crx.d:    Changed for target matching
        * i386/x86-64-drx-suffix.d:     Changed for target matching and 
padding
        * i386/x86-64-crx-suffix.d:     Changed for target matching and 
padding
        * i386/x86-64-opcode.d: Changed for target matching
        * i386/x86-64-pcrel.d:  Changed for target matching and relocation 
fixing
        * i386/x86-64-rip.d:    Changed for target matching and padding
        * i386/x86-64-stack-intel.d:    Changed for target matching and 
padding
        * i386/x86-64-stack-suffix.d:   Changed for target matching and 
padding
        * i386/x86-64-stack.d:  Changed for target matching and padding
        * i386/x86_64.d:        Changed section specifier to .text
Regards,
 i.A. Kai Tietz


[-- Attachment #2: binutils-2.17.pex-64.060913_gas.diff --]
[-- Type: application/octet-stream, Size: 17652 bytes --]

diff -rNbu binutils_060913_org/gas/config/obj-coff.h binutils_060913/gas/config/obj-coff.h
--- binutils_060913_org/gas/config/obj-coff.h	2006-06-07 13:27:57.000000000 +0200
+++ binutils_060913/gas/config/obj-coff.h	2006-09-11 14:17:40.000000000 +0200
@@ -55,16 +55,30 @@
 #endif
 
 #ifdef TC_I386
+#ifndef TE_PEP
 #include "coff/i386.h"
+#else
+#include "coff/x86_64.h"
+#endif
 
 #ifdef TE_PE
+#ifdef TE_PEP
+extern const char *x86_64_target_format PARAMS ((void));
+#define TARGET_FORMAT x86_64_target_format ()
+#define COFF_TARGET_FORMAT "pe-x86-64"
+#else
 #define TARGET_FORMAT "pe-i386"
 #endif
+#endif
 
 #ifndef TARGET_FORMAT
+#ifdef TE_PEP
+#define TARGET_FORMAT "coff-x86-64"
+#else
 #define TARGET_FORMAT "coff-i386"
 #endif
 #endif
+#endif
 
 #ifdef TC_M68K
 #include "coff/m68k.h"
diff -rNbu binutils_060913_org/gas/config/tc-i386.c binutils_060913/gas/config/tc-i386.c
--- binutils_060913_org/gas/config/tc-i386.c	2006-08-02 18:25:14.000000000 +0200
+++ binutils_060913/gas/config/tc-i386.c	2006-09-11 14:26:14.000000000 +0200
@@ -5768,7 +5768,7 @@
 
 struct option md_longopts[] = {
   {"32", no_argument, NULL, OPTION_32},
-#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined(TE_PEP)
   {"64", no_argument, NULL, OPTION_64},
 #endif
   {"divide", no_argument, NULL, OPTION_DIVIDE},
@@ -5793,7 +5793,8 @@
       quiet_warnings = 1;
       break;
 
-#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined(TE_PEP)
+#ifndef TE_PEP
       /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
 	 should be emitted or not.  FIXME: Not implemented.  */
     case 'Q':
@@ -5812,14 +5813,15 @@
       /* -s: On i386 Solaris, this tells the native assembler to use
 	 .stab instead of .stab.excl.  We always use .stab anyhow.  */
       break;
-
+#endif
     case OPTION_64:
       {
 	const char **list, **l;
 
 	list = bfd_target_list ();
 	for (l = list; *l != NULL; l++)
-	  if (strncmp (*l, "elf64-x86-64", 12) == 0)
+	  if (strcmp (*l, "elf64-x86-64") == 0 || strcmp(*l,"coff-x86-64")==0 || strcmp(*l,"pe-x86-64")==0 ||
+		  strcmp(*l,"pei-x86-64")==0)
 	    {
 	      default_arch = "x86_64";
 	      break;
@@ -5927,6 +5929,22 @@
 
 }
 
+#if defined(TE_PEP)
+const char *x86_64_target_format(void)
+{
+	if (!strcmp (default_arch, "x86_64")) {
+		set_code_flag (CODE_64BIT);
+		return COFF_TARGET_FORMAT;
+	} else if (!strcmp (default_arch, "i386")) {
+		set_code_flag (CODE_32BIT);
+		return "coff-i386";
+	} else
+		as_fatal (_("Unknown architecture"));
+	abort ();
+	return NULL;
+}
+#endif
+
 #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
      || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))
 
diff -rNbu binutils_060913_org/gas/config/te-pep.h binutils_060913/gas/config/te-pep.h
--- binutils_060913_org/gas/config/te-pep.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/gas/config/te-pep.h	2006-09-11 14:26:46.000000000 +0200
@@ -0,0 +1,10 @@
+#define TE_PEP
+#define COFF_WITH_pex64
+
+#define TE_PE
+#define LEX_AT (LEX_BEGIN_NAME | LEX_NAME) /* Can have @'s inside labels.  */
+
+/* The PE format supports long section names.  */
+#define COFF_LONG_SECTION_NAMES
+
+#include "obj-format.h"
diff -rNbu binutils_060913_org/gas/configure binutils_060913/gas/configure
--- binutils_060913_org/gas/configure	2006-08-02 16:26:07.000000000 +0200
+++ binutils_060913/gas/configure	2006-09-11 14:09:36.000000000 +0200
@@ -3921,7 +3921,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -3935,6 +3935,9 @@
         x86_64-*linux*)
           LD="${LD-ld} -m elf_i386"
           ;;
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_i386"
+          ;;
         ppc64-*linux*|powerpc64-*linux*)
           LD="${LD-ld} -m elf32ppclinux"
           ;;
@@ -3951,6 +3954,9 @@
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         ppc*-*linux*|powerpc*-*linux*)
           LD="${LD-ld} -m elf64ppc"
           ;;
@@ -4948,6 +4954,11 @@
 #define I386COFF 1
 _ACEOF
  ;;
+      x86_64)
+cat >>confdefs.h <<\_ACEOF
+#define I386COFF 1
+_ACEOF
+ ;;
       m68k)
 cat >>confdefs.h <<\_ACEOF
 #define M68KCOFF 1
diff -rNbu binutils_060913_org/gas/configure.in binutils_060913/gas/configure.in
--- binutils_060913_org/gas/configure.in	2006-08-02 16:26:07.000000000 +0200
+++ binutils_060913/gas/configure.in	2006-09-11 14:11:30.000000000 +0200
@@ -417,6 +417,19 @@
       ;;
     esac
   ;;
+  x86_64)
+    case ${obj_format} in
+    aout)
+      emulations="$emulations i386coff i386elf"
+      ;;
+    coff)
+      emulations="$emulations i386aout i386elf"
+    ;;
+    elf)
+      emulations="$emulations i386aout i386coff"
+      ;;
+    esac
+  ;;
   esac
 fi
 
@@ -459,6 +472,7 @@
   coff)
     case ${target_cpu_type} in
       i386) AC_DEFINE(I386COFF, 1, [Using i386 COFF?]) ;;
+      x86_64) AC_DEFINE(I386COFF, 1, [Using i386 COFF?]) ;;
       m68k) AC_DEFINE(M68KCOFF, 1, [Using m68k COFF?]) ;;
       m88k) AC_DEFINE(M88KCOFF, 1, [Using m88k COFF?]) ;;
     esac
diff -rNbu binutils_060913_org/gas/configure.tgt binutils_060913/gas/configure.tgt
--- binutils_060913_org/gas/configure.tgt	2006-08-15 20:23:11.000000000 +0200
+++ binutils_060913/gas/configure.tgt	2006-09-11 14:13:06.000000000 +0200
@@ -77,7 +77,7 @@
   strongarm*b)		cpu_type=arm endian=big ;;
   strongarm*)		cpu_type=arm endian=little ;;
   v850*)		cpu_type=v850 ;;
-  x86_64)		cpu_type=i386 arch=x86_64;;
+  x86_64*)		cpu_type=i386 arch=x86_64;;
   xscale*be|xscale*b)	cpu_type=arm endian=big ;;
   xscale*)		cpu_type=arm endian=little ;;
   xtensa*)		cpu_type=xtensa arch=xtensa ;;
@@ -210,6 +210,7 @@
   i386-*-cygwin*)			fmt=coff em=pe ;;
   i386-*-interix*)			fmt=coff em=interix ;;
   i386-*-mingw32*)			fmt=coff em=pe ;;
+  i386-*-mingw64*)			fmt=coff em=pep ;;
   i386-*-nto-qnx*)			fmt=elf ;;
   i386-*-*nt*)				fmt=coff em=pe ;;
   i386-*-chaos)				fmt=elf ;;
diff -rNbu binutils_060913_org/gas/testsuite/gas/all/gas.exp binutils_060913/gas/testsuite/gas/all/gas.exp
--- binutils_060913_org/gas/testsuite/gas/all/gas.exp	2005-11-21 05:30:32.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/all/gas.exp	2006-09-11 14:28:34.000000000 +0200
@@ -207,6 +207,7 @@
      || [istarget i*86-*-isc*] \
      || [istarget i*86-*-go32*] \
      || [istarget i*86-*-cygwin*] \
+     || [istarget x86_64-*-mingw64*] \
      || [istarget i*86-*-*nt] \
      || [istarget i*86-*-interix*] \
      || ([istarget i960-*-vxworks5.*] && ![istarget i960-*-vxworks5.0*]) } {
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/i386.exp binutils_060913/gas/testsuite/gas/i386/i386.exp
--- binutils_060913_org/gas/testsuite/gas/i386/i386.exp	2006-07-14 00:25:46.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/i386.exp	2006-09-11 16:09:42.000000000 +0200
@@ -155,7 +155,9 @@
     run_dump_test "x86-64-rep-suffix"
     run_dump_test "x86-64-gidt"
     run_dump_test "x86-64-nops"
+    if ![istarget "*-*-mingw64*"] then {
     run_dump_test "x86-64-nops-1"
+    }
     run_dump_test "x86-64-nops-1-k8"
     run_dump_test "x86-64-nops-1-nocona"
     run_dump_test "x86-64-nops-1-merom"
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/immed64.d binutils_060913/gas/testsuite/gas/i386/immed64.d
--- binutils_060913_org/gas/testsuite/gas/i386/immed64.d	2005-07-26 17:34:11.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/immed64.d	2006-09-11 14:29:36.000000000 +0200
@@ -57,3 +57,4 @@
 [ 	]*[0-9a-fA-F]+:[ 	]+e5 04[ 	]+inl? +\$0x4,%eax
 [ 	]*[0-9a-fA-F]+:[ 	]+e5 08[ 	]+inl? +\$0x8,%eax
 [ 	]*[0-9a-fA-F]+:[ 	]+e5 00[ 	]+inl? +\$0x0,%eax
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/rex.d binutils_060913/gas/testsuite/gas/i386/rex.d
--- binutils_060913_org/gas/testsuite/gas/i386/rex.d	2005-12-14 09:57:06.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/rex.d	2006-09-11 14:30:06.000000000 +0200
@@ -1,7 +1,7 @@
 #objdump: -dw
 #name: x86-64 manual rex prefix use
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-addr32.d binutils_060913/gas/testsuite/gas/i386/x86-64-addr32.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-addr32.d	2004-07-21 18:09:43.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-addr32.d	2006-09-11 14:31:36.000000000 +0200
@@ -2,7 +2,7 @@
 #objdump: -drw
 #name: x86-64 32-bit addressing
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -11,3 +11,4 @@
 [	 ]*8:[	 ]+67 49 8d 80 00 00 00 00[	 ]+addr32[	 ]+lea[ 	]+0x0\(%r8d?\),%rax.*
 [	 ]*10:[	 ]+67 48 8d 05 00 00 00 00[	 ]+addr32[	 ]+lea[ 	]+0\(%[re]ip\),%rax.*
 [	 ]*18:[	 ]+67 48 8d 04 25 00 00 00 00[	 ]+addr32[	 ]+lea[ 	]+0x0,%rax.*
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-branch.d binutils_060913/gas/testsuite/gas/i386/x86-64-branch.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-branch.d	2005-05-07 15:30:02.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-branch.d	2006-09-11 14:32:00.000000000 +0200
@@ -2,7 +2,7 @@
 #objdump: -drw
 #name: x86-64 indirect branch
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -11,3 +11,4 @@
 [	 ]*2:[	 ]+ff d0[	 ]+callq[	 ]+\*%rax
 [	 ]*4:[	 ]+ff e0[	 ]+jmpq[	 ]+\*%rax
 [	 ]*6:[	 ]+ff e0[	 ]+jmpq[	 ]+\*%rax
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-crx-suffix.d binutils_060913/gas/testsuite/gas/i386/x86-64-crx-suffix.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-crx-suffix.d	2006-02-12 18:26:21.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-crx-suffix.d	2006-09-11 14:33:10.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 control register related opcodes (with suffixes)
 #source: x86-64-crx.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -19,3 +19,4 @@
 [ 	]*[0-9a-f]+:	44 0f 20 c7[ 	]+movq[ 	]+?%cr8,%rdi
 [ 	]*[0-9a-f]+:	44 0f 22 c0[ 	]+movq[ 	]+?%rax,%cr8
 [ 	]*[0-9a-f]+:	44 0f 22 c7[ 	]+movq[ 	]+?%rdi,%cr8
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-crx.d binutils_060913/gas/testsuite/gas/i386/x86-64-crx.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-crx.d	2006-02-11 18:00:58.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-crx.d	2006-09-11 14:32:40.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 control register related opcodes
 #source: x86-64-crx.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -19,3 +19,4 @@
 [ 	]*[0-9a-f]+:	44 0f 20 c7[ 	]+movq?[ 	]+?%cr8,%rdi
 [ 	]*[0-9a-f]+:	44 0f 22 c0[ 	]+movq?[ 	]+?%rax,%cr8
 [ 	]*[0-9a-f]+:	44 0f 22 c7[ 	]+movq?[ 	]+?%rdi,%cr8
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-drx-suffix.d binutils_060913/gas/testsuite/gas/i386/x86-64-drx-suffix.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-drx-suffix.d	2006-02-11 19:08:35.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-drx-suffix.d	2006-09-11 14:33:44.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 debug register related opcodes (with suffixes)
 #source: x86-64-drx.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -19,3 +19,4 @@
 [ 	]*[0-9a-f]+:	44 0f 21 c7[ 	]+movq[ 	]+?%db8,%rdi
 [ 	]*[0-9a-f]+:	44 0f 23 c0[ 	]+movq[ 	]+?%rax,%db8
 [ 	]*[0-9a-f]+:	44 0f 23 c7[ 	]+movq[ 	]+?%rdi,%db8
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-drx.d binutils_060913/gas/testsuite/gas/i386/x86-64-drx.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-drx.d	2006-02-11 19:08:35.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-drx.d	2006-09-11 14:33:30.000000000 +0200
@@ -1,7 +1,7 @@
 #objdump: -dw
 #name: x86-64 debug register related opcodes
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -18,3 +18,4 @@
 [ 	]*[0-9a-f]+:	44 0f 21 c7[ 	]+movq?[ 	]+?%db8,%rdi
 [ 	]*[0-9a-f]+:	44 0f 23 c0[ 	]+movq?[ 	]+?%rax,%db8
 [ 	]*[0-9a-f]+:	44 0f 23 c7[ 	]+movq?[ 	]+?%rdi,%db8
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-opcode.d binutils_060913/gas/testsuite/gas/i386/x86-64-opcode.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-opcode.d	2006-07-18 22:25:40.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-opcode.d	2006-09-11 14:34:30.000000000 +0200
@@ -2,7 +2,7 @@
 #objdump: -drw
 #name: x86-64 opcode
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-pcrel.d binutils_060913/gas/testsuite/gas/i386/x86-64-pcrel.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-pcrel.d	2005-06-17 10:03:58.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-pcrel.d	2006-09-06 12:56:52.000000000 +0200
@@ -1,16 +1,16 @@
 #objdump: -drw
 #name: x86-64 pcrel
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
 0+000 <_start>:
-[	 ]*[0-9a-f]+:[	 ]+b0 00[	 ]+movb?[	 ]+\$(0x)?0,%al[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC8[	 ]+xtrn\+(0x)?1
-[	 ]*[0-9a-f]+:[	 ]+66 b8 00 00[	 ]+movw?[	 ]+\$(0x)?0,%ax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC16[	 ]+xtrn\+(0x)?2
-[	 ]*[0-9a-f]+:[	 ]+b8( 00){4}[	 ]+movl?[	 ]+\$(0x)?0,%eax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn\+(0x)?1
-[	 ]*[0-9a-f]+:[	 ]+48 c7 c0( 00){4}[	 ]+movq?[	 ]+\$(0x)?0,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn\+(0x)?3
-[	 ]*[0-9a-f]+:[	 ]+48 b8( 00){8}[	 ]+mov(abs)?q?[	 ]+\$(0x)?0,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC64[	 ]+xtrn\+(0x)?2
+[	 ]*[0-9a-f]+:[	 ]+b0 0[02]+[	 ]+movb?[	 ]+\$(0x)?[02]+,%al[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC8[	 ]+xtrn(\+(0x)?1)?
+[	 ]*[0-9a-f]+:[	 ]+66 b8 0[04]+ 00[	 ]+movw?[	 ]+\$(0x)?[04]+,%ax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC16[	 ]+xtrn(\+(0x)?2)?
+[	 ]*[0-9a-f]+:[	 ]+b8 0[05]+( 00){3}[	 ]+movl?[	 ]+\$(0x)?[05]+,%eax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn(\+(0x)?1)?
+[	 ]*[0-9a-f]+:[	 ]+48 c7 c0 0[07]+( 00){3}[	 ]+movq?[	 ]+\$(0x)?[07]+,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn(\+(0x)?3)?
+[	 ]*[0-9a-f]+:[	 ]+48 b8 0[0a]+( 00){7}[	 ]+mov(abs)?q?[	 ]+\$(0x)?[0a]+,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC64[	 ]+xtrn(\+(0x)?2)?
 [	 ]*[0-9a-f]+:[	 ]+b0 00[	 ]+movb?[	 ]+\$(0x)?0,%al[	 ]*[0-9a-f]+:[	 ]+R_X86_64_8[	 ]+xtrn
 [	 ]*[0-9a-f]+:[	 ]+66 b8 00 00[	 ]+movw?[	 ]+\$(0x)?0,%ax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_16[	 ]+xtrn
 [	 ]*[0-9a-f]+:[	 ]+b8( 00){4}[	 ]+movl?[	 ]+\$(0x)?0,%eax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_32[	 ]+xtrn
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-rip.d binutils_060913/gas/testsuite/gas/i386/x86-64-rip.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-rip.d	2004-07-21 18:09:43.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-rip.d	2006-09-11 14:35:50.000000000 +0200
@@ -2,7 +2,7 @@
 #objdump: -drw
 #name: x86-64 rip addressing
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -11,3 +11,4 @@
 [	 ]*6:[	 ]+8d 05 11 11 11 11[	 ]+lea[	 ]+286331153\(%rip\),%eax[ 	]*(#.*)?
 [	 ]*c:[	 ]+8d 05 01 00 00 00[	 ]+lea[	 ]+1\(%rip\),%eax[ 	]*(#.*)?
 [	 ]*12:[	 ]+8d 05 00 00 00 00[	 ]+lea[	 ]+0\(%rip\),%eax[ 	]*(#.*)?
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack-intel.d binutils_060913/gas/testsuite/gas/i386/x86-64-stack-intel.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack-intel.d	2005-09-28 17:34:51.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-stack-intel.d	2006-09-11 14:36:18.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 stack-related opcodes (Intel mode)
 #source: x86-64-stack.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack-suffix.d binutils_060913/gas/testsuite/gas/i386/x86-64-stack-suffix.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack-suffix.d	2005-09-28 17:34:51.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-stack-suffix.d	2006-09-11 14:36:46.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 stack-related opcodes (with suffixes)
 #source: x86-64-stack.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack.d binutils_060913/gas/testsuite/gas/i386/x86-64-stack.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack.d	2005-09-28 17:34:51.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-stack.d	2006-09-11 14:37:04.000000000 +0200
@@ -1,7 +1,7 @@
 #objdump: -dw
 #name: x86-64 stack-related opcodes
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86_64.d binutils_060913/gas/testsuite/gas/i386/x86_64.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86_64.d	2006-03-07 21:18:05.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/x86_64.d	2006-09-11 15:55:16.000000000 +0200
@@ -6,7 +6,7 @@
 
 Disassembly of section .text:
 
-0+ <bar-0x1a7>:
+0+ <.*>:
 [ 	]+0:	01 ca[ 	]+add[ 	]+%ecx,%edx
 [ 	]+2:	44 01 ca[ 	]+add[ 	]+%r9d,%edx
 [ 	]+5:	41 01 ca[ 	]+add[ 	]+%ecx,%r10d

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista binaries
  2006-09-13 10:52 ` Pedro Alves
  2006-09-13 11:50   ` Kai Tietz
@ 2006-09-13 11:54   ` Kai Tietz
  2006-09-13 12:02   ` Kai Tietz
  2006-09-13 12:07   ` Kai Tietz
  3 siblings, 0 replies; 17+ messages in thread
From: Kai Tietz @ 2006-09-13 11:54 UTC (permalink / raw)
  To: Pedro Alves; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 1377 bytes --]

Hallo Pedro,

here comes the third part of the patch for binutils (This is a small one)

Change log modifications for binutils:

        * configure.in: Add new target x86_64-pc-mingw64
        * dlltool.c:    Adjust include for this target
                DLLTOOL_MX86_64:        Added macro to handle target 
specific code
                mname:                                  Added default 
target static as "i386:x86-64"
                MX86:                                   Added macro for 
target ident
                mtable:                         Added target specific 
definitions
                rvaafter:                       Add handling of MX86
                rvabefore:                      Add handling of MX86
                asmprefix:                      Add handling of MX86

Changes log modifcations for binutils/testsuite:

        * binutils-all/dlltool.exp:     Add support for target 
x86_64-pc-mingw64
        * binutils-all/objcopy.exp:     Add support for target 
x86_64-pc-mingw64
        * binutils-all/windres/windres.exp:     Add support for target 
x86_64-pc-mingw64
        * binutils-all/windres/lang.rc: xfail it as long as there is no 
windows.h
        * binutils-all/windres/strtab1.rc:      xfail it as long as there 
is no windows.h
        * lib/utils-lib.exp:    Adjust executable prefix detection (as 
.exe)
 i.A. Kai Tietz


[-- Attachment #2: binutils-2.17.pex-64.060913_binutils.diff --]
[-- Type: application/octet-stream, Size: 13001 bytes --]

diff -rNbu binutils_060913_org/binutils/ChangeLog binutils_060913/binutils/ChangeLog
--- binutils_060913_org/binutils/ChangeLog	2006-09-11 16:40:39.000000000 +0200
+++ binutils_060913/binutils/ChangeLog	2006-09-13 11:06:00.000000000 +0200
@@ -1,3 +1,15 @@
+2006-09-13	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* configure.in:	Add new target x86_64-pc-mingw64
+	* dlltool.c:	Adjust include for this target
+		DLLTOOL_MX86_64:	Added macro to handle target specific code
+		mname:					Added default target static as "i386:x86-64"
+		MX86:					Added macro for target ident
+		mtable:				Added target specific definitions
+		rvaafter:			Add handling of MX86
+		rvabefore:			Add handling of MX86
+		asmprefix:			Add handling of MX86
+
 2006-09-09  Nick Clifton  <nickc@redhat.com>
 
 	PR binutils/3110
diff -rNbu binutils_060913_org/binutils/configure binutils_060913/binutils/configure
--- binutils_060913_org/binutils/configure	2006-08-21 10:12:45.000000000 +0200
+++ binutils_060913/binutils/configure	2006-09-11 13:50:34.000000000 +0200
@@ -8451,6 +8451,12 @@
 	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
 	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
 	  ;;
+	x86_64-*-mingw64*)
+  	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MX86_64"
+	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+	  ;;
 	i[3-7]86-*-interix)
 	  BUILD_DLLTOOL='$(DLLTOOL_PROG)'
 	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386"
diff -rNbu binutils_060913_org/binutils/configure.in binutils_060913/binutils/configure.in
--- binutils_060913_org/binutils/configure.in	2006-08-21 10:12:45.000000000 +0200
+++ binutils_060913/binutils/configure.in	2006-09-11 13:33:20.000000000 +0200
@@ -265,6 +265,14 @@
 	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
 	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
 	  ;;
+	x86_64-*-mingw64*)
+changequote([,])dnl
+  	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MX86_64"
+	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+	  ;;
+changequote(,)dnl
 changequote(,)dnl
 	i[3-7]86-*-interix)
 changequote([,])dnl
diff -rNbu binutils_060913_org/binutils/dlltool.c binutils_060913/binutils/dlltool.c
--- binutils_060913_org/binutils/dlltool.c	2006-08-21 10:12:45.000000000 +0200
+++ binutils_060913/binutils/dlltool.c	2006-09-11 13:47:12.000000000 +0200
@@ -261,6 +261,9 @@
 #include "coff/arm.h"
 #include "coff/internal.h"
 #endif
+#ifdef DLLTOOL_MX86_64
+#include "coff/x86_64.h"
+#endif
 
 /* Forward references.  */
 static char *look_for_prog (const char *, const char *, int);
@@ -398,6 +401,10 @@
 static const char *mname = "i386";
 #endif
 
+#ifdef DLLTOOL_MX86_64
+static const char *mname = "i386:x86-64";
+#endif
+
 #ifdef DLLTOOL_PPC
 static const char *mname = "ppc";
 #endif
@@ -640,6 +647,14 @@
     arm_jtab, sizeof (arm_jtab), 8
   }
   ,
+  {
+#define MX86 11
+    "i386:x86-64", ".byte", ".short", ".long", ".asciz", "#",
+    "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
+    "pe-x86-64",bfd_arch_i386,
+    i386_jtab, sizeof (i386_jtab), 2
+  }
+  ,
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 };
 
@@ -763,6 +778,7 @@
     {
     case MARM:
     case M386:
+	case MX86:
     case MPPC:
     case MTHUMB:
     case MARM_INTERWORK:
@@ -788,6 +804,7 @@
     {
     case MARM:
     case M386:
+	case MX86:
     case MPPC:
     case MTHUMB:
     case MARM_INTERWORK:
@@ -823,6 +840,7 @@
     case MARM_WINCE:
       break;
     case M386:
+	case MX86:
       /* Symbol names starting with ? do not have a leading underscore. */
       if (name && *name == '?')
         break;
@@ -1701,9 +1719,18 @@
     {
       fprintf (filvar, "listone%d:\n", headindex);
       for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
+#ifdef DLLTOOL_MX86_64
+	fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
+		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG);
+#else
 	fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
 		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
+#endif
+#ifdef DLLTOOL_MX86_64
+      fprintf (filvar,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
       fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       headindex++;
     }
 
@@ -1713,9 +1740,18 @@
     {
       fprintf (filvar, "listtwo%d:\n", headindex);
       for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
+#ifdef DLLTOOL_MX86_64
+	fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
+		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG);
+#else
 	fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
 		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
-      fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
+#ifdef DLLTOOL_MX86_64
+      fprintf (filvar,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       headindex++;
     }
 
@@ -2388,6 +2424,36 @@
 	  /* An idata$4 or idata$5 is one word long, and has an
 	     rva to idata$6.  */
 
+#ifdef DLLTOOL_MX86_64
+	  si->data = xmalloc (8);
+	  si->size = 8;
+
+	  if (exp->noname)
+	    {
+	      si->data[0] = exp->ordinal ;
+	      si->data[1] = exp->ordinal >> 8;
+	      si->data[2] = exp->ordinal >> 16;
+		  si->data[3] = exp->ordinal >> 24;
+		  si->data[4] = 0;
+		  si->data[5] = 0;
+		  si->data[6] = 0;
+	      si->data[7] = 0x80;
+	    }
+	  else
+	    {
+	      sec->reloc_count = 1;
+	      memset (si->data, 0, si->size);
+	      rel = xmalloc (sizeof (arelent));
+	      rpp = xmalloc (sizeof (arelent *) * 2);
+	      rpp[0] = rel;
+	      rpp[1] = 0;
+	      rel->address = 0;
+	      rel->addend = 0;
+	      rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
+	      rel->sym_ptr_ptr = secdata[IDATA6].sympp;
+	      sec->orelocation = rpp;
+	    }
+#else
 	  si->data = xmalloc (4);
 	  si->size = 4;
 
@@ -2412,7 +2478,7 @@
 	      rel->sym_ptr_ptr = secdata[IDATA6].sympp;
 	      sec->orelocation = rpp;
 	    }
-
+#endif
 	  break;
 
 	case IDATA6:
@@ -2626,7 +2692,11 @@
   if (!no_idata5)
     {
       fprintf (f, "\t.section\t.idata$5\n");
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       fprintf (f, "fthunk:\n");
     }
 
@@ -2634,7 +2704,11 @@
     {
       fprintf (f, "\t.section\t.idata$4\n");
 
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       fprintf (f, "\t.section	.idata$4\n");
       fprintf (f, "hname:\n");
     }
@@ -2660,13 +2734,21 @@
   if (!no_idata4)
     {
       fprintf (f, "\t.section	.idata$4\n");
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
     }
 
   if (!no_idata5)
     {
       fprintf (f, "\t.section	.idata$5\n");
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
     }
 
 #ifdef DLLTOOL_PPC
diff -rNbu binutils_060913_org/binutils/testsuite/ChangeLog binutils_060913/binutils/testsuite/ChangeLog
--- binutils_060913_org/binutils/testsuite/ChangeLog	2006-08-15 20:23:10.000000000 +0200
+++ binutils_060913/binutils/testsuite/ChangeLog	2006-09-13 11:06:25.000000000 +0200
@@ -1,3 +1,12 @@
+2006-09-13	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* binutils-all/dlltool.exp:	Add support for target x86_64-pc-mingw64
+	* binutils-all/objcopy.exp:	Add support for target x86_64-pc-mingw64
+	* binutils-all/windres/windres.exp:	Add support for target x86_64-pc-mingw64
+	* binutils-all/windres/lang.rc:	xfail it as long as there is no windows.h
+	* binutils-all/windres/strtab1.rc:	xfail it as long as there is no windows.h
+	* lib/utils-lib.exp:	Adjust executable prefix detection (as .exe)
+
 2006-08-15  Thiemo Seufer  <ths@mips.com>
             Nigel Stephens  <nigel@mips.com>
             David Ung  <davidu@mips.com>
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/copy-3.d binutils_060913/binutils/testsuite/binutils-all/copy-3.d
--- binutils_060913_org/binutils/testsuite/binutils-all/copy-3.d	2006-05-03 18:45:59.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/copy-3.d	2006-09-11 15:53:34.000000000 +0200
@@ -3,7 +3,7 @@
 #objcopy: --set-section-flags .text=alloc,data
 #name: copy with setting section flags 3
 #source: bintest.s
-#not-target: *-*-aout *-*-*pe *-*-*coff i*86-*-cygwin* i*86-*-mingw32*
+#not-target: *-*-aout *-*-*pe *-*-*coff i*86-*-cygwin* i*86-*-mingw32* x86_64-*-mingw64*
 # The .text # section in PE/COFF has a fixed set of flags and these
 # cannot be changed.  We skip it for them.
 
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/dlltool.exp binutils_060913/binutils/testsuite/binutils-all/dlltool.exp
--- binutils_060913_org/binutils/testsuite/binutils-all/dlltool.exp	2005-05-08 16:17:40.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/dlltool.exp	2006-09-11 13:53:24.000000000 +0200
@@ -14,13 +14,14 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 
-if {![istarget "i*86-*-*"]} {
+if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw64*"] } {
     return
 }
 
 if {![istarget "i*86-*-*pe*"] \
     && ![istarget "i*86-*-cygwin*"] \
-    && ![istarget "i*86-*-mingw32*"] } {
+    && ![istarget "i*86-*-mingw32*"] \
+    && ![istarget "x86_64-*-mingw64*"] } {
     set target_xfail "yes"
 } else {
     set target_xfail "no"
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/objcopy.exp binutils_060913/binutils/testsuite/binutils-all/objcopy.exp
--- binutils_060913_org/binutils/testsuite/binutils-all/objcopy.exp	2006-06-23 18:23:09.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/objcopy.exp	2006-09-11 13:54:42.000000000 +0200
@@ -443,7 +443,7 @@
 
 # Build a final executable.
 
-if { [istarget *-*-cygwin] || [istarget *-*-mingw32] } {
+if { [istarget *-*-cygwin] || [istarget *-*-mingw*] } {
     set test_prog "testprog.exe"
 } else {
     set test_prog "testprog"
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/windres/lang.rc binutils_060913/binutils/testsuite/binutils-all/windres/lang.rc
--- binutils_060913_org/binutils/testsuite/binutils-all/windres/lang.rc	2001-07-19 01:56:41.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/windres/lang.rc	2006-09-11 13:55:32.000000000 +0200
@@ -1,3 +1,4 @@
+//#xfail *-*-mingw64
 #include "windows.h"
 
 LANGUAGE 0, 0
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/windres/strtab1.rc binutils_060913/binutils/testsuite/binutils-all/windres/strtab1.rc
--- binutils_060913_org/binutils/testsuite/binutils-all/windres/strtab1.rc	2001-07-19 01:56:41.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/windres/strtab1.rc	2006-09-11 13:55:58.000000000 +0200
@@ -1,3 +1,4 @@
+//#xfail *-*-mingw64
 #include "windows.h"
 
 LANGUAGE 0, 0
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/windres/windres.exp binutils_060913/binutils/testsuite/binutils-all/windres/windres.exp
--- binutils_060913_org/binutils/testsuite/binutils-all/windres/windres.exp	2005-05-08 16:17:41.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/windres/windres.exp	2006-09-11 13:56:48.000000000 +0200
@@ -19,13 +19,14 @@
 
 # Written by DJ Delorie <dj@redhat.com>
 
-if {![istarget "i*86-*-*"]} {
+if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw64"] } {
     return
 }
 
 if {![istarget "i*86-*-*pe*"] \
     && ![istarget "i*86-*-cygwin*"] \
-    && ![istarget "i*86-*-mingw32*"] } {
+    && ![istarget "i*86-*-mingw32*"] \
+    && ![istarget "x86_64-*-mingw64*"] } {
     set target_xfail "yes"
 } else {
     set target_xfail "no"
diff -rNbu binutils_060913_org/binutils/testsuite/lib/utils-lib.exp binutils_060913/binutils/testsuite/lib/utils-lib.exp
--- binutils_060913_org/binutils/testsuite/lib/utils-lib.exp	2006-04-26 15:37:05.000000000 +0200
+++ binutils_060913/binutils/testsuite/lib/utils-lib.exp	2006-09-11 13:57:44.000000000 +0200
@@ -161,7 +161,7 @@
 #	Returns target executable extension, if any.
 #
 proc exe_ext {} {
-    if { [istarget *-*-mingw32] || [istarget *-*-cygwin*] } {
+    if { [istarget *-*-mingw*] || [istarget *-*-cygwin*] } {
         return ".exe"
     } else {
         return ""

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista  binaries
  2006-09-13 10:52 ` Pedro Alves
@ 2006-09-13 11:50   ` Kai Tietz
  2006-09-13 11:54   ` Kai Tietz
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 17+ messages in thread
From: Kai Tietz @ 2006-09-13 11:50 UTC (permalink / raw)
  To: Pedro Alves; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 2968 bytes --]

Hallo Pedro,

I tested the testsuites on i386-linux cross and native for binutils, gas, 
and ld. Sorry for, but I have no other architecture available.

Here comes the two first parts of the patch. There will be another three 
for binutils, gas, and ld coming up soon.

Change log modifications for include/coff

        * external.h:   Add proper external_aouthdr64 structure (without 
data_start member)
                AOUTHDRSZ64:    Set according structure size
                AOUTHDR64:              As typedef of external_aouthdr64 
structure
        * internal.h:   Add relocation identifiers for coff
        * pe.h: Add define IMAGE_FILE_MACHINE_AMD64 the coff signature
                PEPAOUTHDR:             Adjust structure to have proper 
size (using AOUTHDR64)
                PEPAOUTSZ:              Calculated size of 240
        * x86_64.h:     New file for coff information for x86_64 (AMD64)

Changes log modifications for bfd

        * configure.in: Added new target-vectors x86_64coff_vec, 
x86_64pe_vec, and x86_64pei_vec
        * config.bfd:           Adjusted x86_64 target architecture 
detection
        * bfd.c:                        Add for new target "coff-x86-64"
                bfd_get_sign_extend:    Add target vector idents for 
pe-x86-64. and pei-x86-64
        * coff-x86_64.c:        Add new file for x86_64 (AMD64) coff 
support
        * libpei.h                              Adjustments for 
COFF_WITH_pex64
        * coffcode.h:                   Add for new target machine, 
architecture, signature, and internal
                                                                signature 
handler.
        * makefile.am:  Add new files to target-all and define make-rule 
for pex64igen.c
        * makefile.in:  Add new files to target-all and define make-rule 
for pex64igen.c
        * pe-x86_64.c:  Add for new target "pe-x86-64"
        * pei-x86_64.c: Add for new target "pei-x86-64"
        * peicode.h:            Adjusts for new targets
                coff_swap_filehdr_out:  set for this target to 
_bfd_pex64_only_swap_filehdr_out
                SIZEOF_IDATA4:                          define it as 8 
byte size for this target
                SIZEOF_IDATA5:                          define it as 8 
byte size for this target
                jump_table jtab:                        Add for AMD64MAGIC
                pe_ILF_build_a_bfd:             Adjusts for new size of 
SIZEOF_IDATA4 and SIZE_IDATA5
                pe_ILF_object_p:                        Add coff 
image-file signature to internal signature translation
        * pexxigen.c:           Adjust proper include of target 
coff-header and introduced target specific code
                COFF_WITH_pex64:        New macro for this target
                pe_print_idata: New dumping method for import section of 
PE+ files
        * target.c:             Add new target vectors declarations for 
x86_64 coff targets

Regards,
 i.A. Kai Tietz


[-- Attachment #2: binutils-2.17.pex-64.060913_bfd.diff --]
[-- Type: application/octet-stream, Size: 52697 bytes --]

diff -rNbu binutils_060913_org/bfd/ChangeLog binutils_060913/bfd/ChangeLog
--- binutils_060913_org/bfd/ChangeLog	2006-09-13 00:10:31.000000000 +0200
+++ binutils_060913/bfd/ChangeLog	2006-09-13 11:04:28.000000000 +0200
@@ -1,3 +1,29 @@
+2006-09-13	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* configure.in:	Added new target-vectors x86_64coff_vec, x86_64pe_vec, and x86_64pei_vec
+	* config.bfd:		Adjusted x86_64 target architecture detection
+	* bfd.c:			Add for new target "coff-x86-64"
+		bfd_get_sign_extend:	Add target vector idents for pe-x86-64. and pei-x86-64
+	* coff-x86_64.c: 	Add new file for x86_64 (AMD64) coff support
+	* libpei.h				Adjustments for COFF_WITH_pex64
+	* coffcode.h:			Add for new target machine, architecture, signature, and internal
+								signature handler.
+	* makefile.am:	Add new files to target-all and define make-rule for pex64igen.c
+	* makefile.in:	Add new files to target-all and define make-rule for pex64igen.c
+	* pe-x86_64.c:	Add for new target "pe-x86-64"
+	* pei-x86_64.c:	Add for new target "pei-x86-64"
+	* peicode.h:		Adjusts for new targets
+		coff_swap_filehdr_out:	set for this target to _bfd_pex64_only_swap_filehdr_out
+		SIZEOF_IDATA4:				define it as 8 byte size for this target
+		SIZEOF_IDATA5:				define it as 8 byte size for this target
+		jump_table jtab:			Add for AMD64MAGIC
+		pe_ILF_build_a_bfd:		Adjusts for new size of SIZEOF_IDATA4 and SIZE_IDATA5
+		pe_ILF_object_p:			Add coff image-file signature to internal signature translation
+	* pexxigen.c:		Adjust proper include of target coff-header and introduced target specific code
+		COFF_WITH_pex64:	New macro for this target
+		pe_print_idata:	New dumping method for import section of PE+ files
+	* target.c:		Add new target vectors declarations for x86_64 coff targets
+	
 2006-09-12  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR ld/3197
diff -rNbu binutils_060913_org/bfd/Makefile.am binutils_060913/bfd/Makefile.am
--- binutils_060913_org/bfd/Makefile.am	2006-08-21 10:12:44.000000000 +0200
+++ binutils_060913/bfd/Makefile.am	2006-09-11 11:47:44.000000000 +0200
@@ -559,7 +559,11 @@
 	mmo.lo \
 	nlm32-alpha.lo \
 	nlm64.lo \
-	pepigen.lo
+	coff-x86_64.lo \
+	pe-x86_64.lo \
+	pei-x86_64.lo \
+	pepigen.lo \
+	pex64igen.lo
 
 BFD64_BACKENDS_CFILES = \
 	aix5ppc-core.c \
@@ -582,7 +586,10 @@
 	elf64.c \
 	mmo.c \
 	nlm32-alpha.c \
-	nlm64.c
+	nlm64.c \
+	coff-x86_64.c \
+	pe-x86_64.c \
+	pei-x86_64.c
 
 OPTIONAL_BACKENDS = \
 	aix386-core.lo \
@@ -632,7 +639,7 @@
 	$(OPTIONAL_BACKENDS_CFILES)
 
 BUILD_CFILES = \
-	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c
+	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c pex64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 
@@ -790,6 +797,11 @@
 	sed -e s/XX/pep/g < $(srcdir)/peXXigen.c > pepigen.new
 	mv -f pepigen.new pepigen.c
 
+pex64igen.c: peXXigen.c
+	rm -f pex64igen.c
+	sed -e s/XX/pex64/g < $(srcdir)/peXXigen.c > pex64igen.new
+	mv -f pex64igen.new pex64igen.c
+
 BFD_H_DEPS= $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h
 LOCAL_H_DEPS= libbfd.h sysdep.h config.h
 $(BFD32_LIBS) \
@@ -1852,4 +1864,7 @@
 pepigen.lo: pepigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/ia64.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
+pex64igen.lo: pex64igen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+  $(INCDIR)/coff/internal.h $(INCDIR)/coff/x86_64.h $(INCDIR)/coff/external.h \
+  $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
 # IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff -rNbu binutils_060913_org/bfd/Makefile.in binutils_060913/bfd/Makefile.in
--- binutils_060913_org/bfd/Makefile.in	2006-08-21 10:12:44.000000000 +0200
+++ binutils_060913/bfd/Makefile.in	2006-09-11 13:21:24.000000000 +0200
@@ -792,7 +792,11 @@
 	mmo.lo \
 	nlm32-alpha.lo \
 	nlm64.lo \
-	pepigen.lo
+	coff-x86_64.lo \
+	pe-x86_64.lo \
+	pei-x86_64.lo \
+	pepigen.lo \
+	pex64igen.lo
 
 BFD64_BACKENDS_CFILES = \
 	aix5ppc-core.c \
@@ -815,7 +819,10 @@
 	elf64.c \
 	mmo.c \
 	nlm32-alpha.c \
-	nlm64.c
+	nlm64.c \
+	coff-x86_64.c \
+	pe-x86_64.c \
+	pei-x86_64.c
 
 OPTIONAL_BACKENDS = \
 	aix386-core.lo \
@@ -866,7 +873,7 @@
 	$(OPTIONAL_BACKENDS_CFILES)
 
 BUILD_CFILES = \
-	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c
+	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c pex64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 SOURCE_HFILES = \
@@ -1364,6 +1371,11 @@
 	sed -e s/XX/pe/g < $(srcdir)/peXXigen.c > peigen.new
 	mv -f peigen.new peigen.c
 
+pex64igen.c : peXXigen.c
+	rm -f pex64igen.c
+	sed -e s/XX/pex64/g < $(srcdir)/peXXigen.c > pex64igen.new
+	mv -f pex64igen.new pex64igen.c
+	
 pepigen.c : peXXigen.c
 	rm -f pepigen.c
 	sed -e s/XX/pep/g < $(srcdir)/peXXigen.c > pepigen.new
@@ -2410,6 +2422,9 @@
 peigen.lo: peigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
+pex64igen.lo: pex64igen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+  $(INCDIR)/coff/internal.h $(INCDIR)/coff/x86_64.h $(INCDIR)/coff/external.h \
+  $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
 pepigen.lo: pepigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/ia64.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
diff -rNbu binutils_060913_org/bfd/coff-x86_64.c binutils_060913/bfd/coff-x86_64.c
--- binutils_060913_org/bfd/coff-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/bfd/coff-x86_64.c	2006-09-06 12:28:12.000000000 +0200
@@ -0,0 +1,751 @@
+/* BFD back-end for AMD 64 COFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+#ifndef COFF_WITH_pex64
+#define COFF_WITH_pex64
+#endif
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#include "coff/x86_64.h"
+#include "coff/internal.h"
+#include "coff/pe.h"
+#include "libcoff.h"
+
+#define BADMAG(x) AMD64BADMAG(x)
+
+#ifdef COFF_WITH_pex64
+# undef AOUTSZ
+# define AOUTSZ		PEPAOUTSZ
+# define PEAOUTHDR	PEPAOUTHDR
+#endif
+
+static bfd_reloc_status_type coff_amd64_reloc(bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **);
+static reloc_howto_type *coff_amd64_rtype_to_howto(bfd *, asection *, struct internal_reloc *,struct coff_link_hash_entry *, struct internal_syment *,bfd_vma *);
+static reloc_howto_type *coff_amd64_reloc_type_lookup(bfd *, bfd_reloc_code_real_type);
+
+#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 AMD 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 relocatable 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_amd64_reloc(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 !defined(COFF_WITH_PE)
+  if(output_bfd == (bfd *) NULL)
+    return bfd_reloc_continue;
+#endif
+
+  if(bfd_is_com_section (symbol->section)) {
+#if !defined(COFF_WITH_PE)
+     /* 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
+      /* In PE mode, we do not offset the common symbol.  */
+      diff = reloc_entry->addend;
+#endif
+    }
+  else
+    {
+      /* For some reason bfd_perform_relocation always effectively
+	 ignores the addend for a COFF target when producing
+	 relocatable output.  This seems to be always wrong for 386
+	 COFF, so we handle the addend here instead.  */
+#if defined(COFF_WITH_PE)
+      if(output_bfd == (bfd *) NULL)
+	{
+	  reloc_howto_type *howto = reloc_entry->howto;
+
+	  /* Although PC relative relocations are very similar between
+	     PE and non-PE formats, but they are off by 1 << howto->size
+	     bytes. For the external relocation, PE is very different
+	     from others. See md_apply_fix3 () in gas/config/tc-amd64.c.
+	     When we link PE and non-PE object files together to
+	     generate a non-PE executable, we have to compensate it
+	     here.  */
+	  if(howto->pc_relative && howto->pcrel_offset)
+	    diff = -(1 << howto->size);
+	  else if(symbol->flags & BSF_WEAK)
+	    diff = reloc_entry->addend - symbol->value;
+	  else
+	    diff = -reloc_entry->addend;
+	}
+      else
+#endif
+	diff = reloc_entry->addend;
+    }
+
+#if defined(COFF_WITH_PE)
+  /* FIXME: How should this case be handled?  */
+  if(reloc_entry->howto->type == R_AMD64_IMAGEBASE
+      && output_bfd!=NULL
+      && bfd_get_flavour(output_bfd) == bfd_target_coff_flavour)
+    diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
+#endif
+
+#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;
+	  case 4:
+	    {
+	      long long x = bfd_get_64 (abfd, addr);
+	      DOIT (x);
+	      bfd_put_64 (abfd, (bfd_vma) x, addr);
+	    }
+	    break;
+
+	  default:
+	    abort ();
+	  }
+      }
+
+  /* Now let bfd_perform_relocation finish everything up.  */
+  return bfd_reloc_continue;
+}
+
+#if defined(COFF_WITH_PE)
+/* Return TRUE if this relocation should appear in the output .reloc
+   section.  */
+
+static bfd_boolean in_reloc_p(bfd *, reloc_howto_type *);
+
+static bfd_boolean in_reloc_p(bfd *abfd ATTRIBUTE_UNUSED,reloc_howto_type *howto)
+{
+  return ! howto->pc_relative && howto->type!=R_AMD64_IMAGEBASE;
+}
+#endif /* COFF_WITH_PE */
+
+#ifndef PCRELOFFSET
+#define PCRELOFFSET TRUE
+#endif
+
+static reloc_howto_type howto_table[] =
+{
+  EMPTY_HOWTO (0),
+  HOWTO (R_AMD64_DIR64,		/* type  1*/
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long, 4 = long long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "R_X86_64_64",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffffffffffffll,		/* src_mask */
+	 0xffffffffffffffffll,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+  HOWTO (R_AMD64_DIR32,		/* type 2 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "R_X86_64_32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+  /* PE IMAGE_REL_AMD64_ADDR32NB relocation (3).	*/
+  HOWTO (R_AMD64_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_amd64_reloc,	/* special_function */
+	 "rva32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+  /* 32-bit longword PC relative relocation (4).  */
+  HOWTO (R_AMD64_PCRLONG,		/* type 4 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+
+ HOWTO (R_AMD64_PCRLONG_1,		/* type 5 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+1",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_2,		/* type 6 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+2",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_3,		/* type 7 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+3",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_4,		/* type 8 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+4",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_5,		/* type 9 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+5",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  EMPTY_HOWTO (10), // R_AMD64_SECTION 10
+#if defined(COFF_WITH_PE)
+  /* 32-bit longword section relative relocation (11).  */
+  HOWTO (R_AMD64_SECREL,		/* 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_amd64_reloc,	/* special_function */
+	 "secrel32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+#else
+  EMPTY_HOWTO (11),
+#endif
+  EMPTY_HOWTO (12),
+  EMPTY_HOWTO (13),
+#ifndef DONT_EXTEND_AMD64
+  HOWTO (R_AMD64_PCRQUAD,
+         0,                     /* rightshift */
+         4,                     /* size (0 = byte, 1 = short, 2 = long) */
+         64,                    /* bitsize */
+         TRUE,                  /* pc_relative */
+         0,                     /* bitpos */
+         complain_overflow_signed, /* complain_on_overflow */
+         coff_amd64_reloc,      /* special_function */
+         "R_X86_64_PC64",       /* name */
+         TRUE,                  /* partial_inplace */
+         0xffffffffffffffffll,  /* src_mask */
+         0xffffffffffffffffll,  /* dst_mask */
+         PCRELOFFSET),           /* pcrel_offset */
+#else
+  EMPTY_HOWTO (14),
+#endif
+  /* Byte relocation (15).  */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_8",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0x000000ff,		/* src_mask */
+	 0x000000ff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 16-bit word relocation (16).  */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_16",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 32-bit longword relocation (17).	*/
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_32S",			/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* Byte PC relative relocation (18).	 */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC8",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x000000ff,		/* src_mask */
+	 0x000000ff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 16-bit word PC relative relocation (19).	*/
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 32-bit longword PC relative relocation (20).  */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC32",	/* 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 I386 1			/* Customize coffcode.h */
+#define AMD64 1
+#define RTYPE2HOWTO(cache_ptr, dst)					\
+  ((cache_ptr)->howto =							\
+   ((dst)->r_type < sizeof (howto_table) / sizeof (howto_table[0])	\
+    ? howto_table + (dst)->r_type					\
+    : NULL))
+
+/* For 386 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.  For normal AMD64 COFF, we
+   can use the generic relocate_section routine.  For PE, we need our
+   own routine.  */
+
+#if !defined(COFF_WITH_PE)
+
+#define coff_relocate_section _bfd_coff_generic_relocate_section
+
+#else /* COFF_WITH_PE */
+
+/* The PE relocate section routine.  The only difference between this
+   and the regular routine is that we don't want to do anything for a
+   relocatable link.  */
+
+static bfd_boolean coff_pe_amd64_relocate_section(bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,struct internal_reloc *, struct internal_syment *, asection **);
+
+static bfd_boolean
+coff_pe_amd64_relocate_section(bfd *output_bfd,struct bfd_link_info *info,bfd *input_bfd,asection *input_section,bfd_byte *contents,struct internal_reloc *relocs,struct internal_syment *syms,asection **sections)
+{
+  if(info->relocatable)
+    return TRUE;
+
+  return _bfd_coff_generic_relocate_section(output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
+}
+
+#define coff_relocate_section coff_pe_amd64_relocate_section
+
+#endif /* COFF_WITH_PE */
+
+/* Convert an rtype to howto for the COFF backend linker.  */
+
+static reloc_howto_type *
+coff_amd64_rtype_to_howto(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;
+
+  if(rel->r_type > sizeof (howto_table) / sizeof (howto_table[0])) {
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
+  if(rel->r_type>=R_AMD64_PCRLONG_1 && rel->r_type<=R_AMD64_PCRLONG_5) {
+	  rel->r_vaddr+=(bfd_vma)(rel->r_type-R_AMD64_PCRLONG);
+	  rel->r_type=R_AMD64_PCRLONG;
+  }
+  howto = howto_table + rel->r_type;
+
+#if defined(COFF_WITH_PE)
+  /* Cancel out code in _bfd_coff_generic_relocate_section.  */
+  *addendp = 0;
+#endif
+
+  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);
+
+#if !defined(COFF_WITH_PE)
+      /* I think we *do* want to bypass this.  If we don't, I have
+	 seen some data parameters get the wrong relocation 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;
+#endif
+    }
+
+#if !defined(COFF_WITH_PE)
+  /* If the output symbol is common (in which case this must be a
+     relocatable 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;
+#endif
+
+#if defined(COFF_WITH_PE)
+  if(howto->pc_relative)
+    {
+      *addendp -= 4;
+
+      /* If the symbol is defined, then the generic code is going to
+         add back the symbol value in order to cancel out an
+         adjustment it made to the addend.  However, we set the addend
+         to 0 at the start of this function.  We need to adjust here,
+         to avoid the adjustment the generic code will make.  FIXME:
+         This is getting a bit hackish.  */
+      if(sym!=NULL && sym->n_scnum!=0)
+	*addendp -= sym->n_value;
+    }
+
+  if(rel->r_type == R_AMD64_IMAGEBASE && (bfd_get_flavour(sec->output_section->owner) == bfd_target_coff_flavour)) {
+      *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
+  }
+
+  if(rel->r_type == R_AMD64_SECREL) {
+      bfd_vma osect_vma;
+
+      if(h && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak))
+	osect_vma = h->root.u.def.section->output_section->vma;
+      else {
+	  asection *sec;
+	  int i;
+
+	  /* Sigh, the only way to get the section to offset against
+	     is to find it the hard way.  */
+
+	  for (sec = abfd->sections, i = 1; i < sym->n_scnum; i++)
+	    sec = sec->next;
+
+	  osect_vma = sec->output_section->vma;
+	}
+
+      *addendp -= osect_vma;
+    }
+#endif
+
+  return howto;
+}
+
+#define coff_bfd_reloc_type_lookup coff_amd64_reloc_type_lookup
+
+static reloc_howto_type *
+coff_amd64_reloc_type_lookup(bfd *abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)
+{
+  switch (code) {
+    case BFD_RELOC_RVA:
+      return howto_table + R_AMD64_IMAGEBASE;
+    case BFD_RELOC_32:
+      return howto_table + R_AMD64_DIR32;
+    case BFD_RELOC_64:
+      return howto_table + R_AMD64_DIR64;
+    case BFD_RELOC_64_PCREL:
+#ifndef DONT_EXTEND_AMD64
+      return howto_table + R_AMD64_PCRQUAD;
+#else
+	/* Fall trough */
+#endif
+    case BFD_RELOC_32_PCREL:
+      return howto_table + R_AMD64_PCRLONG;
+    case BFD_RELOC_X86_64_32S:
+      return howto_table + R_RELLONG;
+    case BFD_RELOC_16:
+      return howto_table + R_RELWORD;
+    case BFD_RELOC_16_PCREL:
+      return howto_table + R_PCRWORD;
+    case BFD_RELOC_8:
+      return howto_table + R_RELBYTE;
+    case BFD_RELOC_8_PCREL:
+      return howto_table + R_PCRBYTE;
+#if defined(COFF_WITH_PE)
+    case BFD_RELOC_32_SECREL:
+      return howto_table + R_AMD64_SECREL;
+#endif
+    default:
+      BFD_FAIL ();
+      return 0;
+    }
+}
+
+#define coff_rtype_to_howto coff_amd64_rtype_to_howto
+
+#ifdef TARGET_UNDERSCORE
+
+/* If amd64 gcc uses underscores for symbol names, then it does not use
+   a leading dot for local labels, so if TARGET_UNDERSCORE is defined
+   we treat all symbols starting with L as local.  */
+
+static bfd_boolean coff_amd64_is_local_label_name(bfd *, const char *);
+
+static bfd_boolean coff_amd64_is_local_label_name(bfd *abfd,const char *name)
+{
+  if(name[0] == 'L')
+    return TRUE;
+
+  return _bfd_coff_is_local_label_name (abfd, name);
+}
+
+#define coff_bfd_is_local_label_name coff_amd64_is_local_label_name
+
+#endif /* TARGET_UNDERSCORE */
+
+#include "coffcode.h"
+
+#ifdef PE
+#define amd64coff_object_p pe_bfd_object_p
+#else
+#define amd64coff_object_p coff_object_p
+#endif
+
+const bfd_target
+#ifdef TARGET_SYM
+  TARGET_SYM =
+#else
+  x86_64coff_vec =
+#endif
+{
+#ifdef TARGET_NAME
+  TARGET_NAME,
+#else
+ "coff-x86-64",			/* 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 | D_PAGED),
+
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
+#if defined(COFF_WITH_PE)
+   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY
+#endif
+   | SEC_CODE | SEC_DATA),
+
+#ifdef TARGET_UNDERSCORE
+  TARGET_UNDERSCORE,		/* leading underscore */
+#else
+  0,				/* leading underscore */
+#endif
+  '/',				/* 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, amd64coff_object_p, /* bfd_check_format */
+       bfd_generic_archive_p, amd64coff_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 -rNbu binutils_060913_org/bfd/coffcode.h binutils_060913/bfd/coffcode.h
--- binutils_060913_org/bfd/coffcode.h	2006-09-05 20:56:50.000000000 +0200
+++ binutils_060913/bfd/coffcode.h	2006-09-11 13:28:46.000000000 +0200
@@ -1887,6 +1887,12 @@
       arch = bfd_arch_i386;
       break;
 #endif
+#ifdef AMD64MAGIC
+	case AMD64MAGIC:
+		arch=bfd_arch_i386;
+		machine=bfd_mach_x86_64;
+		break;
+#endif
 #ifdef IA64MAGIC
     case IA64MAGIC:
       arch = bfd_arch_ia64;
@@ -2721,13 +2727,18 @@
       return TRUE;
 #endif
 
-#ifdef I386MAGIC
+#if defined(I386MAGIC) || defined(AMD64MAGIC)
     case bfd_arch_i386:
+#ifdef I386MAGIC
       *magicp = I386MAGIC;
+#endif
 #ifdef LYNXOS
       /* Just overwrite the usual value if we're doing Lynx.  */
       *magicp = LYNXCOFFMAGIC;
 #endif
+#ifdef AMD64MAGIC
+	  *magicp = AMD64MAGIC;
+#endif
       return TRUE;
 #endif
 
@@ -3759,6 +3770,7 @@
     internal_f.f_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
 #endif
 
+#ifndef COFF_WITH_pex64
 #ifdef COFF_WITH_PE
   internal_f.f_flags |= IMAGE_FILE_32BIT_MACHINE;
 #else
@@ -3767,6 +3779,7 @@
   else
     internal_f.f_flags |= F_AR32W;
 #endif
+#endif
 
 #ifdef TI_TARGET_ID
   /* Target id is used in TI COFF v1 and later; COFF0 won't use this field,
@@ -3863,7 +3876,11 @@
 #if defined(LYNXOS)
     internal_a.magic = LYNXCOFFMAGIC;
 #else  /* LYNXOS */
+#ifdef AMD64
+	internal_a.magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+#else
     internal_a.magic = ZMAGIC;
+#endif
 #endif /* LYNXOS */
 #endif /* I386 */
 
diff -rNbu binutils_060913_org/bfd/config.bfd binutils_060913/bfd/config.bfd
--- binutils_060913_org/bfd/config.bfd	2006-08-21 10:12:44.000000000 +0200
+++ binutils_060913/bfd/config.bfd	2006-09-11 11:25:34.000000000 +0200
@@ -98,7 +98,7 @@
 strongarm*)	 targ_archs=bfd_arm_arch ;;
 thumb*)		 targ_archs=bfd_arm_arch ;;
 v850*)		 targ_archs=bfd_v850_arch ;;
-x86_64)		 targ_archs=bfd_i386_arch ;;
+x86_64*)		 targ_archs=bfd_i386_arch ;;
 xscale*)	 targ_archs=bfd_arm_arch ;;
 xtensa*)	 targ_archs=bfd_xtensa_arch ;;
 z80|r800)	 targ_archs=bfd_z80_arch ;;
@@ -578,6 +578,12 @@
     targ_selvecs="bfd_elf32_i386_vec i386linux_vec bfd_efi_app_ia32_vec"
     want64=true
     ;;
+  x86_64-*-mingw64*)
+    targ_defvec=x86_64pe_vec
+    targ_selvecs="x86_64pe_vec x86_64pei_vec x86_64coff_vec  bfd_elf64_x86_64_vec"
+    want64=true
+    targ_underscore=yes
+    ;;
 #endif
   i[3-7]86-*-lynxos*)
     targ_defvec=bfd_elf32_i386_vec
diff -rNbu binutils_060913_org/bfd/configure binutils_060913/bfd/configure
--- binutils_060913_org/bfd/configure	2006-08-21 10:12:44.000000000 +0200
+++ binutils_060913/bfd/configure	2006-09-11 11:31:56.000000000 +0200
@@ -4086,7 +4086,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -4113,6 +4113,9 @@
       ;;
     *64-bit*)
       case $host in
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
@@ -10949,6 +10952,7 @@
     i386aout_vec)		tb="$tb i386aout.lo aout32.lo" ;;
     i386bsd_vec)		tb="$tb i386bsd.lo aout32.lo" ;;
     i386coff_vec)		tb="$tb coff-i386.lo cofflink.lo" ;;
+    x86_64coff_vec)		tb="$tb coff-x86_64.lo cofflink.lo"; target_size=64 ;;
     i386dynix_vec)		tb="$tb i386dynix.lo aout32.lo" ;;
     i386freebsd_vec)		tb="$tb i386freebsd.lo aout32.lo" ;;
     i386linux_vec)		tb="$tb i386linux.lo aout32.lo" ;;
@@ -10959,7 +10963,9 @@
     i386netbsd_vec)		tb="$tb i386netbsd.lo aout32.lo" ;;
     i386os9k_vec)		tb="$tb i386os9k.lo aout32.lo" ;;
     i386pe_vec)			tb="$tb pe-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pe_vec)			tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i386pei_vec)		tb="$tb pei-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pei_vec)		tb="$tb pei-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i860coff_vec)		tb="$tb coff-i860.lo cofflink.lo" ;;
     icoff_big_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
     icoff_little_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
diff -rNbu binutils_060913_org/bfd/configure.in binutils_060913/bfd/configure.in
--- binutils_060913_org/bfd/configure.in	2006-08-21 10:12:45.000000000 +0200
+++ binutils_060913/bfd/configure.in	2006-09-11 11:37:22.000000000 +0200
@@ -739,6 +739,7 @@
     i386aout_vec)		tb="$tb i386aout.lo aout32.lo" ;;
     i386bsd_vec)		tb="$tb i386bsd.lo aout32.lo" ;;
     i386coff_vec)		tb="$tb coff-i386.lo cofflink.lo" ;;
+    x86_64coff_vec)		tb="$tb coff-x86_64.lo cofflink.lo"; target_size=64 ;;
     i386dynix_vec)		tb="$tb i386dynix.lo aout32.lo" ;;
     i386freebsd_vec)		tb="$tb i386freebsd.lo aout32.lo" ;;
     i386linux_vec)		tb="$tb i386linux.lo aout32.lo" ;;
@@ -749,7 +750,9 @@
     i386netbsd_vec)		tb="$tb i386netbsd.lo aout32.lo" ;;
     i386os9k_vec)		tb="$tb i386os9k.lo aout32.lo" ;;
     i386pe_vec)			tb="$tb pe-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pe_vec)			tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i386pei_vec)		tb="$tb pei-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pei_vec)		tb="$tb pei-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i860coff_vec)		tb="$tb coff-i860.lo cofflink.lo" ;;
     icoff_big_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
     icoff_little_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
diff -rNbu binutils_060913_org/bfd/libpei.h binutils_060913/bfd/libpei.h
--- binutils_060913_org/bfd/libpei.h	2005-05-04 17:53:35.000000000 +0200
+++ binutils_060913/bfd/libpei.h	2006-09-11 11:42:22.000000000 +0200
@@ -204,6 +204,38 @@
 #define PUT_SCNHDR_LNNOPTR H_PUT_32
 #endif
 
+#ifdef COFF_WITH_pex64
+#define GET_OPTHDR_IMAGE_BASE H_GET_64
+#define PUT_OPTHDR_IMAGE_BASE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_RESERVE H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_RESERVE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_COMMIT H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_COMMIT H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_RESERVE H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_RESERVE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_COMMIT H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_COMMIT H_PUT_64
+#define GET_PDATA_ENTRY bfd_get_32
+
+#define _bfd_XX_bfd_copy_private_bfd_data_common	_bfd_pex64_bfd_copy_private_bfd_data_common
+#define _bfd_XX_bfd_copy_private_section_data		_bfd_pex64_bfd_copy_private_section_data
+#define _bfd_XX_get_symbol_info				_bfd_pex64_get_symbol_info
+#define _bfd_XX_only_swap_filehdr_out			_bfd_pex64_only_swap_filehdr_out
+#define _bfd_XX_print_private_bfd_data_common		_bfd_pex64_print_private_bfd_data_common
+#define _bfd_XXi_final_link_postscript			_bfd_pex64i_final_link_postscript
+#define _bfd_XXi_final_link_postscript			_bfd_pex64i_final_link_postscript
+#define _bfd_XXi_only_swap_filehdr_out			_bfd_pex64i_only_swap_filehdr_out
+#define _bfd_XXi_swap_aouthdr_in			_bfd_pex64i_swap_aouthdr_in
+#define _bfd_XXi_swap_aouthdr_out			_bfd_pex64i_swap_aouthdr_out
+#define _bfd_XXi_swap_aux_in				_bfd_pex64i_swap_aux_in
+#define _bfd_XXi_swap_aux_out				_bfd_pex64i_swap_aux_out
+#define _bfd_XXi_swap_lineno_in				_bfd_pex64i_swap_lineno_in
+#define _bfd_XXi_swap_lineno_out			_bfd_pex64i_swap_lineno_out
+#define _bfd_XXi_swap_scnhdr_out			_bfd_pex64i_swap_scnhdr_out
+#define _bfd_XXi_swap_sym_in				_bfd_pex64i_swap_sym_in
+#define _bfd_XXi_swap_sym_out				_bfd_pex64i_swap_sym_out
+
+#else /* !COFF_WITH_pex64 */
 #ifdef COFF_WITH_pep
 
 #define GET_OPTHDR_IMAGE_BASE H_GET_64
@@ -269,6 +301,7 @@
 #define _bfd_XXi_swap_sym_out				_bfd_pei_swap_sym_out
 
 #endif /* !COFF_WITH_pep */
+#endif /* !COFF_WITG_pex64 */
 
 /* Macro: Returns true if the bfd is a PE executable as opposed to a PE object file.  */
 #define bfd_pe_executable_p(abfd) \
diff -rNbu binutils_060913_org/bfd/pe-x86_64.c binutils_060913/bfd/pe-x86_64.c
--- binutils_060913_org/bfd/pe-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/bfd/pe-x86_64.c	2006-09-06 12:23:54.000000000 +0200
@@ -0,0 +1,54 @@
+/* BFD back-end for Intel/AMD x86_64 PECOFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_SYM 		x86_64pe_vec
+#define TARGET_NAME 		"pe-x86-64"
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+#define PCRELOFFSET 		TRUE
+#define TARGET_UNDERSCORE 	'_'
+#define COFF_LONG_SECTION_NAMES
+#define COFF_SUPPORT_GNU_LINKONCE
+#define COFF_LONG_FILENAMES
+
+#define COFF_SECTION_ALIGNMENT_ENTRIES \
+{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
+
+#include "coff-x86_64.c"
diff -rNbu binutils_060913_org/bfd/peXXigen.c binutils_060913/bfd/peXXigen.c
--- binutils_060913_org/bfd/peXXigen.c	2006-07-24 18:51:26.000000000 +0200
+++ binutils_060913/bfd/peXXigen.c	2006-09-11 13:29:26.000000000 +0200
@@ -52,7 +52,7 @@
    on this code has a chance of getting something accomplished without
    wasting too much time.  */
 
-/* This expands into COFF_WITH_pe or COFF_WITH_pep depending on whether
+/* This expands into COFF_WITH_pe, COFF_WITH_pep, or COFF_WITH_pex64 depending on whether
    we're compiling for straight PE or PE+.  */
 #define COFF_WITH_XX
 
@@ -67,17 +67,21 @@
    within PE/PEI, so we get them from there.  FIXME: The lack of
    variance is an assumption which may prove to be incorrect if new
    PE/PEI targets are created.  */
-#ifdef COFF_WITH_pep
-# include "coff/ia64.h"
+#ifdef COFF_WITH_pex64
+# include "coff/x86_64.h"
 #else
+# ifdef COFF_WITH_pep
+#  include "coff/ia64.h"
+# else
 # include "coff/i386.h"
+# endif
 #endif
 
 #include "coff/pe.h"
 #include "libcoff.h"
 #include "libpei.h"
 
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
 # undef AOUTSZ
 # define AOUTSZ		PEPAOUTSZ
 # define PEAOUTHDR	PEPAOUTHDR
@@ -399,7 +403,7 @@
   aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry);
   aouthdr_int->text_start =
     GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   aouthdr_int->data_start =
     GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start);
@@ -455,7 +459,7 @@
   if (aouthdr_int->entry)
     {
       aouthdr_int->entry += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_int->entry &= 0xffffffff;
 #endif
     }
@@ -463,12 +467,12 @@
   if (aouthdr_int->tsize)
     {
       aouthdr_int->text_start += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_int->text_start &= 0xffffffff;
 #endif
     }
 
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   if (aouthdr_int->dsize)
     {
@@ -548,7 +552,7 @@
   if (aouthdr_in->tsize)
     {
       aouthdr_in->text_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->text_start &= 0xffffffff;
 #endif
     }
@@ -556,7 +560,7 @@
   if (aouthdr_in->dsize)
     {
       aouthdr_in->data_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->data_start &= 0xffffffff;
 #endif
     }
@@ -564,7 +568,7 @@
   if (aouthdr_in->entry)
     {
       aouthdr_in->entry -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->entry &= 0xffffffff;
 #endif
     }
@@ -661,7 +665,7 @@
   PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
 			  aouthdr_out->standard.text_start);
 
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
 			  aouthdr_out->standard.data_start);
@@ -1262,6 +1266,35 @@
 	    }
 
 	  /* Print HintName vector entries.  */
+#ifdef COFF_WITH_pex64
+	  for (j = 0; j < datasize; j += 8)
+	    {
+			unsigned long member = bfd_get_32(abfd,data+idx+j);
+			unsigned long member_high = bfd_get_32(abfd,data+idx+j+4);
+			if(!member && !member_high) break;
+	      if (member_high & 0x80000000)
+		fprintf (file, "\t%lx%08lx\t %4lx%08lx  <none>",
+			 member_high,member, member_high & 0x7fffffff,member);
+	      else
+		{
+		  int ordinal;
+		  char *member_name;
+
+		  ordinal = bfd_get_16 (abfd, data + member - adj);
+		  member_name = (char *) data + member - adj + 2;
+		  fprintf (file, "\t%04lx\t %4d  %s",member, ordinal, member_name);
+		  }
+
+	      /* If the time stamp is not zero, the import address
+		 table holds actual addresses.  */
+	      if (time_stamp != 0
+		  && first_thunk != 0
+		  && first_thunk != hint_addr)
+		fprintf (file, "\t%04lx",
+			 (long) bfd_get_32 (abfd, ft_data + ft_idx + j));
+	      fprintf (file, "\n");
+	    }
+#else
 	  for (j = 0; j < datasize; j += 4)
 	    {
 	      unsigned long member = bfd_get_32 (abfd, data + idx + j);
@@ -1294,6 +1327,7 @@
 
 	      fprintf (file, "\n");
 	    }
+#endif /* !defined(COFF_WITH_pex64) */
 
 	  if (ft_allocated)
 	    free (ft_data);
@@ -1534,7 +1568,7 @@
 static bfd_boolean
 pe_print_pdata (bfd * abfd, void * vfile)
 {
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
 # define PDATA_ROW_SIZE	(3*8)
 #else
 # define PDATA_ROW_SIZE	(5*4)
@@ -1560,7 +1594,7 @@
 
   fprintf (file,
 	   _("\nThe Function Table (interpreted .pdata section contents)\n"));
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   fprintf (file,
 	   _(" vma:\t\t\tBegin Address    End Address      Unwind Info\n"));
 #else
@@ -1614,7 +1648,7 @@
       fprintf_vma (file, begin_addr); fputc (' ', file);
       fprintf_vma (file, end_addr); fputc (' ', file);
       fprintf_vma (file, eh_handler);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
       fputc (' ', file);
       fprintf_vma (file, eh_data); fputc (' ', file);
       fprintf_vma (file, prolog_end_addr);
diff -rNbu binutils_060913_org/bfd/pei-x86_64.c binutils_060913/bfd/pei-x86_64.c
--- binutils_060913_org/bfd/pei-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/bfd/pei-x86_64.c	2006-09-06 12:23:58.000000000 +0200
@@ -0,0 +1,55 @@
+/* BFD back-end for Intel 386 PE IMAGE COFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_SYM 		x86_64pei_vec
+#define TARGET_NAME 		"pei-x86-64"
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+#define PCRELOFFSET 		TRUE
+#define TARGET_UNDERSCORE 	'_'
+#define COFF_LONG_SECTION_NAMES
+#define COFF_SUPPORT_GNU_LINKONCE
+#define COFF_LONG_FILENAMES
+
+#define COFF_SECTION_ALIGNMENT_ENTRIES \
+{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
+
+#include "coff-x86_64.c"
diff -rNbu binutils_060913_org/bfd/peicode.h binutils_060913/bfd/peicode.h
--- binutils_060913_org/bfd/peicode.h	2005-05-04 17:53:37.000000000 +0200
+++ binutils_060913/bfd/peicode.h	2006-09-11 11:58:24.000000000 +0200
@@ -183,7 +183,15 @@
 #ifdef COFF_IMAGE_WITH_PE
 # define coff_swap_filehdr_out _bfd_XXi_only_swap_filehdr_out
 #else
+# ifdef COFF_WITH_pex64
+#  define coff_swap_filehdr_out _bfd_pex64_only_swap_filehdr_out
+# else
+#  ifdef COFF_WITH_pep
+#   define coff_swap_filehdr_out _bfd_pep_only_swap_filehdr_out
+#  else
 # define coff_swap_filehdr_out _bfd_pe_only_swap_filehdr_out
+#  endif
+# endif
 #endif
 
 static void
@@ -217,7 +225,10 @@
   if (scnhdr_int->s_vaddr != 0)
     {
       scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
+      /* Do not cut upper 32 bit for 64 vma */
+#ifndef COFF_WITH_pex64
       scnhdr_int->s_vaddr &= 0xffffffff;
+#endif
     }
 
 #ifndef COFF_NO_HACK_SCNHDR_SIZE
@@ -405,8 +416,16 @@
 					+ NUM_ILF_SECTIONS * 9 \
 					+ STRING_SIZE_SIZE)
 #define SIZEOF_IDATA2		(5 * 4)
+
+/* For PE+ idata4 & 5 have thumb size of 8 bytes ! */
+#ifndef COFF_WITH_pex64
 #define SIZEOF_IDATA4		(1 * 4)
 #define SIZEOF_IDATA5		(1 * 4)
+#else
+#define SIZEOF_IDATA4		(2 * 4)
+#define SIZEOF_IDATA5		(2 * 4)
+#endif
+
 #define SIZEOF_IDATA6		(2 + strlen (symbol_name) + 1 + 1)
 #define SIZEOF_IDATA7		(strlen (source_dll) + 1 + 1)
 #define SIZEOF_ILF_SECTIONS     (NUM_ILF_SECTIONS * sizeof (struct coff_section_tdata))
@@ -656,6 +675,13 @@
   },
 #endif
 
+#ifdef AMD64MAGIC
+  { AMD64MAGIC,
+  { 0xff,0x25,0x00,0x00,0x00,0x00,0x90,0x90 },
+  8,2
+  },
+#endif
+
 #ifdef  MC68MAGIC
   { MC68MAGIC, { /* XXX fill me in */ }, 0, 0 },
 #endif
@@ -830,8 +856,15 @@
 	/* XXX - treat as IMPORT_NAME ??? */
 	abort ();
 
+#ifndef COFF_WITH_pex64
       * (unsigned int *) id4->contents = ordinal | 0x80000000;
       * (unsigned int *) id5->contents = ordinal | 0x80000000;
+#else
+      * (unsigned int *) id4->contents = ordinal;
+	  ((unsigned int *) id4->contents)[1] = 0x80000000;
+      * (unsigned int *) id5->contents = ordinal;
+      ((unsigned int *) id5->contents)[1] = 0x80000000;
+#endif
     }
   else
     {
@@ -1071,6 +1104,12 @@
 #endif
       break;
 
+	case IMAGE_FILE_MACHINE_AMD64:
+#ifdef AMD64MAGIC
+		magic=AMD64MAGIC;
+#endif
+		break;
+
     case IMAGE_FILE_MACHINE_M68K:
 #ifdef MC68AGIC
       magic = MC68MAGIC;
diff -rNbu binutils_060913_org/bfd/targets.c binutils_060913/bfd/targets.c
--- binutils_060913_org/bfd/targets.c	2006-08-21 10:12:45.000000000 +0200
+++ binutils_060913/bfd/targets.c	2006-09-11 12:28:24.000000000 +0200
@@ -789,6 +789,9 @@
 extern const bfd_target we32kcoff_vec;
 extern const bfd_target z80coff_vec;
 extern const bfd_target z8kcoff_vec;
+extern const bfd_target x86_64pe_vec;
+extern const bfd_target x86_64pei_vec;
+extern const bfd_target x86_64coff_vec;
 
 /* These are always included.  */
 extern const bfd_target srec_vec;
@@ -1033,6 +1036,11 @@
 #if 0
 	&i386dynix_vec,
 #endif
+#ifdef BFD64
+	&x86_64coff_vec,
+	&x86_64pe_vec,
+	&x86_64pei_vec,
+#endif
 	&i386freebsd_vec,
 #if 0
 	/* Since a.out files lack decent magic numbers, no way to recognize

[-- Attachment #3: binutils-2.17.pex-64.060913_include.diff --]
[-- Type: application/octet-stream, Size: 7174 bytes --]

diff -rNbu binutils_060913_org/include/coff/ChangeLog binutils_060913/include/coff/ChangeLog
--- binutils_060913_org/include/coff/ChangeLog	2006-02-05 12:57:34.000000000 +0100
+++ binutils_060913/include/coff/ChangeLog	2006-09-11 18:52:20.000000000 +0200
@@ -1,3 +1,14 @@
+2006-09-11	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* external.h:	Add proper external_aouthdr64 structure (without data_start member)
+		AOUTHDRSZ64:	Set according structure size
+		AOUTHDR64:		As typedef of external_aouthdr64 structure
+	* internal.h:	Add relocation identifiers for coff
+	* pe.h:	Add define IMAGE_FILE_MACHINE_AMD64 the coff signature
+		PEPAOUTHDR:		Adjust structure to have proper size (using AOUTHDR64)
+		PEPAOUTSZ:		Calculated size of 240
+	* x86_64.h:	Coff information for x86_64 (AMD64)
+
 2006-02-05  Arnold Metselaar  <arnold.metselaar@planet.nl>
 
 	* internal.h: Add relocation number R_IMM24 for Z80.
diff -rNbu binutils_060913_org/include/coff/external.h binutils_060913/include/coff/external.h
--- binutils_060913_org/include/coff/external.h	2005-05-10 12:21:09.000000000 +0200
+++ binutils_060913/include/coff/external.h	2006-09-11 12:30:40.000000000 +0200
@@ -55,6 +55,20 @@
 
 #define AOUTHDRSZ 28
 #define AOUTSZ 28
+
+typedef struct external_aouthdr64
+  {
+    char magic[2];	/* type of file				*/
+    char vstamp[2];	/* version stamp			*/
+    char tsize[4];	/* text size in bytes, padded to FW bdry*/
+    char dsize[4];	/* initialized data "  "		*/
+    char bsize[4];	/* uninitialized data "   "		*/
+    char entry[4];	/* entry pt.				*/
+    char text_start[4];	/* base of text used for this file 	*/
+  }
+AOUTHDR64;
+#define AOUTHDRSZ64	24
+
 #endif
 
 #ifndef DO_NOT_DEFINE_SCNHDR
diff -rNbu binutils_060913_org/include/coff/internal.h binutils_060913/include/coff/internal.h
--- binutils_060913_org/include/coff/internal.h	2006-02-05 12:57:34.000000000 +0100
+++ binutils_060913/include/coff/internal.h	2006-09-11 12:32:16.000000000 +0200
@@ -604,6 +604,24 @@
   unsigned long r_offset;	/* Used by Alpha ECOFF, SPARC, others */
 };
 
+/* X86-64 relocations */
+#define R_AMD64_ABS 0 /* Reference is absolute, no relocation is necessary */
+#define R_AMD64_DIR64	1 /* 64-bit address (VA) */
+#define R_AMD64_DIR32	2 /* 32-bit address (VA) R_DIR32 */
+#define R_AMD64_IMAGEBASE	 3 /* 32-bit absolute ref w/o base R_IMAGEBASE */
+#define R_AMD64_PCRLONG		 4 /* 32-bit relative address from byte following reloc R_PCRLONG */
+#define R_AMD64_PCRLONG_1		 5 /* 32-bit relative address from byte distance 1 from reloc */
+#define R_AMD64_PCRLONG_2		 6 /* 32-bit relative address from byte distance 2 from reloc */
+#define R_AMD64_PCRLONG_3		 7 /* 32-bit relative address from byte distance 3 from reloc */
+#define R_AMD64_PCRLONG_4		 8 /* 32-bit relative address from byte distance 4 from reloc */
+#define R_AMD64_PCRLONG_5		 9 /* 32-bit relative address from byte distance 5 from reloc */
+#define R_AMD64_SECTION	10 /* Section index */
+#define R_AMD64_SECREL	11 /* 32 bit offset from base of section containing target R_SECREL*/
+#define R_AMD64_SECREL7	12 /* 7 bit unsigned offset from base of section containing target */
+#define R_AMD64_TOKEN	13 /* 32 bit metadata token */
+/* Pseude PC64 relocation - note not specified by MS/AMD but need for gas pc-relative 64bit wide relocation generated by elf*/
+#define R_AMD64_PCRQUAD	14
+
 #define R_DIR16 	 1
 #define R_REL24          5
 #define R_DIR32 	 6
diff -rNbu binutils_060913_org/include/coff/pe.h binutils_060913/include/coff/pe.h
--- binutils_060913_org/include/coff/pe.h	2005-05-10 12:21:09.000000000 +0200
+++ binutils_060913/include/coff/pe.h	2006-09-11 12:33:56.000000000 +0200
@@ -119,6 +119,7 @@
 #define IMAGE_FILE_MACHINE_THUMB             0x01c2
 #define IMAGE_FILE_MACHINE_TRICORE           0x0520
 #define IMAGE_FILE_MACHINE_WCEMIPSV2         0x0169
+#define IMAGE_FILE_MACHINE_AMD64             0x8664  // AMD64 (K8)
 
 #define IMAGE_SUBSYSTEM_UNKNOWN			 0
 #define IMAGE_SUBSYSTEM_NATIVE			 1
@@ -267,7 +268,7 @@
    of just 4 bytes long.  */
 typedef struct 
 {
-  AOUTHDR standard;
+  AOUTHDR64 standard;
 
   /* NT extra fields; see internal.h for descriptions.  */
   char  ImageBase[8];
@@ -294,7 +295,7 @@
   /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];  */
   char  DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars.  */
 } PEPAOUTHDR;
-#define PEPAOUTSZ	240
+#define PEPAOUTSZ	(AOUTHDRSZ64+196+5*4) /* 240 */
   
 #undef  E_FILNMLEN
 #define E_FILNMLEN	18	/* # characters in a file name.  */
diff -rNbu binutils_060913_org/include/coff/x86_64.h binutils_060913/include/coff/x86_64.h
--- binutils_060913_org/include/coff/x86_64.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/include/coff/x86_64.h	2006-08-17 09:12:24.000000000 +0200
@@ -0,0 +1,67 @@
+/* coff information for AMD 64.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#define L_LNNO_SIZE 2
+#define INCLUDE_COMDAT_FIELDS_IN_AUXENT
+#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
+ 	F_AR32WR	file has byte ordering of an AR32WR machine (e.g. vax).  */
+
+#define F_RELFLG	(0x0001)
+#define F_EXEC		(0x0002)
+#define F_LNNO		(0x0004)
+#define F_LSYMS		(0x0008)
+
+#define AMD64MAGIC	0x8664
+
+#define AMD64BADMAG(x)	( (x).f_magic != AMD64MAGIC)
+#define IMAGE_NT_OPTIONAL_HDR64_MAGIC      0x20b
+
+#define OMAGIC          0404    /* object files, eg as output */
+#define ZMAGIC          IMAGE_NT_OPTIONAL_HDR64_MAGIC    /* demand load format, eg normal ld output 0x10b */
+#define STMAGIC		0401	/* target shlib */
+#define SHMAGIC		0443	/* host   shlib */
+
+/* define some NT default values */
+/*  #define NT_IMAGE_BASE        0x400000 moved to internal.h */
+#define NT_SECTION_ALIGNMENT 0x1000
+#define NT_FILE_ALIGNMENT    0x200
+#define NT_DEF_RESERVE       0x100000
+#define NT_DEF_COMMIT        0x1000
+
+/********************** 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
+

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista  binaries
  2006-09-13  9:43 Kai Tietz
@ 2006-09-13 10:52 ` Pedro Alves
  2006-09-13 11:50   ` Kai Tietz
                     ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: Pedro Alves @ 2006-09-13 10:52 UTC (permalink / raw)
  To: Kai Tietz; +Cc: binutils

Hi Kai,

Kai Tietz wrote:
 > Hey,
 >
 > Finally I did the merge to the current CVS version. Additionally I 
changed
 > pep_dll.c to inherit the pe_dll.c file to avoid double source code.
 > By this merge I fixed - by side-effect - a memory out-of-bounds 
access for
 > idata relocation section in pe_dll.c (allocating 4-bytes but 
memset'ing 8
 > bytes).
 > The changelogs are now splitted and the testcases adjusted for the new
 > target. I removed some escaped debug prints, which lead under cygwin
 > environment to compiler warnigns in the ld-module.
 >

A few more tips that may get your work into CVS faster.

- The ChangeLog entries aren't supposed to be put in the patch itself.
They should be placed in the email instead. Check the mail archives for
reference.

- You should really consider submitting this piece by piece. I would
have some of comments to the code, but the patch being so big, puts me
off. At least please split the bfd/gas/ld/binutils parts. I would start
with bfd first. I know its more work for you, but it should be less work
for the maintainers, and that's who you want to catch attention from.
Keep in mind, they are very busy with other stuff. The easier you make
it for them, the best for you.

- There are still some big files that you duplicated.
Please describe why you needed to duplicate them when you submit your
patches. Maybe the limitations you found in the originals could be
tackled, instead of just duplicating them. Duplicate code just means
more maintainance for you. If a bug gets fixed in the original, well,
you know what I mean.
For example the ld/emultempl/pe.em file is already a shell script so
the code duplication is minimized, Couldn't it be adapted instead of
duplicated? There is already a copy of it there (beos.em), and in my
opinion another one would be bad.

- On lots of places you touch code just to change the indenting. It only
makes the patch longer, and harder to review.

- When you touch code that is common with other archs, you should at
least run the testsuite in one of those other archs,
and say you did so in patch submission. That brings up the confidence
the patch is ok for everybody else.

Just trying to be helpful,
Cheers,
Pedro Alves

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista binaries
@ 2006-09-13  9:43 Kai Tietz
  2006-09-13 10:52 ` Pedro Alves
  0 siblings, 1 reply; 17+ messages in thread
From: Kai Tietz @ 2006-09-13  9:43 UTC (permalink / raw)
  To: binutils; +Cc: H. J. Lu

[-- Attachment #1: Type: text/plain, Size: 574 bytes --]

Hey,

Finally I did the merge to the current CVS version. Additionally I changed 
pep_dll.c to inherit the pe_dll.c file to avoid double source code.
By this merge I fixed - by side-effect - a memory out-of-bounds access for 
idata relocation section in pe_dll.c (allocating 4-bytes but memset'ing 8 
bytes).
The changelogs are now splitted and the testcases adjusted for the new 
target. I removed some escaped debug prints, which lead under cygwin 
environment to compiler warnigns in the ld-module.

Regards,
 i.A. Kai Tietz

PS: The FSF contract issue is now complete.


[-- Attachment #2: binutils-2.17.pex-64.060913.diff --]
[-- Type: application/octet-stream, Size: 191244 bytes --]

diff -rNbu binutils_060913_org/ChangeLog binutils_060913/ChangeLog
--- binutils_060913_org/ChangeLog	2006-08-30 15:14:18.000000000 +0200
+++ binutils_060913/ChangeLog	2006-09-13 11:03:35.000000000 +0200
@@ -1,3 +1,7 @@
+2006-09-13  Kai Tietz	<Kai.Tietz@onevision.com>
+	* configure.in: Add new target x86_64-pc-mingw64
+	* config.sub: Add new target x86_64-pc-mingw64
+	
 2006-08-30  Corinna Vinschen  <corinna@vinschen.de>
 
 	* configure.in: Never build newlib for a Mingw host.
diff -rNbu binutils_060913_org/bfd/ChangeLog binutils_060913/bfd/ChangeLog
--- binutils_060913_org/bfd/ChangeLog	2006-09-13 00:10:31.000000000 +0200
+++ binutils_060913/bfd/ChangeLog	2006-09-13 11:04:28.000000000 +0200
@@ -1,3 +1,29 @@
+2006-09-13	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* configure.in:	Added new target-vectors x86_64coff_vec, x86_64pe_vec, and x86_64pei_vec
+	* config.bfd:		Adjusted x86_64 target architecture detection
+	* bfd.c:			Add for new target "coff-x86-64"
+		bfd_get_sign_extend:	Add target vector idents for pe-x86-64. and pei-x86-64
+	* coff-x86_64.c: 	Add new file for x86_64 (AMD64) coff support
+	* libpei.h				Adjustments for COFF_WITH_pex64
+	* coffcode.h:			Add for new target machine, architecture, signature, and internal
+								signature handler.
+	* makefile.am:	Add new files to target-all and define make-rule for pex64igen.c
+	* makefile.in:	Add new files to target-all and define make-rule for pex64igen.c
+	* pe-x86_64.c:	Add for new target "pe-x86-64"
+	* pei-x86_64.c:	Add for new target "pei-x86-64"
+	* peicode.h:		Adjusts for new targets
+		coff_swap_filehdr_out:	set for this target to _bfd_pex64_only_swap_filehdr_out
+		SIZEOF_IDATA4:				define it as 8 byte size for this target
+		SIZEOF_IDATA5:				define it as 8 byte size for this target
+		jump_table jtab:			Add for AMD64MAGIC
+		pe_ILF_build_a_bfd:		Adjusts for new size of SIZEOF_IDATA4 and SIZE_IDATA5
+		pe_ILF_object_p:			Add coff image-file signature to internal signature translation
+	* pexxigen.c:		Adjust proper include of target coff-header and introduced target specific code
+		COFF_WITH_pex64:	New macro for this target
+		pe_print_idata:	New dumping method for import section of PE+ files
+	* target.c:		Add new target vectors declarations for x86_64 coff targets
+	
 2006-09-12  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR ld/3197
diff -rNbu binutils_060913_org/bfd/Makefile.am binutils_060913/bfd/Makefile.am
--- binutils_060913_org/bfd/Makefile.am	2006-08-21 10:12:44.000000000 +0200
+++ binutils_060913/bfd/Makefile.am	2006-09-11 11:47:44.000000000 +0200
@@ -559,7 +559,11 @@
 	mmo.lo \
 	nlm32-alpha.lo \
 	nlm64.lo \
-	pepigen.lo
+	coff-x86_64.lo \
+	pe-x86_64.lo \
+	pei-x86_64.lo \
+	pepigen.lo \
+	pex64igen.lo
 
 BFD64_BACKENDS_CFILES = \
 	aix5ppc-core.c \
@@ -582,7 +586,10 @@
 	elf64.c \
 	mmo.c \
 	nlm32-alpha.c \
-	nlm64.c
+	nlm64.c \
+	coff-x86_64.c \
+	pe-x86_64.c \
+	pei-x86_64.c
 
 OPTIONAL_BACKENDS = \
 	aix386-core.lo \
@@ -632,7 +639,7 @@
 	$(OPTIONAL_BACKENDS_CFILES)
 
 BUILD_CFILES = \
-	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c
+	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c pex64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 
@@ -790,6 +797,11 @@
 	sed -e s/XX/pep/g < $(srcdir)/peXXigen.c > pepigen.new
 	mv -f pepigen.new pepigen.c
 
+pex64igen.c: peXXigen.c
+	rm -f pex64igen.c
+	sed -e s/XX/pex64/g < $(srcdir)/peXXigen.c > pex64igen.new
+	mv -f pex64igen.new pex64igen.c
+
 BFD_H_DEPS= $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h
 LOCAL_H_DEPS= libbfd.h sysdep.h config.h
 $(BFD32_LIBS) \
@@ -1852,4 +1864,7 @@
 pepigen.lo: pepigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/ia64.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
+pex64igen.lo: pex64igen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+  $(INCDIR)/coff/internal.h $(INCDIR)/coff/x86_64.h $(INCDIR)/coff/external.h \
+  $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
 # IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff -rNbu binutils_060913_org/bfd/Makefile.in binutils_060913/bfd/Makefile.in
--- binutils_060913_org/bfd/Makefile.in	2006-08-21 10:12:44.000000000 +0200
+++ binutils_060913/bfd/Makefile.in	2006-09-11 13:21:24.000000000 +0200
@@ -792,7 +792,11 @@
 	mmo.lo \
 	nlm32-alpha.lo \
 	nlm64.lo \
-	pepigen.lo
+	coff-x86_64.lo \
+	pe-x86_64.lo \
+	pei-x86_64.lo \
+	pepigen.lo \
+	pex64igen.lo
 
 BFD64_BACKENDS_CFILES = \
 	aix5ppc-core.c \
@@ -815,7 +819,10 @@
 	elf64.c \
 	mmo.c \
 	nlm32-alpha.c \
-	nlm64.c
+	nlm64.c \
+	coff-x86_64.c \
+	pe-x86_64.c \
+	pei-x86_64.c
 
 OPTIONAL_BACKENDS = \
 	aix386-core.lo \
@@ -866,7 +873,7 @@
 	$(OPTIONAL_BACKENDS_CFILES)
 
 BUILD_CFILES = \
-	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c
+	elf32-ia64.c elf64-ia64.c peigen.c pepigen.c pex64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 SOURCE_HFILES = \
@@ -1364,6 +1371,11 @@
 	sed -e s/XX/pe/g < $(srcdir)/peXXigen.c > peigen.new
 	mv -f peigen.new peigen.c
 
+pex64igen.c : peXXigen.c
+	rm -f pex64igen.c
+	sed -e s/XX/pex64/g < $(srcdir)/peXXigen.c > pex64igen.new
+	mv -f pex64igen.new pex64igen.c
+	
 pepigen.c : peXXigen.c
 	rm -f pepigen.c
 	sed -e s/XX/pep/g < $(srcdir)/peXXigen.c > pepigen.new
@@ -2410,6 +2422,9 @@
 peigen.lo: peigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/i386.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
+pex64igen.lo: pex64igen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
+  $(INCDIR)/coff/internal.h $(INCDIR)/coff/x86_64.h $(INCDIR)/coff/external.h \
+  $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
 pepigen.lo: pepigen.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
   $(INCDIR)/coff/internal.h $(INCDIR)/coff/ia64.h $(INCDIR)/coff/external.h \
   $(INCDIR)/coff/pe.h libcoff.h $(INCDIR)/bfdlink.h libpei.h
diff -rNbu binutils_060913_org/bfd/coff-x86_64.c binutils_060913/bfd/coff-x86_64.c
--- binutils_060913_org/bfd/coff-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/bfd/coff-x86_64.c	2006-09-06 12:28:12.000000000 +0200
@@ -0,0 +1,751 @@
+/* BFD back-end for AMD 64 COFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+#ifndef COFF_WITH_pex64
+#define COFF_WITH_pex64
+#endif
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#include "coff/x86_64.h"
+#include "coff/internal.h"
+#include "coff/pe.h"
+#include "libcoff.h"
+
+#define BADMAG(x) AMD64BADMAG(x)
+
+#ifdef COFF_WITH_pex64
+# undef AOUTSZ
+# define AOUTSZ		PEPAOUTSZ
+# define PEAOUTHDR	PEPAOUTHDR
+#endif
+
+static bfd_reloc_status_type coff_amd64_reloc(bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **);
+static reloc_howto_type *coff_amd64_rtype_to_howto(bfd *, asection *, struct internal_reloc *,struct coff_link_hash_entry *, struct internal_syment *,bfd_vma *);
+static reloc_howto_type *coff_amd64_reloc_type_lookup(bfd *, bfd_reloc_code_real_type);
+
+#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 AMD 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 relocatable 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_amd64_reloc(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 !defined(COFF_WITH_PE)
+  if(output_bfd == (bfd *) NULL)
+    return bfd_reloc_continue;
+#endif
+
+  if(bfd_is_com_section (symbol->section)) {
+#if !defined(COFF_WITH_PE)
+     /* 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
+      /* In PE mode, we do not offset the common symbol.  */
+      diff = reloc_entry->addend;
+#endif
+    }
+  else
+    {
+      /* For some reason bfd_perform_relocation always effectively
+	 ignores the addend for a COFF target when producing
+	 relocatable output.  This seems to be always wrong for 386
+	 COFF, so we handle the addend here instead.  */
+#if defined(COFF_WITH_PE)
+      if(output_bfd == (bfd *) NULL)
+	{
+	  reloc_howto_type *howto = reloc_entry->howto;
+
+	  /* Although PC relative relocations are very similar between
+	     PE and non-PE formats, but they are off by 1 << howto->size
+	     bytes. For the external relocation, PE is very different
+	     from others. See md_apply_fix3 () in gas/config/tc-amd64.c.
+	     When we link PE and non-PE object files together to
+	     generate a non-PE executable, we have to compensate it
+	     here.  */
+	  if(howto->pc_relative && howto->pcrel_offset)
+	    diff = -(1 << howto->size);
+	  else if(symbol->flags & BSF_WEAK)
+	    diff = reloc_entry->addend - symbol->value;
+	  else
+	    diff = -reloc_entry->addend;
+	}
+      else
+#endif
+	diff = reloc_entry->addend;
+    }
+
+#if defined(COFF_WITH_PE)
+  /* FIXME: How should this case be handled?  */
+  if(reloc_entry->howto->type == R_AMD64_IMAGEBASE
+      && output_bfd!=NULL
+      && bfd_get_flavour(output_bfd) == bfd_target_coff_flavour)
+    diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
+#endif
+
+#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;
+	  case 4:
+	    {
+	      long long x = bfd_get_64 (abfd, addr);
+	      DOIT (x);
+	      bfd_put_64 (abfd, (bfd_vma) x, addr);
+	    }
+	    break;
+
+	  default:
+	    abort ();
+	  }
+      }
+
+  /* Now let bfd_perform_relocation finish everything up.  */
+  return bfd_reloc_continue;
+}
+
+#if defined(COFF_WITH_PE)
+/* Return TRUE if this relocation should appear in the output .reloc
+   section.  */
+
+static bfd_boolean in_reloc_p(bfd *, reloc_howto_type *);
+
+static bfd_boolean in_reloc_p(bfd *abfd ATTRIBUTE_UNUSED,reloc_howto_type *howto)
+{
+  return ! howto->pc_relative && howto->type!=R_AMD64_IMAGEBASE;
+}
+#endif /* COFF_WITH_PE */
+
+#ifndef PCRELOFFSET
+#define PCRELOFFSET TRUE
+#endif
+
+static reloc_howto_type howto_table[] =
+{
+  EMPTY_HOWTO (0),
+  HOWTO (R_AMD64_DIR64,		/* type  1*/
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long, 4 = long long) */
+	 64,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "R_X86_64_64",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffffffffffffll,		/* src_mask */
+	 0xffffffffffffffffll,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+  HOWTO (R_AMD64_DIR32,		/* type 2 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "R_X86_64_32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+  /* PE IMAGE_REL_AMD64_ADDR32NB relocation (3).	*/
+  HOWTO (R_AMD64_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_amd64_reloc,	/* special_function */
+	 "rva32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+  /* 32-bit longword PC relative relocation (4).  */
+  HOWTO (R_AMD64_PCRLONG,		/* type 4 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+
+ HOWTO (R_AMD64_PCRLONG_1,		/* type 5 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+1",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_2,		/* type 6 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+2",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_3,		/* type 7 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+3",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_4,		/* type 8 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+4",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+ HOWTO (R_AMD64_PCRLONG_5,		/* type 9 */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 TRUE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 coff_amd64_reloc,	/* special_function */
+	 "DISP32+5",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  EMPTY_HOWTO (10), // R_AMD64_SECTION 10
+#if defined(COFF_WITH_PE)
+  /* 32-bit longword section relative relocation (11).  */
+  HOWTO (R_AMD64_SECREL,		/* 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_amd64_reloc,	/* special_function */
+	 "secrel32",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 TRUE),			/* pcrel_offset */
+#else
+  EMPTY_HOWTO (11),
+#endif
+  EMPTY_HOWTO (12),
+  EMPTY_HOWTO (13),
+#ifndef DONT_EXTEND_AMD64
+  HOWTO (R_AMD64_PCRQUAD,
+         0,                     /* rightshift */
+         4,                     /* size (0 = byte, 1 = short, 2 = long) */
+         64,                    /* bitsize */
+         TRUE,                  /* pc_relative */
+         0,                     /* bitpos */
+         complain_overflow_signed, /* complain_on_overflow */
+         coff_amd64_reloc,      /* special_function */
+         "R_X86_64_PC64",       /* name */
+         TRUE,                  /* partial_inplace */
+         0xffffffffffffffffll,  /* src_mask */
+         0xffffffffffffffffll,  /* dst_mask */
+         PCRELOFFSET),           /* pcrel_offset */
+#else
+  EMPTY_HOWTO (14),
+#endif
+  /* Byte relocation (15).  */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_8",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0x000000ff,		/* src_mask */
+	 0x000000ff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 16-bit word relocation (16).  */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_16",		/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 32-bit longword relocation (17).	*/
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_32S",			/* name */
+	 TRUE,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* Byte PC relative relocation (18).	 */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC8",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x000000ff,		/* src_mask */
+	 0x000000ff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 16-bit word PC relative relocation (19).	*/
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC16",	/* name */
+	 TRUE,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 PCRELOFFSET),		/* pcrel_offset */
+  /* 32-bit longword PC relative relocation (20).  */
+  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_amd64_reloc,	/* special_function */
+	 "R_X86_64_PC32",	/* 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 I386 1			/* Customize coffcode.h */
+#define AMD64 1
+#define RTYPE2HOWTO(cache_ptr, dst)					\
+  ((cache_ptr)->howto =							\
+   ((dst)->r_type < sizeof (howto_table) / sizeof (howto_table[0])	\
+    ? howto_table + (dst)->r_type					\
+    : NULL))
+
+/* For 386 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.  For normal AMD64 COFF, we
+   can use the generic relocate_section routine.  For PE, we need our
+   own routine.  */
+
+#if !defined(COFF_WITH_PE)
+
+#define coff_relocate_section _bfd_coff_generic_relocate_section
+
+#else /* COFF_WITH_PE */
+
+/* The PE relocate section routine.  The only difference between this
+   and the regular routine is that we don't want to do anything for a
+   relocatable link.  */
+
+static bfd_boolean coff_pe_amd64_relocate_section(bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,struct internal_reloc *, struct internal_syment *, asection **);
+
+static bfd_boolean
+coff_pe_amd64_relocate_section(bfd *output_bfd,struct bfd_link_info *info,bfd *input_bfd,asection *input_section,bfd_byte *contents,struct internal_reloc *relocs,struct internal_syment *syms,asection **sections)
+{
+  if(info->relocatable)
+    return TRUE;
+
+  return _bfd_coff_generic_relocate_section(output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
+}
+
+#define coff_relocate_section coff_pe_amd64_relocate_section
+
+#endif /* COFF_WITH_PE */
+
+/* Convert an rtype to howto for the COFF backend linker.  */
+
+static reloc_howto_type *
+coff_amd64_rtype_to_howto(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;
+
+  if(rel->r_type > sizeof (howto_table) / sizeof (howto_table[0])) {
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+    }
+  if(rel->r_type>=R_AMD64_PCRLONG_1 && rel->r_type<=R_AMD64_PCRLONG_5) {
+	  rel->r_vaddr+=(bfd_vma)(rel->r_type-R_AMD64_PCRLONG);
+	  rel->r_type=R_AMD64_PCRLONG;
+  }
+  howto = howto_table + rel->r_type;
+
+#if defined(COFF_WITH_PE)
+  /* Cancel out code in _bfd_coff_generic_relocate_section.  */
+  *addendp = 0;
+#endif
+
+  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);
+
+#if !defined(COFF_WITH_PE)
+      /* I think we *do* want to bypass this.  If we don't, I have
+	 seen some data parameters get the wrong relocation 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;
+#endif
+    }
+
+#if !defined(COFF_WITH_PE)
+  /* If the output symbol is common (in which case this must be a
+     relocatable 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;
+#endif
+
+#if defined(COFF_WITH_PE)
+  if(howto->pc_relative)
+    {
+      *addendp -= 4;
+
+      /* If the symbol is defined, then the generic code is going to
+         add back the symbol value in order to cancel out an
+         adjustment it made to the addend.  However, we set the addend
+         to 0 at the start of this function.  We need to adjust here,
+         to avoid the adjustment the generic code will make.  FIXME:
+         This is getting a bit hackish.  */
+      if(sym!=NULL && sym->n_scnum!=0)
+	*addendp -= sym->n_value;
+    }
+
+  if(rel->r_type == R_AMD64_IMAGEBASE && (bfd_get_flavour(sec->output_section->owner) == bfd_target_coff_flavour)) {
+      *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
+  }
+
+  if(rel->r_type == R_AMD64_SECREL) {
+      bfd_vma osect_vma;
+
+      if(h && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak))
+	osect_vma = h->root.u.def.section->output_section->vma;
+      else {
+	  asection *sec;
+	  int i;
+
+	  /* Sigh, the only way to get the section to offset against
+	     is to find it the hard way.  */
+
+	  for (sec = abfd->sections, i = 1; i < sym->n_scnum; i++)
+	    sec = sec->next;
+
+	  osect_vma = sec->output_section->vma;
+	}
+
+      *addendp -= osect_vma;
+    }
+#endif
+
+  return howto;
+}
+
+#define coff_bfd_reloc_type_lookup coff_amd64_reloc_type_lookup
+
+static reloc_howto_type *
+coff_amd64_reloc_type_lookup(bfd *abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)
+{
+  switch (code) {
+    case BFD_RELOC_RVA:
+      return howto_table + R_AMD64_IMAGEBASE;
+    case BFD_RELOC_32:
+      return howto_table + R_AMD64_DIR32;
+    case BFD_RELOC_64:
+      return howto_table + R_AMD64_DIR64;
+    case BFD_RELOC_64_PCREL:
+#ifndef DONT_EXTEND_AMD64
+      return howto_table + R_AMD64_PCRQUAD;
+#else
+	/* Fall trough */
+#endif
+    case BFD_RELOC_32_PCREL:
+      return howto_table + R_AMD64_PCRLONG;
+    case BFD_RELOC_X86_64_32S:
+      return howto_table + R_RELLONG;
+    case BFD_RELOC_16:
+      return howto_table + R_RELWORD;
+    case BFD_RELOC_16_PCREL:
+      return howto_table + R_PCRWORD;
+    case BFD_RELOC_8:
+      return howto_table + R_RELBYTE;
+    case BFD_RELOC_8_PCREL:
+      return howto_table + R_PCRBYTE;
+#if defined(COFF_WITH_PE)
+    case BFD_RELOC_32_SECREL:
+      return howto_table + R_AMD64_SECREL;
+#endif
+    default:
+      BFD_FAIL ();
+      return 0;
+    }
+}
+
+#define coff_rtype_to_howto coff_amd64_rtype_to_howto
+
+#ifdef TARGET_UNDERSCORE
+
+/* If amd64 gcc uses underscores for symbol names, then it does not use
+   a leading dot for local labels, so if TARGET_UNDERSCORE is defined
+   we treat all symbols starting with L as local.  */
+
+static bfd_boolean coff_amd64_is_local_label_name(bfd *, const char *);
+
+static bfd_boolean coff_amd64_is_local_label_name(bfd *abfd,const char *name)
+{
+  if(name[0] == 'L')
+    return TRUE;
+
+  return _bfd_coff_is_local_label_name (abfd, name);
+}
+
+#define coff_bfd_is_local_label_name coff_amd64_is_local_label_name
+
+#endif /* TARGET_UNDERSCORE */
+
+#include "coffcode.h"
+
+#ifdef PE
+#define amd64coff_object_p pe_bfd_object_p
+#else
+#define amd64coff_object_p coff_object_p
+#endif
+
+const bfd_target
+#ifdef TARGET_SYM
+  TARGET_SYM =
+#else
+  x86_64coff_vec =
+#endif
+{
+#ifdef TARGET_NAME
+  TARGET_NAME,
+#else
+ "coff-x86-64",			/* 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 | D_PAGED),
+
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
+#if defined(COFF_WITH_PE)
+   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY
+#endif
+   | SEC_CODE | SEC_DATA),
+
+#ifdef TARGET_UNDERSCORE
+  TARGET_UNDERSCORE,		/* leading underscore */
+#else
+  0,				/* leading underscore */
+#endif
+  '/',				/* 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, amd64coff_object_p, /* bfd_check_format */
+       bfd_generic_archive_p, amd64coff_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 -rNbu binutils_060913_org/bfd/coffcode.h binutils_060913/bfd/coffcode.h
--- binutils_060913_org/bfd/coffcode.h	2006-09-05 20:56:50.000000000 +0200
+++ binutils_060913/bfd/coffcode.h	2006-09-11 13:28:46.000000000 +0200
@@ -1887,6 +1887,12 @@
       arch = bfd_arch_i386;
       break;
 #endif
+#ifdef AMD64MAGIC
+	case AMD64MAGIC:
+		arch=bfd_arch_i386;
+		machine=bfd_mach_x86_64;
+		break;
+#endif
 #ifdef IA64MAGIC
     case IA64MAGIC:
       arch = bfd_arch_ia64;
@@ -2721,13 +2727,18 @@
       return TRUE;
 #endif
 
-#ifdef I386MAGIC
+#if defined(I386MAGIC) || defined(AMD64MAGIC)
     case bfd_arch_i386:
+#ifdef I386MAGIC
       *magicp = I386MAGIC;
+#endif
 #ifdef LYNXOS
       /* Just overwrite the usual value if we're doing Lynx.  */
       *magicp = LYNXCOFFMAGIC;
 #endif
+#ifdef AMD64MAGIC
+	  *magicp = AMD64MAGIC;
+#endif
       return TRUE;
 #endif
 
@@ -3759,6 +3770,7 @@
     internal_f.f_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
 #endif
 
+#ifndef COFF_WITH_pex64
 #ifdef COFF_WITH_PE
   internal_f.f_flags |= IMAGE_FILE_32BIT_MACHINE;
 #else
@@ -3767,6 +3779,7 @@
   else
     internal_f.f_flags |= F_AR32W;
 #endif
+#endif
 
 #ifdef TI_TARGET_ID
   /* Target id is used in TI COFF v1 and later; COFF0 won't use this field,
@@ -3863,7 +3876,11 @@
 #if defined(LYNXOS)
     internal_a.magic = LYNXCOFFMAGIC;
 #else  /* LYNXOS */
+#ifdef AMD64
+	internal_a.magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+#else
     internal_a.magic = ZMAGIC;
+#endif
 #endif /* LYNXOS */
 #endif /* I386 */
 
diff -rNbu binutils_060913_org/bfd/config.bfd binutils_060913/bfd/config.bfd
--- binutils_060913_org/bfd/config.bfd	2006-08-21 10:12:44.000000000 +0200
+++ binutils_060913/bfd/config.bfd	2006-09-11 11:25:34.000000000 +0200
@@ -98,7 +98,7 @@
 strongarm*)	 targ_archs=bfd_arm_arch ;;
 thumb*)		 targ_archs=bfd_arm_arch ;;
 v850*)		 targ_archs=bfd_v850_arch ;;
-x86_64)		 targ_archs=bfd_i386_arch ;;
+x86_64*)		 targ_archs=bfd_i386_arch ;;
 xscale*)	 targ_archs=bfd_arm_arch ;;
 xtensa*)	 targ_archs=bfd_xtensa_arch ;;
 z80|r800)	 targ_archs=bfd_z80_arch ;;
@@ -578,6 +578,12 @@
     targ_selvecs="bfd_elf32_i386_vec i386linux_vec bfd_efi_app_ia32_vec"
     want64=true
     ;;
+  x86_64-*-mingw64*)
+    targ_defvec=x86_64pe_vec
+    targ_selvecs="x86_64pe_vec x86_64pei_vec x86_64coff_vec  bfd_elf64_x86_64_vec"
+    want64=true
+    targ_underscore=yes
+    ;;
 #endif
   i[3-7]86-*-lynxos*)
     targ_defvec=bfd_elf32_i386_vec
diff -rNbu binutils_060913_org/bfd/configure binutils_060913/bfd/configure
--- binutils_060913_org/bfd/configure	2006-08-21 10:12:44.000000000 +0200
+++ binutils_060913/bfd/configure	2006-09-11 11:31:56.000000000 +0200
@@ -4086,7 +4086,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -4113,6 +4113,9 @@
       ;;
     *64-bit*)
       case $host in
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
@@ -10949,6 +10952,7 @@
     i386aout_vec)		tb="$tb i386aout.lo aout32.lo" ;;
     i386bsd_vec)		tb="$tb i386bsd.lo aout32.lo" ;;
     i386coff_vec)		tb="$tb coff-i386.lo cofflink.lo" ;;
+    x86_64coff_vec)		tb="$tb coff-x86_64.lo cofflink.lo"; target_size=64 ;;
     i386dynix_vec)		tb="$tb i386dynix.lo aout32.lo" ;;
     i386freebsd_vec)		tb="$tb i386freebsd.lo aout32.lo" ;;
     i386linux_vec)		tb="$tb i386linux.lo aout32.lo" ;;
@@ -10959,7 +10963,9 @@
     i386netbsd_vec)		tb="$tb i386netbsd.lo aout32.lo" ;;
     i386os9k_vec)		tb="$tb i386os9k.lo aout32.lo" ;;
     i386pe_vec)			tb="$tb pe-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pe_vec)			tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i386pei_vec)		tb="$tb pei-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pei_vec)		tb="$tb pei-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i860coff_vec)		tb="$tb coff-i860.lo cofflink.lo" ;;
     icoff_big_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
     icoff_little_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
diff -rNbu binutils_060913_org/bfd/configure.in binutils_060913/bfd/configure.in
--- binutils_060913_org/bfd/configure.in	2006-08-21 10:12:45.000000000 +0200
+++ binutils_060913/bfd/configure.in	2006-09-11 11:37:22.000000000 +0200
@@ -739,6 +739,7 @@
     i386aout_vec)		tb="$tb i386aout.lo aout32.lo" ;;
     i386bsd_vec)		tb="$tb i386bsd.lo aout32.lo" ;;
     i386coff_vec)		tb="$tb coff-i386.lo cofflink.lo" ;;
+    x86_64coff_vec)		tb="$tb coff-x86_64.lo cofflink.lo"; target_size=64 ;;
     i386dynix_vec)		tb="$tb i386dynix.lo aout32.lo" ;;
     i386freebsd_vec)		tb="$tb i386freebsd.lo aout32.lo" ;;
     i386linux_vec)		tb="$tb i386linux.lo aout32.lo" ;;
@@ -749,7 +750,9 @@
     i386netbsd_vec)		tb="$tb i386netbsd.lo aout32.lo" ;;
     i386os9k_vec)		tb="$tb i386os9k.lo aout32.lo" ;;
     i386pe_vec)			tb="$tb pe-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pe_vec)			tb="$tb pe-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i386pei_vec)		tb="$tb pei-i386.lo peigen.lo cofflink.lo" ;;
+    x86_64pei_vec)		tb="$tb pei-x86_64.lo pex64igen.lo cofflink.lo"; target_size=64 ;;
     i860coff_vec)		tb="$tb coff-i860.lo cofflink.lo" ;;
     icoff_big_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
     icoff_little_vec)		tb="$tb coff-i960.lo cofflink.lo" ;;
diff -rNbu binutils_060913_org/bfd/libpei.h binutils_060913/bfd/libpei.h
--- binutils_060913_org/bfd/libpei.h	2005-05-04 17:53:35.000000000 +0200
+++ binutils_060913/bfd/libpei.h	2006-09-11 11:42:22.000000000 +0200
@@ -204,6 +204,38 @@
 #define PUT_SCNHDR_LNNOPTR H_PUT_32
 #endif
 
+#ifdef COFF_WITH_pex64
+#define GET_OPTHDR_IMAGE_BASE H_GET_64
+#define PUT_OPTHDR_IMAGE_BASE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_RESERVE H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_RESERVE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_COMMIT H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_COMMIT H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_RESERVE H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_RESERVE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_COMMIT H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_COMMIT H_PUT_64
+#define GET_PDATA_ENTRY bfd_get_32
+
+#define _bfd_XX_bfd_copy_private_bfd_data_common	_bfd_pex64_bfd_copy_private_bfd_data_common
+#define _bfd_XX_bfd_copy_private_section_data		_bfd_pex64_bfd_copy_private_section_data
+#define _bfd_XX_get_symbol_info				_bfd_pex64_get_symbol_info
+#define _bfd_XX_only_swap_filehdr_out			_bfd_pex64_only_swap_filehdr_out
+#define _bfd_XX_print_private_bfd_data_common		_bfd_pex64_print_private_bfd_data_common
+#define _bfd_XXi_final_link_postscript			_bfd_pex64i_final_link_postscript
+#define _bfd_XXi_final_link_postscript			_bfd_pex64i_final_link_postscript
+#define _bfd_XXi_only_swap_filehdr_out			_bfd_pex64i_only_swap_filehdr_out
+#define _bfd_XXi_swap_aouthdr_in			_bfd_pex64i_swap_aouthdr_in
+#define _bfd_XXi_swap_aouthdr_out			_bfd_pex64i_swap_aouthdr_out
+#define _bfd_XXi_swap_aux_in				_bfd_pex64i_swap_aux_in
+#define _bfd_XXi_swap_aux_out				_bfd_pex64i_swap_aux_out
+#define _bfd_XXi_swap_lineno_in				_bfd_pex64i_swap_lineno_in
+#define _bfd_XXi_swap_lineno_out			_bfd_pex64i_swap_lineno_out
+#define _bfd_XXi_swap_scnhdr_out			_bfd_pex64i_swap_scnhdr_out
+#define _bfd_XXi_swap_sym_in				_bfd_pex64i_swap_sym_in
+#define _bfd_XXi_swap_sym_out				_bfd_pex64i_swap_sym_out
+
+#else /* !COFF_WITH_pex64 */
 #ifdef COFF_WITH_pep
 
 #define GET_OPTHDR_IMAGE_BASE H_GET_64
@@ -269,6 +301,7 @@
 #define _bfd_XXi_swap_sym_out				_bfd_pei_swap_sym_out
 
 #endif /* !COFF_WITH_pep */
+#endif /* !COFF_WITG_pex64 */
 
 /* Macro: Returns true if the bfd is a PE executable as opposed to a PE object file.  */
 #define bfd_pe_executable_p(abfd) \
diff -rNbu binutils_060913_org/bfd/pe-x86_64.c binutils_060913/bfd/pe-x86_64.c
--- binutils_060913_org/bfd/pe-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/bfd/pe-x86_64.c	2006-09-06 12:23:54.000000000 +0200
@@ -0,0 +1,54 @@
+/* BFD back-end for Intel/AMD x86_64 PECOFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_SYM 		x86_64pe_vec
+#define TARGET_NAME 		"pe-x86-64"
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+#define PCRELOFFSET 		TRUE
+#define TARGET_UNDERSCORE 	'_'
+#define COFF_LONG_SECTION_NAMES
+#define COFF_SUPPORT_GNU_LINKONCE
+#define COFF_LONG_FILENAMES
+
+#define COFF_SECTION_ALIGNMENT_ENTRIES \
+{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
+
+#include "coff-x86_64.c"
diff -rNbu binutils_060913_org/bfd/peXXigen.c binutils_060913/bfd/peXXigen.c
--- binutils_060913_org/bfd/peXXigen.c	2006-07-24 18:51:26.000000000 +0200
+++ binutils_060913/bfd/peXXigen.c	2006-09-11 13:29:26.000000000 +0200
@@ -52,7 +52,7 @@
    on this code has a chance of getting something accomplished without
    wasting too much time.  */
 
-/* This expands into COFF_WITH_pe or COFF_WITH_pep depending on whether
+/* This expands into COFF_WITH_pe, COFF_WITH_pep, or COFF_WITH_pex64 depending on whether
    we're compiling for straight PE or PE+.  */
 #define COFF_WITH_XX
 
@@ -67,17 +67,21 @@
    within PE/PEI, so we get them from there.  FIXME: The lack of
    variance is an assumption which may prove to be incorrect if new
    PE/PEI targets are created.  */
-#ifdef COFF_WITH_pep
-# include "coff/ia64.h"
+#ifdef COFF_WITH_pex64
+# include "coff/x86_64.h"
 #else
+# ifdef COFF_WITH_pep
+#  include "coff/ia64.h"
+# else
 # include "coff/i386.h"
+# endif
 #endif
 
 #include "coff/pe.h"
 #include "libcoff.h"
 #include "libpei.h"
 
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
 # undef AOUTSZ
 # define AOUTSZ		PEPAOUTSZ
 # define PEAOUTHDR	PEPAOUTHDR
@@ -399,7 +403,7 @@
   aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry);
   aouthdr_int->text_start =
     GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   aouthdr_int->data_start =
     GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start);
@@ -455,7 +459,7 @@
   if (aouthdr_int->entry)
     {
       aouthdr_int->entry += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_int->entry &= 0xffffffff;
 #endif
     }
@@ -463,12 +467,12 @@
   if (aouthdr_int->tsize)
     {
       aouthdr_int->text_start += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_int->text_start &= 0xffffffff;
 #endif
     }
 
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   if (aouthdr_int->dsize)
     {
@@ -548,7 +552,7 @@
   if (aouthdr_in->tsize)
     {
       aouthdr_in->text_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->text_start &= 0xffffffff;
 #endif
     }
@@ -556,7 +560,7 @@
   if (aouthdr_in->dsize)
     {
       aouthdr_in->data_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->data_start &= 0xffffffff;
 #endif
     }
@@ -564,7 +568,7 @@
   if (aouthdr_in->entry)
     {
       aouthdr_in->entry -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
       aouthdr_in->entry &= 0xffffffff;
 #endif
     }
@@ -661,7 +665,7 @@
   PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
 			  aouthdr_out->standard.text_start);
 
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   /* PE32+ does not have data_start member!  */
   PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
 			  aouthdr_out->standard.data_start);
@@ -1262,6 +1266,35 @@
 	    }
 
 	  /* Print HintName vector entries.  */
+#ifdef COFF_WITH_pex64
+	  for (j = 0; j < datasize; j += 8)
+	    {
+			unsigned long member = bfd_get_32(abfd,data+idx+j);
+			unsigned long member_high = bfd_get_32(abfd,data+idx+j+4);
+			if(!member && !member_high) break;
+	      if (member_high & 0x80000000)
+		fprintf (file, "\t%lx%08lx\t %4lx%08lx  <none>",
+			 member_high,member, member_high & 0x7fffffff,member);
+	      else
+		{
+		  int ordinal;
+		  char *member_name;
+
+		  ordinal = bfd_get_16 (abfd, data + member - adj);
+		  member_name = (char *) data + member - adj + 2;
+		  fprintf (file, "\t%04lx\t %4d  %s",member, ordinal, member_name);
+		  }
+
+	      /* If the time stamp is not zero, the import address
+		 table holds actual addresses.  */
+	      if (time_stamp != 0
+		  && first_thunk != 0
+		  && first_thunk != hint_addr)
+		fprintf (file, "\t%04lx",
+			 (long) bfd_get_32 (abfd, ft_data + ft_idx + j));
+	      fprintf (file, "\n");
+	    }
+#else
 	  for (j = 0; j < datasize; j += 4)
 	    {
 	      unsigned long member = bfd_get_32 (abfd, data + idx + j);
@@ -1294,6 +1327,7 @@
 
 	      fprintf (file, "\n");
 	    }
+#endif /* !defined(COFF_WITH_pex64) */
 
 	  if (ft_allocated)
 	    free (ft_data);
@@ -1534,7 +1568,7 @@
 static bfd_boolean
 pe_print_pdata (bfd * abfd, void * vfile)
 {
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
 # define PDATA_ROW_SIZE	(3*8)
 #else
 # define PDATA_ROW_SIZE	(5*4)
@@ -1560,7 +1594,7 @@
 
   fprintf (file,
 	   _("\nThe Function Table (interpreted .pdata section contents)\n"));
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
   fprintf (file,
 	   _(" vma:\t\t\tBegin Address    End Address      Unwind Info\n"));
 #else
@@ -1614,7 +1648,7 @@
       fprintf_vma (file, begin_addr); fputc (' ', file);
       fprintf_vma (file, end_addr); fputc (' ', file);
       fprintf_vma (file, eh_handler);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
       fputc (' ', file);
       fprintf_vma (file, eh_data); fputc (' ', file);
       fprintf_vma (file, prolog_end_addr);
diff -rNbu binutils_060913_org/bfd/pei-x86_64.c binutils_060913/bfd/pei-x86_64.c
--- binutils_060913_org/bfd/pei-x86_64.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/bfd/pei-x86_64.c	2006-09-06 12:23:58.000000000 +0200
@@ -0,0 +1,55 @@
+/* BFD back-end for Intel 386 PE IMAGE COFF files.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_SYM 		x86_64pei_vec
+#define TARGET_NAME 		"pei-x86-64"
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+#define PCRELOFFSET 		TRUE
+#define TARGET_UNDERSCORE 	'_'
+#define COFF_LONG_SECTION_NAMES
+#define COFF_SUPPORT_GNU_LINKONCE
+#define COFF_LONG_FILENAMES
+
+#define COFF_SECTION_ALIGNMENT_ENTRIES \
+{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
+
+#include "coff-x86_64.c"
diff -rNbu binutils_060913_org/bfd/peicode.h binutils_060913/bfd/peicode.h
--- binutils_060913_org/bfd/peicode.h	2005-05-04 17:53:37.000000000 +0200
+++ binutils_060913/bfd/peicode.h	2006-09-11 11:58:24.000000000 +0200
@@ -183,7 +183,15 @@
 #ifdef COFF_IMAGE_WITH_PE
 # define coff_swap_filehdr_out _bfd_XXi_only_swap_filehdr_out
 #else
+# ifdef COFF_WITH_pex64
+#  define coff_swap_filehdr_out _bfd_pex64_only_swap_filehdr_out
+# else
+#  ifdef COFF_WITH_pep
+#   define coff_swap_filehdr_out _bfd_pep_only_swap_filehdr_out
+#  else
 # define coff_swap_filehdr_out _bfd_pe_only_swap_filehdr_out
+#  endif
+# endif
 #endif
 
 static void
@@ -217,7 +225,10 @@
   if (scnhdr_int->s_vaddr != 0)
     {
       scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
+      /* Do not cut upper 32 bit for 64 vma */
+#ifndef COFF_WITH_pex64
       scnhdr_int->s_vaddr &= 0xffffffff;
+#endif
     }
 
 #ifndef COFF_NO_HACK_SCNHDR_SIZE
@@ -405,8 +416,16 @@
 					+ NUM_ILF_SECTIONS * 9 \
 					+ STRING_SIZE_SIZE)
 #define SIZEOF_IDATA2		(5 * 4)
+
+/* For PE+ idata4 & 5 have thumb size of 8 bytes ! */
+#ifndef COFF_WITH_pex64
 #define SIZEOF_IDATA4		(1 * 4)
 #define SIZEOF_IDATA5		(1 * 4)
+#else
+#define SIZEOF_IDATA4		(2 * 4)
+#define SIZEOF_IDATA5		(2 * 4)
+#endif
+
 #define SIZEOF_IDATA6		(2 + strlen (symbol_name) + 1 + 1)
 #define SIZEOF_IDATA7		(strlen (source_dll) + 1 + 1)
 #define SIZEOF_ILF_SECTIONS     (NUM_ILF_SECTIONS * sizeof (struct coff_section_tdata))
@@ -656,6 +675,13 @@
   },
 #endif
 
+#ifdef AMD64MAGIC
+  { AMD64MAGIC,
+  { 0xff,0x25,0x00,0x00,0x00,0x00,0x90,0x90 },
+  8,2
+  },
+#endif
+
 #ifdef  MC68MAGIC
   { MC68MAGIC, { /* XXX fill me in */ }, 0, 0 },
 #endif
@@ -830,8 +856,15 @@
 	/* XXX - treat as IMPORT_NAME ??? */
 	abort ();
 
+#ifndef COFF_WITH_pex64
       * (unsigned int *) id4->contents = ordinal | 0x80000000;
       * (unsigned int *) id5->contents = ordinal | 0x80000000;
+#else
+      * (unsigned int *) id4->contents = ordinal;
+	  ((unsigned int *) id4->contents)[1] = 0x80000000;
+      * (unsigned int *) id5->contents = ordinal;
+      ((unsigned int *) id5->contents)[1] = 0x80000000;
+#endif
     }
   else
     {
@@ -1071,6 +1104,12 @@
 #endif
       break;
 
+	case IMAGE_FILE_MACHINE_AMD64:
+#ifdef AMD64MAGIC
+		magic=AMD64MAGIC;
+#endif
+		break;
+
     case IMAGE_FILE_MACHINE_M68K:
 #ifdef MC68AGIC
       magic = MC68MAGIC;
diff -rNbu binutils_060913_org/bfd/targets.c binutils_060913/bfd/targets.c
--- binutils_060913_org/bfd/targets.c	2006-08-21 10:12:45.000000000 +0200
+++ binutils_060913/bfd/targets.c	2006-09-11 12:28:24.000000000 +0200
@@ -789,6 +789,9 @@
 extern const bfd_target we32kcoff_vec;
 extern const bfd_target z80coff_vec;
 extern const bfd_target z8kcoff_vec;
+extern const bfd_target x86_64pe_vec;
+extern const bfd_target x86_64pei_vec;
+extern const bfd_target x86_64coff_vec;
 
 /* These are always included.  */
 extern const bfd_target srec_vec;
@@ -1033,6 +1036,11 @@
 #if 0
 	&i386dynix_vec,
 #endif
+#ifdef BFD64
+	&x86_64coff_vec,
+	&x86_64pe_vec,
+	&x86_64pei_vec,
+#endif
 	&i386freebsd_vec,
 #if 0
 	/* Since a.out files lack decent magic numbers, no way to recognize
diff -rNbu binutils_060913_org/binutils/ChangeLog binutils_060913/binutils/ChangeLog
--- binutils_060913_org/binutils/ChangeLog	2006-09-11 16:40:39.000000000 +0200
+++ binutils_060913/binutils/ChangeLog	2006-09-13 11:06:00.000000000 +0200
@@ -1,3 +1,15 @@
+2006-09-13	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* configure.in:	Add new target x86_64-pc-mingw64
+	* dlltool.c:	Adjust include for this target
+		DLLTOOL_MX86_64:	Added macro to handle target specific code
+		mname:					Added default target static as "i386:x86-64"
+		MX86:					Added macro for target ident
+		mtable:				Added target specific definitions
+		rvaafter:			Add handling of MX86
+		rvabefore:			Add handling of MX86
+		asmprefix:			Add handling of MX86
+
 2006-09-09  Nick Clifton  <nickc@redhat.com>
 
 	PR binutils/3110
diff -rNbu binutils_060913_org/binutils/configure binutils_060913/binutils/configure
--- binutils_060913_org/binutils/configure	2006-08-21 10:12:45.000000000 +0200
+++ binutils_060913/binutils/configure	2006-09-11 13:50:34.000000000 +0200
@@ -8451,6 +8451,12 @@
 	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
 	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
 	  ;;
+	x86_64-*-mingw64*)
+  	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MX86_64"
+	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+	  ;;
 	i[3-7]86-*-interix)
 	  BUILD_DLLTOOL='$(DLLTOOL_PROG)'
 	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386"
diff -rNbu binutils_060913_org/binutils/configure.in binutils_060913/binutils/configure.in
--- binutils_060913_org/binutils/configure.in	2006-08-21 10:12:45.000000000 +0200
+++ binutils_060913/binutils/configure.in	2006-09-11 13:33:20.000000000 +0200
@@ -265,6 +265,14 @@
 	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
 	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
 	  ;;
+	x86_64-*-mingw64*)
+changequote([,])dnl
+  	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_MX86_64"
+	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+	  ;;
+changequote(,)dnl
 changequote(,)dnl
 	i[3-7]86-*-interix)
 changequote([,])dnl
diff -rNbu binutils_060913_org/binutils/dlltool.c binutils_060913/binutils/dlltool.c
--- binutils_060913_org/binutils/dlltool.c	2006-08-21 10:12:45.000000000 +0200
+++ binutils_060913/binutils/dlltool.c	2006-09-11 13:47:12.000000000 +0200
@@ -261,6 +261,9 @@
 #include "coff/arm.h"
 #include "coff/internal.h"
 #endif
+#ifdef DLLTOOL_MX86_64
+#include "coff/x86_64.h"
+#endif
 
 /* Forward references.  */
 static char *look_for_prog (const char *, const char *, int);
@@ -398,6 +401,10 @@
 static const char *mname = "i386";
 #endif
 
+#ifdef DLLTOOL_MX86_64
+static const char *mname = "i386:x86-64";
+#endif
+
 #ifdef DLLTOOL_PPC
 static const char *mname = "ppc";
 #endif
@@ -640,6 +647,14 @@
     arm_jtab, sizeof (arm_jtab), 8
   }
   ,
+  {
+#define MX86 11
+    "i386:x86-64", ".byte", ".short", ".long", ".asciz", "#",
+    "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
+    "pe-x86-64",bfd_arch_i386,
+    i386_jtab, sizeof (i386_jtab), 2
+  }
+  ,
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 };
 
@@ -763,6 +778,7 @@
     {
     case MARM:
     case M386:
+	case MX86:
     case MPPC:
     case MTHUMB:
     case MARM_INTERWORK:
@@ -788,6 +804,7 @@
     {
     case MARM:
     case M386:
+	case MX86:
     case MPPC:
     case MTHUMB:
     case MARM_INTERWORK:
@@ -823,6 +840,7 @@
     case MARM_WINCE:
       break;
     case M386:
+	case MX86:
       /* Symbol names starting with ? do not have a leading underscore. */
       if (name && *name == '?')
         break;
@@ -1701,9 +1719,18 @@
     {
       fprintf (filvar, "listone%d:\n", headindex);
       for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
+#ifdef DLLTOOL_MX86_64
+	fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
+		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG);
+#else
 	fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
 		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
+#endif
+#ifdef DLLTOOL_MX86_64
+      fprintf (filvar,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
       fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       headindex++;
     }
 
@@ -1713,9 +1740,18 @@
     {
       fprintf (filvar, "listtwo%d:\n", headindex);
       for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ )
+#ifdef DLLTOOL_MX86_64
+	fprintf (filvar, "\t%sfuncptr%d_%d%s\n%s\t0\n",
+		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER,ASM_LONG);
+#else
 	fprintf (filvar, "\t%sfuncptr%d_%d%s\n",
 		 ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER);
-      fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
+#ifdef DLLTOOL_MX86_64
+      fprintf (filvar,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       headindex++;
     }
 
@@ -2388,6 +2424,36 @@
 	  /* An idata$4 or idata$5 is one word long, and has an
 	     rva to idata$6.  */
 
+#ifdef DLLTOOL_MX86_64
+	  si->data = xmalloc (8);
+	  si->size = 8;
+
+	  if (exp->noname)
+	    {
+	      si->data[0] = exp->ordinal ;
+	      si->data[1] = exp->ordinal >> 8;
+	      si->data[2] = exp->ordinal >> 16;
+		  si->data[3] = exp->ordinal >> 24;
+		  si->data[4] = 0;
+		  si->data[5] = 0;
+		  si->data[6] = 0;
+	      si->data[7] = 0x80;
+	    }
+	  else
+	    {
+	      sec->reloc_count = 1;
+	      memset (si->data, 0, si->size);
+	      rel = xmalloc (sizeof (arelent));
+	      rpp = xmalloc (sizeof (arelent *) * 2);
+	      rpp[0] = rel;
+	      rpp[1] = 0;
+	      rel->address = 0;
+	      rel->addend = 0;
+	      rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
+	      rel->sym_ptr_ptr = secdata[IDATA6].sympp;
+	      sec->orelocation = rpp;
+	    }
+#else
 	  si->data = xmalloc (4);
 	  si->size = 4;
 
@@ -2412,7 +2478,7 @@
 	      rel->sym_ptr_ptr = secdata[IDATA6].sympp;
 	      sec->orelocation = rpp;
 	    }
-
+#endif
 	  break;
 
 	case IDATA6:
@@ -2626,7 +2692,11 @@
   if (!no_idata5)
     {
       fprintf (f, "\t.section\t.idata$5\n");
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       fprintf (f, "fthunk:\n");
     }
 
@@ -2634,7 +2704,11 @@
     {
       fprintf (f, "\t.section\t.idata$4\n");
 
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
       fprintf (f, "\t.section	.idata$4\n");
       fprintf (f, "hname:\n");
     }
@@ -2660,13 +2734,21 @@
   if (!no_idata4)
     {
       fprintf (f, "\t.section	.idata$4\n");
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
     }
 
   if (!no_idata5)
     {
       fprintf (f, "\t.section	.idata$5\n");
-      fprintf (f, "\t%s\t0\n", ASM_LONG);
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list */
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */
+#endif
     }
 
 #ifdef DLLTOOL_PPC
diff -rNbu binutils_060913_org/binutils/testsuite/ChangeLog binutils_060913/binutils/testsuite/ChangeLog
--- binutils_060913_org/binutils/testsuite/ChangeLog	2006-08-15 20:23:10.000000000 +0200
+++ binutils_060913/binutils/testsuite/ChangeLog	2006-09-13 11:06:25.000000000 +0200
@@ -1,3 +1,12 @@
+2006-09-13	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* binutils-all/dlltool.exp:	Add support for target x86_64-pc-mingw64
+	* binutils-all/objcopy.exp:	Add support for target x86_64-pc-mingw64
+	* binutils-all/windres/windres.exp:	Add support for target x86_64-pc-mingw64
+	* binutils-all/windres/lang.rc:	xfail it as long as there is no windows.h
+	* binutils-all/windres/strtab1.rc:	xfail it as long as there is no windows.h
+	* lib/utils-lib.exp:	Adjust executable prefix detection (as .exe)
+
 2006-08-15  Thiemo Seufer  <ths@mips.com>
             Nigel Stephens  <nigel@mips.com>
             David Ung  <davidu@mips.com>
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/copy-3.d binutils_060913/binutils/testsuite/binutils-all/copy-3.d
--- binutils_060913_org/binutils/testsuite/binutils-all/copy-3.d	2006-05-03 18:45:59.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/copy-3.d	2006-09-11 15:53:34.000000000 +0200
@@ -3,7 +3,7 @@
 #objcopy: --set-section-flags .text=alloc,data
 #name: copy with setting section flags 3
 #source: bintest.s
-#not-target: *-*-aout *-*-*pe *-*-*coff i*86-*-cygwin* i*86-*-mingw32*
+#not-target: *-*-aout *-*-*pe *-*-*coff i*86-*-cygwin* i*86-*-mingw32* x86_64-*-mingw64*
 # The .text # section in PE/COFF has a fixed set of flags and these
 # cannot be changed.  We skip it for them.
 
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/dlltool.exp binutils_060913/binutils/testsuite/binutils-all/dlltool.exp
--- binutils_060913_org/binutils/testsuite/binutils-all/dlltool.exp	2005-05-08 16:17:40.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/dlltool.exp	2006-09-11 13:53:24.000000000 +0200
@@ -14,13 +14,14 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 
-if {![istarget "i*86-*-*"]} {
+if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw64*"] } {
     return
 }
 
 if {![istarget "i*86-*-*pe*"] \
     && ![istarget "i*86-*-cygwin*"] \
-    && ![istarget "i*86-*-mingw32*"] } {
+    && ![istarget "i*86-*-mingw32*"] \
+    && ![istarget "x86_64-*-mingw64*"] } {
     set target_xfail "yes"
 } else {
     set target_xfail "no"
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/objcopy.exp binutils_060913/binutils/testsuite/binutils-all/objcopy.exp
--- binutils_060913_org/binutils/testsuite/binutils-all/objcopy.exp	2006-06-23 18:23:09.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/objcopy.exp	2006-09-11 13:54:42.000000000 +0200
@@ -443,7 +443,7 @@
 
 # Build a final executable.
 
-if { [istarget *-*-cygwin] || [istarget *-*-mingw32] } {
+if { [istarget *-*-cygwin] || [istarget *-*-mingw*] } {
     set test_prog "testprog.exe"
 } else {
     set test_prog "testprog"
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/windres/lang.rc binutils_060913/binutils/testsuite/binutils-all/windres/lang.rc
--- binutils_060913_org/binutils/testsuite/binutils-all/windres/lang.rc	2001-07-19 01:56:41.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/windres/lang.rc	2006-09-11 13:55:32.000000000 +0200
@@ -1,3 +1,4 @@
+//#xfail *-*-mingw64
 #include "windows.h"
 
 LANGUAGE 0, 0
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/windres/strtab1.rc binutils_060913/binutils/testsuite/binutils-all/windres/strtab1.rc
--- binutils_060913_org/binutils/testsuite/binutils-all/windres/strtab1.rc	2001-07-19 01:56:41.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/windres/strtab1.rc	2006-09-11 13:55:58.000000000 +0200
@@ -1,3 +1,4 @@
+//#xfail *-*-mingw64
 #include "windows.h"
 
 LANGUAGE 0, 0
diff -rNbu binutils_060913_org/binutils/testsuite/binutils-all/windres/windres.exp binutils_060913/binutils/testsuite/binutils-all/windres/windres.exp
--- binutils_060913_org/binutils/testsuite/binutils-all/windres/windres.exp	2005-05-08 16:17:41.000000000 +0200
+++ binutils_060913/binutils/testsuite/binutils-all/windres/windres.exp	2006-09-11 13:56:48.000000000 +0200
@@ -19,13 +19,14 @@
 
 # Written by DJ Delorie <dj@redhat.com>
 
-if {![istarget "i*86-*-*"]} {
+if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw64"] } {
     return
 }
 
 if {![istarget "i*86-*-*pe*"] \
     && ![istarget "i*86-*-cygwin*"] \
-    && ![istarget "i*86-*-mingw32*"] } {
+    && ![istarget "i*86-*-mingw32*"] \
+    && ![istarget "x86_64-*-mingw64*"] } {
     set target_xfail "yes"
 } else {
     set target_xfail "no"
diff -rNbu binutils_060913_org/binutils/testsuite/lib/utils-lib.exp binutils_060913/binutils/testsuite/lib/utils-lib.exp
--- binutils_060913_org/binutils/testsuite/lib/utils-lib.exp	2006-04-26 15:37:05.000000000 +0200
+++ binutils_060913/binutils/testsuite/lib/utils-lib.exp	2006-09-11 13:57:44.000000000 +0200
@@ -161,7 +161,7 @@
 #	Returns target executable extension, if any.
 #
 proc exe_ext {} {
-    if { [istarget *-*-mingw32] || [istarget *-*-cygwin*] } {
+    if { [istarget *-*-mingw*] || [istarget *-*-cygwin*] } {
         return ".exe"
     } else {
         return ""
diff -rNbu binutils_060913_org/config.guess binutils_060913/config.guess
--- binutils_060913_org/config.guess	2006-05-14 02:51:19.000000000 +0200
+++ binutils_060913/config.guess	2006-09-11 10:11:09.000000000 +0200
@@ -780,6 +780,9 @@
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
 	exit ;;
+    x86*:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
     i*:MINGW*:*)
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
diff -rNbu binutils_060913_org/config.sub binutils_060913/config.sub
--- binutils_060913_org/config.sub	2006-08-15 20:23:07.000000000 +0200
+++ binutils_060913/config.sub	2006-09-11 11:01:18.000000000 +0200
@@ -682,6 +682,10 @@
 		basic_machine=i386-pc
 		os=-mingw32
 		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
 	miniframe)
 		basic_machine=m68000-convergent
 		;;
@@ -1210,7 +1214,7 @@
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 	      | -chorusos* | -chorusrdb* \
 	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
 	      | -uxpv* | -beos* | -mpeix* | -udk* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
diff -rNbu binutils_060913_org/configure binutils_060913/configure
--- binutils_060913_org/configure	2006-08-30 15:14:18.000000000 +0200
+++ binutils_060913/configure	2006-09-11 11:08:02.000000000 +0200
@@ -1097,6 +1097,10 @@
     # noconfigdirs="tcl tk expect dejagnu make texinfo bison patch flex byacc send-pr uudecode dejagnu diff guile perl itcl gnuserv"
     noconfigdirs="$noconfigdirs expect dejagnu autoconf automake send-pr rcs guile perl texinfo libtool newlib"
     ;;
+  x86_64-*-mingw64*)
+    # noconfigdirs="tcl tk expect dejagnu make texinfo bison patch flex byacc send-pr uudecode dejagnu diff guile perl itcl gnuserv"
+    noconfigdirs="$noconfigdirs expect dejagnu autoconf automake send-pr rcs guile perl texinfo libtool newlib"
+    ;;
   i[3456789]86-*-beos*)
     noconfigdirs="$noconfigdirs tk itcl libgui gdb"
     ;;
@@ -1442,6 +1446,10 @@
     target_configdirs="$target_configdirs target-winsup"
     noconfigdirs="$noconfigdirs expect target-libgloss target-newlib ${libgcj}"
     ;;    
+  x86_64-*-mingw64*)
+    target_configdirs="$target_configdirs target-winsup"
+    noconfigdirs="$noconfigdirs expect target-libgloss target-newlib ${libgcj}"
+    ;;    
   *-*-cygwin*)
     target_configdirs="$target_configdirs target-libtermcap target-winsup"
     noconfigdirs="$noconfigdirs target-gperf target-libgloss ${libgcj}"
@@ -1760,6 +1768,8 @@
     ;;
   *-mingw32*)
     ;;
+  *-mingw64*)
+    ;;
   *-interix*)
     host_makefile_frag="config/mh-interix"
     ;;
diff -rNbu binutils_060913_org/configure.in binutils_060913/configure.in
--- binutils_060913_org/configure.in	2006-08-30 15:14:18.000000000 +0200
+++ binutils_060913/configure.in	2006-09-11 11:07:02.000000000 +0200
@@ -281,6 +281,10 @@
     # noconfigdirs="tcl tk expect dejagnu make texinfo bison patch flex byacc send-pr uudecode dejagnu diff guile perl itcl gnuserv"
     noconfigdirs="$noconfigdirs expect dejagnu autoconf automake send-pr rcs guile perl texinfo libtool newlib"
     ;;
+  x86_64-*-mingw64*)
+    # noconfigdirs="tcl tk expect dejagnu make texinfo bison patch flex byacc send-pr uudecode dejagnu diff guile perl itcl gnuserv"
+    noconfigdirs="$noconfigdirs expect dejagnu autoconf automake send-pr rcs guile perl texinfo libtool newlib"
+    ;;
   i[[3456789]]86-*-beos*)
     noconfigdirs="$noconfigdirs tk itcl libgui gdb"
     ;;
@@ -618,6 +622,10 @@
     target_configdirs="$target_configdirs target-winsup"
     noconfigdirs="$noconfigdirs expect target-libgloss target-newlib ${libgcj}"
     ;;    
+  x86_64-*-mingw64*)
+    target_configdirs="$target_configdirs target-winsup"
+    noconfigdirs="$noconfigdirs expect target-libgloss target-newlib ${libgcj}"
+    ;;    
   *-*-cygwin*)
     target_configdirs="$target_configdirs target-libtermcap target-winsup"
     noconfigdirs="$noconfigdirs target-gperf target-libgloss ${libgcj}"
@@ -936,6 +944,8 @@
     ;;
   *-mingw32*)
     ;;
+  *-mingw64*)
+    ;;
   *-interix*)
     host_makefile_frag="config/mh-interix"
     ;;
diff -rNbu binutils_060913_org/gas/ChangeLog binutils_060913/gas/ChangeLog
--- binutils_060913_org/gas/ChangeLog	2006-09-13 02:46:08.000000000 +0200
+++ binutils_060913/gas/ChangeLog	2006-09-13 11:08:34.000000000 +0200
@@ -1,3 +1,15 @@
+2006-09-13	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* configure.in:	Add new target x86_64-pc-mingw64
+	* configure.tgt:	Add new target x86_64-pc-mingw64
+	* config/obj-coff.h:	Add handling for TE_PEP target specific code and definitions
+	* config/tc-i386.c:		Add new targets
+		md_parse_option:			Add targets to OPTION_64
+		x86_64_target_format:	Add new method for setup proper default target cpu mode
+	* config/te-pep.h:		Add new target definition header
+		TE_PEP:				Identifies new target architecture
+		COFF_WITH_pex64:	Set proper includes in bfd
+
 2006-09-13  Alan Modra  <amodra@bigpond.net.au>
 
 	PR gas/3165
diff -rNbu binutils_060913_org/gas/config/obj-coff.h binutils_060913/gas/config/obj-coff.h
--- binutils_060913_org/gas/config/obj-coff.h	2006-06-07 13:27:57.000000000 +0200
+++ binutils_060913/gas/config/obj-coff.h	2006-09-11 14:17:40.000000000 +0200
@@ -55,16 +55,30 @@
 #endif
 
 #ifdef TC_I386
+#ifndef TE_PEP
 #include "coff/i386.h"
+#else
+#include "coff/x86_64.h"
+#endif
 
 #ifdef TE_PE
+#ifdef TE_PEP
+extern const char *x86_64_target_format PARAMS ((void));
+#define TARGET_FORMAT x86_64_target_format ()
+#define COFF_TARGET_FORMAT "pe-x86-64"
+#else
 #define TARGET_FORMAT "pe-i386"
 #endif
+#endif
 
 #ifndef TARGET_FORMAT
+#ifdef TE_PEP
+#define TARGET_FORMAT "coff-x86-64"
+#else
 #define TARGET_FORMAT "coff-i386"
 #endif
 #endif
+#endif
 
 #ifdef TC_M68K
 #include "coff/m68k.h"
diff -rNbu binutils_060913_org/gas/config/tc-i386.c binutils_060913/gas/config/tc-i386.c
--- binutils_060913_org/gas/config/tc-i386.c	2006-08-02 18:25:14.000000000 +0200
+++ binutils_060913/gas/config/tc-i386.c	2006-09-11 14:26:14.000000000 +0200
@@ -5768,7 +5768,7 @@
 
 struct option md_longopts[] = {
   {"32", no_argument, NULL, OPTION_32},
-#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined(TE_PEP)
   {"64", no_argument, NULL, OPTION_64},
 #endif
   {"divide", no_argument, NULL, OPTION_DIVIDE},
@@ -5793,7 +5793,8 @@
       quiet_warnings = 1;
       break;
 
-#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined(TE_PEP)
+#ifndef TE_PEP
       /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
 	 should be emitted or not.  FIXME: Not implemented.  */
     case 'Q':
@@ -5812,14 +5813,15 @@
       /* -s: On i386 Solaris, this tells the native assembler to use
 	 .stab instead of .stab.excl.  We always use .stab anyhow.  */
       break;
-
+#endif
     case OPTION_64:
       {
 	const char **list, **l;
 
 	list = bfd_target_list ();
 	for (l = list; *l != NULL; l++)
-	  if (strncmp (*l, "elf64-x86-64", 12) == 0)
+	  if (strcmp (*l, "elf64-x86-64") == 0 || strcmp(*l,"coff-x86-64")==0 || strcmp(*l,"pe-x86-64")==0 ||
+		  strcmp(*l,"pei-x86-64")==0)
 	    {
 	      default_arch = "x86_64";
 	      break;
@@ -5927,6 +5929,22 @@
 
 }
 
+#if defined(TE_PEP)
+const char *x86_64_target_format(void)
+{
+	if (!strcmp (default_arch, "x86_64")) {
+		set_code_flag (CODE_64BIT);
+		return COFF_TARGET_FORMAT;
+	} else if (!strcmp (default_arch, "i386")) {
+		set_code_flag (CODE_32BIT);
+		return "coff-i386";
+	} else
+		as_fatal (_("Unknown architecture"));
+	abort ();
+	return NULL;
+}
+#endif
+
 #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
      || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))
 
diff -rNbu binutils_060913_org/gas/config/te-pep.h binutils_060913/gas/config/te-pep.h
--- binutils_060913_org/gas/config/te-pep.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/gas/config/te-pep.h	2006-09-11 14:26:46.000000000 +0200
@@ -0,0 +1,10 @@
+#define TE_PEP
+#define COFF_WITH_pex64
+
+#define TE_PE
+#define LEX_AT (LEX_BEGIN_NAME | LEX_NAME) /* Can have @'s inside labels.  */
+
+/* The PE format supports long section names.  */
+#define COFF_LONG_SECTION_NAMES
+
+#include "obj-format.h"
diff -rNbu binutils_060913_org/gas/configure binutils_060913/gas/configure
--- binutils_060913_org/gas/configure	2006-08-02 16:26:07.000000000 +0200
+++ binutils_060913/gas/configure	2006-09-11 14:09:36.000000000 +0200
@@ -3921,7 +3921,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -3935,6 +3935,9 @@
         x86_64-*linux*)
           LD="${LD-ld} -m elf_i386"
           ;;
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_i386"
+          ;;
         ppc64-*linux*|powerpc64-*linux*)
           LD="${LD-ld} -m elf32ppclinux"
           ;;
@@ -3951,6 +3954,9 @@
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         ppc*-*linux*|powerpc*-*linux*)
           LD="${LD-ld} -m elf64ppc"
           ;;
@@ -4948,6 +4954,11 @@
 #define I386COFF 1
 _ACEOF
  ;;
+      x86_64)
+cat >>confdefs.h <<\_ACEOF
+#define I386COFF 1
+_ACEOF
+ ;;
       m68k)
 cat >>confdefs.h <<\_ACEOF
 #define M68KCOFF 1
diff -rNbu binutils_060913_org/gas/configure.in binutils_060913/gas/configure.in
--- binutils_060913_org/gas/configure.in	2006-08-02 16:26:07.000000000 +0200
+++ binutils_060913/gas/configure.in	2006-09-11 14:11:30.000000000 +0200
@@ -417,6 +417,19 @@
       ;;
     esac
   ;;
+  x86_64)
+    case ${obj_format} in
+    aout)
+      emulations="$emulations i386coff i386elf"
+      ;;
+    coff)
+      emulations="$emulations i386aout i386elf"
+    ;;
+    elf)
+      emulations="$emulations i386aout i386coff"
+      ;;
+    esac
+  ;;
   esac
 fi
 
@@ -459,6 +472,7 @@
   coff)
     case ${target_cpu_type} in
       i386) AC_DEFINE(I386COFF, 1, [Using i386 COFF?]) ;;
+      x86_64) AC_DEFINE(I386COFF, 1, [Using i386 COFF?]) ;;
       m68k) AC_DEFINE(M68KCOFF, 1, [Using m68k COFF?]) ;;
       m88k) AC_DEFINE(M88KCOFF, 1, [Using m88k COFF?]) ;;
     esac
diff -rNbu binutils_060913_org/gas/configure.tgt binutils_060913/gas/configure.tgt
--- binutils_060913_org/gas/configure.tgt	2006-08-15 20:23:11.000000000 +0200
+++ binutils_060913/gas/configure.tgt	2006-09-11 14:13:06.000000000 +0200
@@ -77,7 +77,7 @@
   strongarm*b)		cpu_type=arm endian=big ;;
   strongarm*)		cpu_type=arm endian=little ;;
   v850*)		cpu_type=v850 ;;
-  x86_64)		cpu_type=i386 arch=x86_64;;
+  x86_64*)		cpu_type=i386 arch=x86_64;;
   xscale*be|xscale*b)	cpu_type=arm endian=big ;;
   xscale*)		cpu_type=arm endian=little ;;
   xtensa*)		cpu_type=xtensa arch=xtensa ;;
@@ -210,6 +210,7 @@
   i386-*-cygwin*)			fmt=coff em=pe ;;
   i386-*-interix*)			fmt=coff em=interix ;;
   i386-*-mingw32*)			fmt=coff em=pe ;;
+  i386-*-mingw64*)			fmt=coff em=pep ;;
   i386-*-nto-qnx*)			fmt=elf ;;
   i386-*-*nt*)				fmt=coff em=pe ;;
   i386-*-chaos)				fmt=elf ;;
diff -rNbu binutils_060913_org/gas/testsuite/ChangeLog binutils_060913/gas/testsuite/ChangeLog
--- binutils_060913_org/gas/testsuite/ChangeLog	2006-09-08 19:08:05.000000000 +0200
+++ binutils_060913/gas/testsuite/ChangeLog	2006-09-13 11:09:11.000000000 +0200
@@ -1,3 +1,21 @@
+2006-09-13	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* i386/immed64.d:	Add #pass for avoid proplems with alignment paddings
+	* i386/rex.d:		Changed for target matching
+	* i386/x86-64-addr32.d:	Changed for target matching and padding
+	* i386/x86-64-branch.d:	Changed for target matching and padding
+	* i386/x86-64-crx-suffix.d:	Changed for target matching and padding
+	* i386/x86-64-crx.d:	Changed for target matching
+	* i386/x86-64-drx-suffix.d:	Changed for target matching and padding
+	* i386/x86-64-crx-suffix.d:	Changed for target matching and padding
+	* i386/x86-64-opcode.d:	Changed for target matching
+	* i386/x86-64-pcrel.d:	Changed for target matching and relocation fixing
+	* i386/x86-64-rip.d:	Changed for target matching and padding
+	* i386/x86-64-stack-intel.d:	Changed for target matching and padding
+	* i386/x86-64-stack-suffix.d:	Changed for target matching and padding
+	* i386/x86-64-stack.d:	Changed for target matching and padding
+	* i386/x86_64.d:	Changed section specifier to .text
+
 2006-09-08  Kazu Hirata  <kazu@codesourcery.com>
 
 	* lib/gas-dg.exp (gas-dg-test): Treat $dir as a literal.
diff -rNbu binutils_060913_org/gas/testsuite/gas/all/gas.exp binutils_060913/gas/testsuite/gas/all/gas.exp
--- binutils_060913_org/gas/testsuite/gas/all/gas.exp	2005-11-21 05:30:32.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/all/gas.exp	2006-09-11 14:28:34.000000000 +0200
@@ -207,6 +207,7 @@
      || [istarget i*86-*-isc*] \
      || [istarget i*86-*-go32*] \
      || [istarget i*86-*-cygwin*] \
+     || [istarget x86_64-*-mingw64*] \
      || [istarget i*86-*-*nt] \
      || [istarget i*86-*-interix*] \
      || ([istarget i960-*-vxworks5.*] && ![istarget i960-*-vxworks5.0*]) } {
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/i386.exp binutils_060913/gas/testsuite/gas/i386/i386.exp
--- binutils_060913_org/gas/testsuite/gas/i386/i386.exp	2006-07-14 00:25:46.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/i386.exp	2006-09-11 16:09:42.000000000 +0200
@@ -155,7 +155,9 @@
     run_dump_test "x86-64-rep-suffix"
     run_dump_test "x86-64-gidt"
     run_dump_test "x86-64-nops"
+    if ![istarget "*-*-mingw64*"] then {
     run_dump_test "x86-64-nops-1"
+    }
     run_dump_test "x86-64-nops-1-k8"
     run_dump_test "x86-64-nops-1-nocona"
     run_dump_test "x86-64-nops-1-merom"
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/immed64.d binutils_060913/gas/testsuite/gas/i386/immed64.d
--- binutils_060913_org/gas/testsuite/gas/i386/immed64.d	2005-07-26 17:34:11.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/immed64.d	2006-09-11 14:29:36.000000000 +0200
@@ -57,3 +57,4 @@
 [ 	]*[0-9a-fA-F]+:[ 	]+e5 04[ 	]+inl? +\$0x4,%eax
 [ 	]*[0-9a-fA-F]+:[ 	]+e5 08[ 	]+inl? +\$0x8,%eax
 [ 	]*[0-9a-fA-F]+:[ 	]+e5 00[ 	]+inl? +\$0x0,%eax
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/rex.d binutils_060913/gas/testsuite/gas/i386/rex.d
--- binutils_060913_org/gas/testsuite/gas/i386/rex.d	2005-12-14 09:57:06.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/rex.d	2006-09-11 14:30:06.000000000 +0200
@@ -1,7 +1,7 @@
 #objdump: -dw
 #name: x86-64 manual rex prefix use
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-addr32.d binutils_060913/gas/testsuite/gas/i386/x86-64-addr32.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-addr32.d	2004-07-21 18:09:43.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-addr32.d	2006-09-11 14:31:36.000000000 +0200
@@ -2,7 +2,7 @@
 #objdump: -drw
 #name: x86-64 32-bit addressing
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -11,3 +11,4 @@
 [	 ]*8:[	 ]+67 49 8d 80 00 00 00 00[	 ]+addr32[	 ]+lea[ 	]+0x0\(%r8d?\),%rax.*
 [	 ]*10:[	 ]+67 48 8d 05 00 00 00 00[	 ]+addr32[	 ]+lea[ 	]+0\(%[re]ip\),%rax.*
 [	 ]*18:[	 ]+67 48 8d 04 25 00 00 00 00[	 ]+addr32[	 ]+lea[ 	]+0x0,%rax.*
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-branch.d binutils_060913/gas/testsuite/gas/i386/x86-64-branch.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-branch.d	2005-05-07 15:30:02.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-branch.d	2006-09-11 14:32:00.000000000 +0200
@@ -2,7 +2,7 @@
 #objdump: -drw
 #name: x86-64 indirect branch
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -11,3 +11,4 @@
 [	 ]*2:[	 ]+ff d0[	 ]+callq[	 ]+\*%rax
 [	 ]*4:[	 ]+ff e0[	 ]+jmpq[	 ]+\*%rax
 [	 ]*6:[	 ]+ff e0[	 ]+jmpq[	 ]+\*%rax
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-crx-suffix.d binutils_060913/gas/testsuite/gas/i386/x86-64-crx-suffix.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-crx-suffix.d	2006-02-12 18:26:21.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-crx-suffix.d	2006-09-11 14:33:10.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 control register related opcodes (with suffixes)
 #source: x86-64-crx.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -19,3 +19,4 @@
 [ 	]*[0-9a-f]+:	44 0f 20 c7[ 	]+movq[ 	]+?%cr8,%rdi
 [ 	]*[0-9a-f]+:	44 0f 22 c0[ 	]+movq[ 	]+?%rax,%cr8
 [ 	]*[0-9a-f]+:	44 0f 22 c7[ 	]+movq[ 	]+?%rdi,%cr8
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-crx.d binutils_060913/gas/testsuite/gas/i386/x86-64-crx.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-crx.d	2006-02-11 18:00:58.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-crx.d	2006-09-11 14:32:40.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 control register related opcodes
 #source: x86-64-crx.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -19,3 +19,4 @@
 [ 	]*[0-9a-f]+:	44 0f 20 c7[ 	]+movq?[ 	]+?%cr8,%rdi
 [ 	]*[0-9a-f]+:	44 0f 22 c0[ 	]+movq?[ 	]+?%rax,%cr8
 [ 	]*[0-9a-f]+:	44 0f 22 c7[ 	]+movq?[ 	]+?%rdi,%cr8
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-drx-suffix.d binutils_060913/gas/testsuite/gas/i386/x86-64-drx-suffix.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-drx-suffix.d	2006-02-11 19:08:35.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-drx-suffix.d	2006-09-11 14:33:44.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 debug register related opcodes (with suffixes)
 #source: x86-64-drx.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -19,3 +19,4 @@
 [ 	]*[0-9a-f]+:	44 0f 21 c7[ 	]+movq[ 	]+?%db8,%rdi
 [ 	]*[0-9a-f]+:	44 0f 23 c0[ 	]+movq[ 	]+?%rax,%db8
 [ 	]*[0-9a-f]+:	44 0f 23 c7[ 	]+movq[ 	]+?%rdi,%db8
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-drx.d binutils_060913/gas/testsuite/gas/i386/x86-64-drx.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-drx.d	2006-02-11 19:08:35.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-drx.d	2006-09-11 14:33:30.000000000 +0200
@@ -1,7 +1,7 @@
 #objdump: -dw
 #name: x86-64 debug register related opcodes
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -18,3 +18,4 @@
 [ 	]*[0-9a-f]+:	44 0f 21 c7[ 	]+movq?[ 	]+?%db8,%rdi
 [ 	]*[0-9a-f]+:	44 0f 23 c0[ 	]+movq?[ 	]+?%rax,%db8
 [ 	]*[0-9a-f]+:	44 0f 23 c7[ 	]+movq?[ 	]+?%rdi,%db8
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-opcode.d binutils_060913/gas/testsuite/gas/i386/x86-64-opcode.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-opcode.d	2006-07-18 22:25:40.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-opcode.d	2006-09-11 14:34:30.000000000 +0200
@@ -2,7 +2,7 @@
 #objdump: -drw
 #name: x86-64 opcode
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-pcrel.d binutils_060913/gas/testsuite/gas/i386/x86-64-pcrel.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-pcrel.d	2005-06-17 10:03:58.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-pcrel.d	2006-09-06 12:56:52.000000000 +0200
@@ -1,16 +1,16 @@
 #objdump: -drw
 #name: x86-64 pcrel
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
 0+000 <_start>:
-[	 ]*[0-9a-f]+:[	 ]+b0 00[	 ]+movb?[	 ]+\$(0x)?0,%al[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC8[	 ]+xtrn\+(0x)?1
-[	 ]*[0-9a-f]+:[	 ]+66 b8 00 00[	 ]+movw?[	 ]+\$(0x)?0,%ax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC16[	 ]+xtrn\+(0x)?2
-[	 ]*[0-9a-f]+:[	 ]+b8( 00){4}[	 ]+movl?[	 ]+\$(0x)?0,%eax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn\+(0x)?1
-[	 ]*[0-9a-f]+:[	 ]+48 c7 c0( 00){4}[	 ]+movq?[	 ]+\$(0x)?0,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn\+(0x)?3
-[	 ]*[0-9a-f]+:[	 ]+48 b8( 00){8}[	 ]+mov(abs)?q?[	 ]+\$(0x)?0,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC64[	 ]+xtrn\+(0x)?2
+[	 ]*[0-9a-f]+:[	 ]+b0 0[02]+[	 ]+movb?[	 ]+\$(0x)?[02]+,%al[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC8[	 ]+xtrn(\+(0x)?1)?
+[	 ]*[0-9a-f]+:[	 ]+66 b8 0[04]+ 00[	 ]+movw?[	 ]+\$(0x)?[04]+,%ax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC16[	 ]+xtrn(\+(0x)?2)?
+[	 ]*[0-9a-f]+:[	 ]+b8 0[05]+( 00){3}[	 ]+movl?[	 ]+\$(0x)?[05]+,%eax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn(\+(0x)?1)?
+[	 ]*[0-9a-f]+:[	 ]+48 c7 c0 0[07]+( 00){3}[	 ]+movq?[	 ]+\$(0x)?[07]+,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC32[	 ]+xtrn(\+(0x)?3)?
+[	 ]*[0-9a-f]+:[	 ]+48 b8 0[0a]+( 00){7}[	 ]+mov(abs)?q?[	 ]+\$(0x)?[0a]+,%rax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_PC64[	 ]+xtrn(\+(0x)?2)?
 [	 ]*[0-9a-f]+:[	 ]+b0 00[	 ]+movb?[	 ]+\$(0x)?0,%al[	 ]*[0-9a-f]+:[	 ]+R_X86_64_8[	 ]+xtrn
 [	 ]*[0-9a-f]+:[	 ]+66 b8 00 00[	 ]+movw?[	 ]+\$(0x)?0,%ax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_16[	 ]+xtrn
 [	 ]*[0-9a-f]+:[	 ]+b8( 00){4}[	 ]+movl?[	 ]+\$(0x)?0,%eax[	 ]*[0-9a-f]+:[	 ]+R_X86_64_32[	 ]+xtrn
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-rip.d binutils_060913/gas/testsuite/gas/i386/x86-64-rip.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-rip.d	2004-07-21 18:09:43.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-rip.d	2006-09-11 14:35:50.000000000 +0200
@@ -2,7 +2,7 @@
 #objdump: -drw
 #name: x86-64 rip addressing
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
@@ -11,3 +11,4 @@
 [	 ]*6:[	 ]+8d 05 11 11 11 11[	 ]+lea[	 ]+286331153\(%rip\),%eax[ 	]*(#.*)?
 [	 ]*c:[	 ]+8d 05 01 00 00 00[	 ]+lea[	 ]+1\(%rip\),%eax[ 	]*(#.*)?
 [	 ]*12:[	 ]+8d 05 00 00 00 00[	 ]+lea[	 ]+0\(%rip\),%eax[ 	]*(#.*)?
+#pass
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack-intel.d binutils_060913/gas/testsuite/gas/i386/x86-64-stack-intel.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack-intel.d	2005-09-28 17:34:51.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-stack-intel.d	2006-09-11 14:36:18.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 stack-related opcodes (Intel mode)
 #source: x86-64-stack.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack-suffix.d binutils_060913/gas/testsuite/gas/i386/x86-64-stack-suffix.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack-suffix.d	2005-09-28 17:34:51.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-stack-suffix.d	2006-09-11 14:36:46.000000000 +0200
@@ -2,7 +2,7 @@
 #name: x86-64 stack-related opcodes (with suffixes)
 #source: x86-64-stack.s
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack.d binutils_060913/gas/testsuite/gas/i386/x86-64-stack.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86-64-stack.d	2005-09-28 17:34:51.000000000 +0200
+++ binutils_060913/gas/testsuite/gas/i386/x86-64-stack.d	2006-09-11 14:37:04.000000000 +0200
@@ -1,7 +1,7 @@
 #objdump: -dw
 #name: x86-64 stack-related opcodes
 
-.*: +file format elf64-x86-64
+.*: +file format .*
 
 Disassembly of section .text:
 
diff -rNbu binutils_060913_org/gas/testsuite/gas/i386/x86_64.d binutils_060913/gas/testsuite/gas/i386/x86_64.d
--- binutils_060913_org/gas/testsuite/gas/i386/x86_64.d	2006-03-07 21:18:05.000000000 +0100
+++ binutils_060913/gas/testsuite/gas/i386/x86_64.d	2006-09-11 15:55:16.000000000 +0200
@@ -6,7 +6,7 @@
 
 Disassembly of section .text:
 
-0+ <bar-0x1a7>:
+0+ <.*>:
 [ 	]+0:	01 ca[ 	]+add[ 	]+%ecx,%edx
 [ 	]+2:	44 01 ca[ 	]+add[ 	]+%r9d,%edx
 [ 	]+5:	41 01 ca[ 	]+add[ 	]+%ecx,%r10d
diff -rNbu binutils_060913_org/include/coff/ChangeLog binutils_060913/include/coff/ChangeLog
--- binutils_060913_org/include/coff/ChangeLog	2006-02-05 12:57:34.000000000 +0100
+++ binutils_060913/include/coff/ChangeLog	2006-09-11 18:52:20.000000000 +0200
@@ -1,3 +1,14 @@
+2006-09-11	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* external.h:	Add proper external_aouthdr64 structure (without data_start member)
+		AOUTHDRSZ64:	Set according structure size
+		AOUTHDR64:		As typedef of external_aouthdr64 structure
+	* internal.h:	Add relocation identifiers for coff
+	* pe.h:	Add define IMAGE_FILE_MACHINE_AMD64 the coff signature
+		PEPAOUTHDR:		Adjust structure to have proper size (using AOUTHDR64)
+		PEPAOUTSZ:		Calculated size of 240
+	* x86_64.h:	Coff information for x86_64 (AMD64)
+
 2006-02-05  Arnold Metselaar  <arnold.metselaar@planet.nl>
 
 	* internal.h: Add relocation number R_IMM24 for Z80.
diff -rNbu binutils_060913_org/include/coff/external.h binutils_060913/include/coff/external.h
--- binutils_060913_org/include/coff/external.h	2005-05-10 12:21:09.000000000 +0200
+++ binutils_060913/include/coff/external.h	2006-09-11 12:30:40.000000000 +0200
@@ -55,6 +55,20 @@
 
 #define AOUTHDRSZ 28
 #define AOUTSZ 28
+
+typedef struct external_aouthdr64
+  {
+    char magic[2];	/* type of file				*/
+    char vstamp[2];	/* version stamp			*/
+    char tsize[4];	/* text size in bytes, padded to FW bdry*/
+    char dsize[4];	/* initialized data "  "		*/
+    char bsize[4];	/* uninitialized data "   "		*/
+    char entry[4];	/* entry pt.				*/
+    char text_start[4];	/* base of text used for this file 	*/
+  }
+AOUTHDR64;
+#define AOUTHDRSZ64	24
+
 #endif
 
 #ifndef DO_NOT_DEFINE_SCNHDR
diff -rNbu binutils_060913_org/include/coff/internal.h binutils_060913/include/coff/internal.h
--- binutils_060913_org/include/coff/internal.h	2006-02-05 12:57:34.000000000 +0100
+++ binutils_060913/include/coff/internal.h	2006-09-11 12:32:16.000000000 +0200
@@ -604,6 +604,24 @@
   unsigned long r_offset;	/* Used by Alpha ECOFF, SPARC, others */
 };
 
+/* X86-64 relocations */
+#define R_AMD64_ABS 0 /* Reference is absolute, no relocation is necessary */
+#define R_AMD64_DIR64	1 /* 64-bit address (VA) */
+#define R_AMD64_DIR32	2 /* 32-bit address (VA) R_DIR32 */
+#define R_AMD64_IMAGEBASE	 3 /* 32-bit absolute ref w/o base R_IMAGEBASE */
+#define R_AMD64_PCRLONG		 4 /* 32-bit relative address from byte following reloc R_PCRLONG */
+#define R_AMD64_PCRLONG_1		 5 /* 32-bit relative address from byte distance 1 from reloc */
+#define R_AMD64_PCRLONG_2		 6 /* 32-bit relative address from byte distance 2 from reloc */
+#define R_AMD64_PCRLONG_3		 7 /* 32-bit relative address from byte distance 3 from reloc */
+#define R_AMD64_PCRLONG_4		 8 /* 32-bit relative address from byte distance 4 from reloc */
+#define R_AMD64_PCRLONG_5		 9 /* 32-bit relative address from byte distance 5 from reloc */
+#define R_AMD64_SECTION	10 /* Section index */
+#define R_AMD64_SECREL	11 /* 32 bit offset from base of section containing target R_SECREL*/
+#define R_AMD64_SECREL7	12 /* 7 bit unsigned offset from base of section containing target */
+#define R_AMD64_TOKEN	13 /* 32 bit metadata token */
+/* Pseude PC64 relocation - note not specified by MS/AMD but need for gas pc-relative 64bit wide relocation generated by elf*/
+#define R_AMD64_PCRQUAD	14
+
 #define R_DIR16 	 1
 #define R_REL24          5
 #define R_DIR32 	 6
diff -rNbu binutils_060913_org/include/coff/pe.h binutils_060913/include/coff/pe.h
--- binutils_060913_org/include/coff/pe.h	2005-05-10 12:21:09.000000000 +0200
+++ binutils_060913/include/coff/pe.h	2006-09-11 12:33:56.000000000 +0200
@@ -119,6 +119,7 @@
 #define IMAGE_FILE_MACHINE_THUMB             0x01c2
 #define IMAGE_FILE_MACHINE_TRICORE           0x0520
 #define IMAGE_FILE_MACHINE_WCEMIPSV2         0x0169
+#define IMAGE_FILE_MACHINE_AMD64             0x8664  // AMD64 (K8)
 
 #define IMAGE_SUBSYSTEM_UNKNOWN			 0
 #define IMAGE_SUBSYSTEM_NATIVE			 1
@@ -267,7 +268,7 @@
    of just 4 bytes long.  */
 typedef struct 
 {
-  AOUTHDR standard;
+  AOUTHDR64 standard;
 
   /* NT extra fields; see internal.h for descriptions.  */
   char  ImageBase[8];
@@ -294,7 +295,7 @@
   /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];  */
   char  DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars.  */
 } PEPAOUTHDR;
-#define PEPAOUTSZ	240
+#define PEPAOUTSZ	(AOUTHDRSZ64+196+5*4) /* 240 */
   
 #undef  E_FILNMLEN
 #define E_FILNMLEN	18	/* # characters in a file name.  */
diff -rNbu binutils_060913_org/include/coff/x86_64.h binutils_060913/include/coff/x86_64.h
--- binutils_060913_org/include/coff/x86_64.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/include/coff/x86_64.h	2006-08-17 09:12:24.000000000 +0200
@@ -0,0 +1,67 @@
+/* coff information for AMD 64.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#define L_LNNO_SIZE 2
+#define INCLUDE_COMDAT_FIELDS_IN_AUXENT
+#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
+ 	F_AR32WR	file has byte ordering of an AR32WR machine (e.g. vax).  */
+
+#define F_RELFLG	(0x0001)
+#define F_EXEC		(0x0002)
+#define F_LNNO		(0x0004)
+#define F_LSYMS		(0x0008)
+
+#define AMD64MAGIC	0x8664
+
+#define AMD64BADMAG(x)	( (x).f_magic != AMD64MAGIC)
+#define IMAGE_NT_OPTIONAL_HDR64_MAGIC      0x20b
+
+#define OMAGIC          0404    /* object files, eg as output */
+#define ZMAGIC          IMAGE_NT_OPTIONAL_HDR64_MAGIC    /* demand load format, eg normal ld output 0x10b */
+#define STMAGIC		0401	/* target shlib */
+#define SHMAGIC		0443	/* host   shlib */
+
+/* define some NT default values */
+/*  #define NT_IMAGE_BASE        0x400000 moved to internal.h */
+#define NT_SECTION_ALIGNMENT 0x1000
+#define NT_FILE_ALIGNMENT    0x200
+#define NT_DEF_RESERVE       0x100000
+#define NT_DEF_COMMIT        0x1000
+
+/********************** 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 -rNbu binutils_060913_org/ld/ChangeLog binutils_060913/ld/ChangeLog
--- binutils_060913_org/ld/ChangeLog	2006-09-08 15:43:54.000000000 +0200
+++ binutils_060913/ld/ChangeLog	2006-09-13 11:20:51.000000000 +0200
@@ -1,3 +1,18 @@
+2006-09-13	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* configure:		Add new target x86_64-pc-mingw64
+	* configure.tgt:	Add definition of target emulation i386pep
+	* makefile.am:		Add new target files for target-all
+	* makefile.in:		Add new target files for target-all
+	* pe_dll.c:		Adjust to be inheritable by pep_dll.c as include. Fix memory out of bounds excess
+				for idata relocation section data.
+	* pep_dll.c:		Add target specific shared object handling
+	* pep_dll.h:		Add target specific definitions for shared object handling
+	* emulparams/i386pep.sh: Add new emulation params for target x86_64 coff
+	* emultempl/pep.em:	Add new emulation file for target x86_64 coff
+	* po/potfiles.in:		Add pepdll.c and pepdll.h
+	* scripttempl/pep.sc: Add linker script template for target x86_64 coff
+	
 2006-09-08  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* ld.texinfo: Document --dynamic-list-cpp-typeinfo.
diff -rNbu binutils_060913_org/ld/Makefile.am binutils_060913/ld/Makefile.am
--- binutils_060913_org/ld/Makefile.am	2006-09-07 19:16:31.000000000 +0200
+++ binutils_060913/ld/Makefile.am	2006-09-11 14:46:32.000000000 +0200
@@ -239,6 +239,7 @@
 	ei386nto.o \
 	ei386nw.o \
 	ei386pe.o \
+	ei386pep.o \
 	ei386pe_posix.o \
 	elnk960.o \
 	em32relf.o \
@@ -411,15 +412,16 @@
 
 ALL_EMUL_EXTRA_OFILES = \
 	deffilep.o \
-	pe-dll.o
+	pe-dll.o \
+	pep-dll.o
 
 CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \
 	ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \
-	mri.c ldcref.c pe-dll.c
+	mri.c ldcref.c pe-dll.c pep-dll.c
 
 HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
 	ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
-	ldwrite.h mri.h deffile.h pe-dll.h elf-hints-local.h
+	ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h elf-hints-local.h
 
 GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
 GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
@@ -1099,6 +1101,9 @@
 ei386pe.c: $(srcdir)/emulparams/i386pe.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe "$(tdir_i386pe)"
+ei386pep.c: $(srcdir)/emulparams/i386pep.sh \
+  $(srcdir)/emultempl/pep.em $(srcdir)/scripttempl/pep.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} i386pep "$(tdir_i386pe)"
 ei386pe_posix.c: $(srcdir)/emulparams/i386pe_posix.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe_posix "$(tdir_i386pe_posix)"
@@ -1965,6 +1970,12 @@
   ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
   ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
   $(BFDDIR)/libcoff.h deffile.h pe-dll.h
+pep-dll.o: pep-dll.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h $(INCDIR)/safe-ctype.h \
+  ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
+  ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
+  $(BFDDIR)/libcoff.h deffile.h pep-dll.h
 ldgram.o: ldgram.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
   $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
   $(INCDIR)/bfdlink.h ld.h $(INCDIR)/bin-bugs.h ldexp.h \
diff -rNbu binutils_060913_org/ld/Makefile.in binutils_060913/ld/Makefile.in
--- binutils_060913_org/ld/Makefile.in	2006-09-07 19:16:32.000000000 +0200
+++ binutils_060913/ld/Makefile.in	2006-09-11 14:50:34.000000000 +0200
@@ -463,6 +463,7 @@
 	ei386nto.o \
 	ei386nw.o \
 	ei386pe.o \
+	ei386pep.o \
 	ei386pe_posix.o \
 	elnk960.o \
 	em32relf.o \
@@ -635,15 +636,16 @@
 
 ALL_EMUL_EXTRA_OFILES = \
 	deffilep.o \
-	pe-dll.o
+	pe-dll.o \
+	pep-dll.o
 
 CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \
 	ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \
-	mri.c ldcref.c pe-dll.c
+	mri.c ldcref.c pe-dll.c pep-dll.c
 
 HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
 	ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
-	ldwrite.h mri.h deffile.h pe-dll.h elf-hints-local.h
+	ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h elf-hints-local.h
 
 GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
 GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
@@ -1910,6 +1912,9 @@
 ei386pe.c: $(srcdir)/emulparams/i386pe.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe "$(tdir_i386pe)"
+ei386pep.c: $(srcdir)/emulparams/i386pep.sh \
+  $(srcdir)/emultempl/pep.em $(srcdir)/scripttempl/pep.sc ${GEN_DEPENDS}
+	${GENSCRIPTS} i386pep "$(tdir_i386pe)"
 ei386pe_posix.c: $(srcdir)/emulparams/i386pe_posix.sh \
   $(srcdir)/emultempl/pe.em $(srcdir)/scripttempl/pe.sc ${GEN_DEPENDS}
 	${GENSCRIPTS} i386pe_posix "$(tdir_i386pe_posix)"
@@ -2746,6 +2751,12 @@
   ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
   ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
   $(BFDDIR)/libcoff.h deffile.h pe-dll.h
+pep-dll.o: pep-dll.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
+  $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
+  $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h $(INCDIR)/safe-ctype.h \
+  ld.h $(INCDIR)/bin-bugs.h ldexp.h ldlang.h ldwrite.h \
+  ldmisc.h ldgram.h ldmain.h ldfile.h ldemul.h $(INCDIR)/coff/internal.h \
+  $(BFDDIR)/libcoff.h deffile.h pep-dll.h
 ldgram.o: ldgram.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \
   $(INCDIR)/symcat.h sysdep.h config.h $(INCDIR)/fopen-same.h \
   $(INCDIR)/bfdlink.h ld.h $(INCDIR)/bin-bugs.h ldexp.h \
diff -rNbu binutils_060913_org/ld/configure binutils_060913/ld/configure
--- binutils_060913_org/ld/configure	2006-07-10 16:30:41.000000000 +0200
+++ binutils_060913/ld/configure	2006-09-11 14:47:58.000000000 +0200
@@ -3923,7 +3923,7 @@
   rm -rf conftest*
   ;;
 
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|x86_64-*mingw64*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # Find out which ABI we are using.
   echo 'int i;' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
@@ -3953,6 +3953,9 @@
         x86_64-*linux*)
           LD="${LD-ld} -m elf_x86_64"
           ;;
+        x86_64-*mingw64*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
         ppc*-*linux*|powerpc*-*linux*)
           LD="${LD-ld} -m elf64ppc"
           ;;
diff -rNbu binutils_060913_org/ld/configure.tgt binutils_060913/ld/configure.tgt
--- binutils_060913_org/ld/configure.tgt	2006-08-22 13:50:33.000000000 +0200
+++ binutils_060913/ld/configure.tgt	2006-09-11 14:43:28.000000000 +0200
@@ -155,6 +155,8 @@
 			  targ_extra_emuls="$targ_extra_emuls elf_x86_64"
 			fi
 			tdir_i386linux=${targ_alias}aout ;;
+x86_64-*-mingw64*) targ_emul=i386pep ;
+			targ_extra_ofiles="deffilep.o pep-dll.o" ;;
 x86_64-*-linux-*)	targ_emul=elf_x86_64
 			targ_extra_emuls="elf_i386 i386linux"
 			targ_extra_libpath=elf_i386
diff -rNbu binutils_060913_org/ld/emulparams/i386pep.sh binutils_060913/ld/emulparams/i386pep.sh
--- binutils_060913_org/ld/emulparams/i386pep.sh	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/ld/emulparams/i386pep.sh	2006-07-28 12:43:22.000000000 +0200
@@ -0,0 +1,9 @@
+ARCH="i386:x86-64"
+SCRIPT_NAME=pep
+OUTPUT_FORMAT="pei-x86-64"
+RELOCATEABLE_OUTPUT_FORMAT="pe-x86-64"
+TEMPLATE_NAME=pep
+ENTRY="_mainCRTStartup"
+SUBSYSTEM=PE_DEF_SUBSYSTEM
+INITIAL_SYMBOL_CHAR=\"_\"
+TARGET_PAGE_SIZE=0x1000
diff -rNbu binutils_060913_org/ld/emultempl/pep.em binutils_060913/ld/emultempl/pep.em
--- binutils_060913_org/ld/emultempl/pep.em	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/ld/emultempl/pep.em	2006-09-06 14:26:52.000000000 +0200
@@ -0,0 +1,1749 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+test -z "${ENTRY}" && ENTRY="_mainCRTStartup"
+if [ -z "$MACHINE" ]; then
+  OUTPUT_ARCH=${ARCH}
+else
+  OUTPUT_ARCH=${ARCH}:${MACHINE}
+fi
+rm -f e${EMULATION_NAME}.c
+(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
+cat >>e${EMULATION_NAME}.c <<EOF
+/* This file is part of GLD, the Gnu Linker.
+   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+   */
+
+/* For WINDOWS_XP64 and higher */
+/* The original file generated returned different default scripts depending
+   on whether certain switches were set, but these switches pertain to the
+   Linux system and that particular version of coff.  In the NT case, we
+   only determine if the subsystem is console or windows in order to select
+   the correct entry point by default. */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "getopt.h"
+#include "libiberty.h"
+#include "ld.h"
+#include "ldmain.h"
+#include "ldexp.h"
+#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
+#include <ldgram.h>
+#include "ldlex.h"
+#include "ldmisc.h"
+#include "ldctor.h"
+#include "coff/internal.h"
+
+/* FIXME: See bfd/peXXigen.c for why we include an architecture specific
+   header in generic PE code.  */
+#include "coff/x86_64.h"
+#include "coff/pe.h"
+
+/* FIXME: This is a BFD internal header file, and we should not be
+   using it here.  */
+#include "../bfd/libcoff.h"
+
+#undef AOUTSZ
+#define AOUTSZ		PEPAOUTSZ
+#define PEAOUTHDR	PEPAOUTHDR
+
+#include "deffile.h"
+#include "pep-dll.h"
+#include "safe-ctype.h"
+
+/* Permit the emulation parameters to override the default section
+   alignment by setting OVERRIDE_SECTION_ALIGNMENT.  FIXME: This makes
+   it seem that include/coff/internal.h should not define
+   PE_DEF_SECTION_ALIGNMENT.  */
+#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT}
+#undef PE_DEF_SECTION_ALIGNMENT
+#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT}
+#endif
+
+#ifdef TARGET_IS_i386pep
+#define DLL_SUPPORT
+#endif
+
+#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT)
+#define	PE_DEF_SUBSYSTEM		3
+#else
+#undef NT_EXE_IMAGE_BASE
+#undef PE_DEF_SECTION_ALIGNMENT
+#undef PE_DEF_FILE_ALIGNMENT
+#define NT_EXE_IMAGE_BASE		0x00010000
+#define PE_DEF_SECTION_ALIGNMENT	0x00000400
+#define	PE_DEF_SUBSYSTEM		2
+#define PE_DEF_FILE_ALIGNMENT		0x00000200
+#endif
+
+
+static struct internal_extra_pe_aouthdr pep;
+static int dll;
+static flagword real_flags = IMAGE_FILE_LARGE_ADDRESS_AWARE;
+static int support_old_code = 0;
+static char * thumb_entry_symbol = NULL;
+static lang_assignment_statement_type *image_base_statement = 0;
+
+#ifdef DLL_SUPPORT
+static int pep_enable_stdcall_fixup = -1; /* 0=disable 1=enable.  */
+static char *pep_out_def_filename = NULL;
+static char *pep_implib_filename = NULL;
+static int pep_enable_auto_image_base = 0;
+static char *pep_dll_search_prefix = NULL;
+#endif
+
+extern const char *output_filename;
+
+static void
+gld_${EMULATION_NAME}_before_parse (void)
+{
+  ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
+  output_filename = "${EXECUTABLE_NAME:-a.exe}";
+#ifdef DLL_SUPPORT
+  config.dynamic_link = TRUE;
+  config.has_shared = 1;
+  link_info.pei386_auto_import = -1;
+  link_info.pei386_runtime_pseudo_reloc = -1;
+
+#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
+#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
+  lang_default_entry ("WinMainCRTStartup");
+#else
+  lang_default_entry ("_WinMainCRTStartup");
+#endif
+#else
+  lang_default_entry ("${ENTRY}");
+#endif
+#endif
+}
+\f
+/* PE format extra command line options.  */
+
+/* Used for setting flags in the PE header.  */
+#define OPTION_BASE_FILE		(300  + 1)
+#define OPTION_DLL			(OPTION_BASE_FILE + 1)
+#define OPTION_FILE_ALIGNMENT		(OPTION_DLL + 1)
+#define OPTION_IMAGE_BASE		(OPTION_FILE_ALIGNMENT + 1)
+#define OPTION_MAJOR_IMAGE_VERSION	(OPTION_IMAGE_BASE + 1)
+#define OPTION_MAJOR_OS_VERSION		(OPTION_MAJOR_IMAGE_VERSION + 1)
+#define OPTION_MAJOR_SUBSYSTEM_VERSION	(OPTION_MAJOR_OS_VERSION + 1)
+#define OPTION_MINOR_IMAGE_VERSION	(OPTION_MAJOR_SUBSYSTEM_VERSION + 1)
+#define OPTION_MINOR_OS_VERSION		(OPTION_MINOR_IMAGE_VERSION + 1)
+#define OPTION_MINOR_SUBSYSTEM_VERSION	(OPTION_MINOR_OS_VERSION + 1)
+#define OPTION_SECTION_ALIGNMENT	(OPTION_MINOR_SUBSYSTEM_VERSION + 1)
+#define OPTION_STACK			(OPTION_SECTION_ALIGNMENT + 1)
+#define OPTION_SUBSYSTEM		(OPTION_STACK + 1)
+#define OPTION_HEAP			(OPTION_SUBSYSTEM + 1)
+#define OPTION_SUPPORT_OLD_CODE		(OPTION_HEAP + 1)
+#define OPTION_OUT_DEF			(OPTION_SUPPORT_OLD_CODE + 1)
+#define OPTION_EXPORT_ALL		(OPTION_OUT_DEF + 1)
+#define OPTION_EXCLUDE_SYMBOLS		(OPTION_EXPORT_ALL + 1)
+#define OPTION_KILL_ATS			(OPTION_EXCLUDE_SYMBOLS + 1)
+#define OPTION_STDCALL_ALIASES		(OPTION_KILL_ATS + 1)
+#define OPTION_ENABLE_STDCALL_FIXUP	(OPTION_STDCALL_ALIASES + 1)
+#define OPTION_DISABLE_STDCALL_FIXUP	(OPTION_ENABLE_STDCALL_FIXUP + 1)
+#define OPTION_IMPLIB_FILENAME		(OPTION_DISABLE_STDCALL_FIXUP + 1)
+#define OPTION_THUMB_ENTRY		(OPTION_IMPLIB_FILENAME + 1)
+#define OPTION_WARN_DUPLICATE_EXPORTS	(OPTION_THUMB_ENTRY + 1)
+#define OPTION_IMP_COMPAT		(OPTION_WARN_DUPLICATE_EXPORTS + 1)
+#define OPTION_ENABLE_AUTO_IMAGE_BASE	(OPTION_IMP_COMPAT + 1)
+#define OPTION_DISABLE_AUTO_IMAGE_BASE	(OPTION_ENABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_DLL_SEARCH_PREFIX	(OPTION_DISABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_NO_DEFAULT_EXCLUDES	(OPTION_DLL_SEARCH_PREFIX + 1)
+#define OPTION_DLL_ENABLE_AUTO_IMPORT	(OPTION_NO_DEFAULT_EXCLUDES + 1)
+#define OPTION_DLL_DISABLE_AUTO_IMPORT	(OPTION_DLL_ENABLE_AUTO_IMPORT + 1)
+#define OPTION_ENABLE_EXTRA_PE_DEBUG	(OPTION_DLL_DISABLE_AUTO_IMPORT + 1)
+#define OPTION_EXCLUDE_LIBS		(OPTION_ENABLE_EXTRA_PE_DEBUG + 1)
+#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC	\
+					(OPTION_EXCLUDE_LIBS + 1)
+#define OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC	\
+					(OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC + 1)
+
+static void
+gld${EMULATION_NAME}_add_options
+  (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl,
+    struct option **longopts, int nrl ATTRIBUTE_UNUSED,
+    struct option **really_longopts ATTRIBUTE_UNUSED)
+{
+  static const struct option xtra_long[] = {
+    /* PE options */
+    {"base-file", required_argument, NULL, OPTION_BASE_FILE},
+    {"dll", no_argument, NULL, OPTION_DLL},
+    {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
+    {"heap", required_argument, NULL, OPTION_HEAP},
+    {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
+    {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
+    {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
+    {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},
+    {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION},
+    {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION},
+    {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION},
+    {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT},
+    {"stack", required_argument, NULL, OPTION_STACK},
+    {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
+    {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
+    {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
+#ifdef DLL_SUPPORT
+    /* getopt allows abbreviations, so we do this to stop it from treating -o
+       as an abbreviation for this option */
+    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
+    {"output-def", required_argument, NULL, OPTION_OUT_DEF},
+    {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
+    {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
+    {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
+    {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
+    {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
+    {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
+    {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
+    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
+    {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
+    /* getopt() allows abbreviations, so we do this to stop it from
+       treating -c as an abbreviation for these --compat-implib.  */
+    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
+    {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
+    {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE},
+    {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE},
+    {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX},
+    {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
+    {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT},
+    {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT},
+    {"enable-extra-pep-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG},
+    {"enable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC},
+    {"disable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC},
+#endif
+    {NULL, no_argument, NULL, 0}
+  };
+
+  *longopts = (struct option *)
+    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
+  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
+}
+
+/* PE/WIN32; added routines to get the subsystem type, heap and/or stack
+   parameters which may be input from the command line.  */
+
+typedef struct
+{
+  void *ptr;
+  int size;
+  int value;
+  char *symbol;
+  int inited;
+} definfo;
+
+#define D(field,symbol,def)  {&pep.field,sizeof(pep.field), def, symbol,0}
+
+static definfo init[] =
+{
+  /* imagebase must be first */
+#define IMAGEBASEOFF 0
+  D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE),
+#define DLLOFF 1
+  {&dll, sizeof(dll), 0, "__dll__", 0},
+#define MSIMAGEBASEOFF	2
+  D(ImageBase,"__ImageBase", NT_EXE_IMAGE_BASE),
+  D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT),
+  D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT),
+  D(MajorOperatingSystemVersion,"__major_os_version__", 4),
+  D(MinorOperatingSystemVersion,"__minor_os_version__", 0),
+  D(MajorImageVersion,"__major_image_version__", 0),
+  D(MinorImageVersion,"__minor_image_version__", 0),
+  D(MajorSubsystemVersion,"__major_subsystem_version__", 5),
+  D(MinorSubsystemVersion,"__minor_subsystem_version__", 2),
+  D(Subsystem,"__subsystem__", ${SUBSYSTEM}),
+  D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000),
+  D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
+  D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
+  D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000),
+  D(LoaderFlags,"__loader_flags__", 0x0),
+  { NULL, 0, 0, NULL, 0 }
+};
+
+
+static void
+gld_${EMULATION_NAME}_list_options (FILE *file)
+{
+  fprintf (file, _("  --base_file <basefile>             Generate a base file for relocatable DLLs\n"));
+  fprintf (file, _("  --dll                              Set image base to the default for DLLs\n"));
+  fprintf (file, _("  --file-alignment <size>            Set file alignment\n"));
+  fprintf (file, _("  --heap <size>                      Set initial size of the heap\n"));
+  fprintf (file, _("  --image-base <address>             Set start address of the executable\n"));
+  fprintf (file, _("  --major-image-version <number>     Set version number of the executable\n"));
+  fprintf (file, _("  --major-os-version <number>        Set minimum required OS version\n"));
+  fprintf (file, _("  --major-subsystem-version <number> Set minimum required OS subsystem version\n"));
+  fprintf (file, _("  --minor-image-version <number>     Set revision number of the executable\n"));
+  fprintf (file, _("  --minor-os-version <number>        Set minimum required OS revision\n"));
+  fprintf (file, _("  --minor-subsystem-version <number> Set minimum required OS subsystem revision\n"));
+  fprintf (file, _("  --section-alignment <size>         Set section alignment\n"));
+  fprintf (file, _("  --stack <size>                     Set size of the initial stack\n"));
+  fprintf (file, _("  --subsystem <name>[:<version>]     Set required OS subsystem [& version]\n"));
+  fprintf (file, _("  --support-old-code                 Support interworking with old code\n"));
+  fprintf (file, _("  --thumb-entry=<symbol>             Set the entry point to be Thumb <symbol>\n"));
+#ifdef DLL_SUPPORT
+  fprintf (file, _("  --add-stdcall-alias                Export symbols with and without @nn\n"));
+  fprintf (file, _("  --disable-stdcall-fixup            Don't link _sym to _sym@nn\n"));
+  fprintf (file, _("  --enable-stdcall-fixup             Link _sym to _sym@nn without warnings\n"));
+  fprintf (file, _("  --exclude-symbols sym,sym,...      Exclude symbols from automatic export\n"));
+  fprintf (file, _("  --exclude-libs lib,lib,...         Exclude libraries from automatic export\n"));
+  fprintf (file, _("  --export-all-symbols               Automatically export all globals to DLL\n"));
+  fprintf (file, _("  --kill-at                          Remove @nn from exported symbols\n"));
+  fprintf (file, _("  --out-implib <file>                Generate import library\n"));
+  fprintf (file, _("  --output-def <file>                Generate a .DEF file for the built DLL\n"));
+  fprintf (file, _("  --warn-duplicate-exports           Warn about duplicate exports.\n"));
+  fprintf (file, _("  --compat-implib                    Create backward compatible import libs;\n\
+                                       create __imp_<SYMBOL> as well.\n"));
+  fprintf (file, _("  --enable-auto-image-base           Automatically choose image base for DLLs\n\
+                                       unless user specifies one\n"));
+  fprintf (file, _("  --disable-auto-image-base          Do not auto-choose image base. (default)\n"));
+  fprintf (file, _("  --dll-search-prefix=<string>       When linking dynamically to a dll without\n\
+                                       an importlib, use <string><basename>.dll\n\
+                                       in preference to lib<basename>.dll \n"));
+  fprintf (file, _("  --enable-auto-import               Do sophistcated linking of _sym to\n\
+                                       __imp_sym for DATA references\n"));
+  fprintf (file, _("  --disable-auto-import              Do not auto-import DATA items from DLLs\n"));
+  fprintf (file, _("  --enable-runtime-pseudo-reloc      Work around auto-import limitations by\n\
+                                       adding pseudo-relocations resolved at\n\
+                                       runtime.\n"));
+  fprintf (file, _("  --disable-runtime-pseudo-reloc     Do not add runtime pseudo-relocations for\n\
+                                       auto-imported DATA.\n"));
+  fprintf (file, _("  --enable-extra-pep-debug            Enable verbose debug output when building\n\
+                                       or linking to DLLs (esp. auto-import)\n"));
+#endif
+}
+
+
+static void
+set_pep_name (char *name, long val)
+{
+  int i;
+
+  /* Find the name and set it.  */
+  for (i = 0; init[i].ptr; i++)
+    {
+      if (strcmp (name, init[i].symbol) == 0)
+	{
+	  init[i].value = val;
+	  init[i].inited = 1;
+	  if(!strcmp(name,"__image_base__")) set_pep_name("__ImageBase",val);
+	  return;
+	}
+    }
+  abort ();
+}
+
+
+static void
+set_pep_subsystem (void)
+{
+  const char *sver;
+  const char *entry;
+  const char *initial_symbol_char;
+  char *end;
+  int len;
+  int i;
+  int subsystem;
+  unsigned long temp_subsystem;
+  static const struct
+    {
+      const char *name;
+      const int value;
+      const char *entry;
+    }
+  v[] =
+    {
+      { "native",  1, "NtProcessStartup" },
+      { "windows", 2, "WinMainCRTStartup" },
+      { "console", 3, "mainCRTStartup" },
+      { "posix",   7, "__PosixProcessStartup"},
+      { "wince",   9, "_WinMainCRTStartup" },
+      { "xbox",   14, "mainCRTStartup" },
+      { NULL, 0, NULL }
+    };
+  /* Entry point name for arbitrary subsystem numbers.  */
+  static const char default_entry[] = "mainCRTStartup";
+
+  /* Check for the presence of a version number.  */
+  sver = strchr (optarg, ':');
+  if (sver == NULL)
+    len = strlen (optarg);
+  else
+    {
+      len = sver - optarg;
+      set_pep_name ("__major_subsystem_version__",
+		   strtoul (sver + 1, &end, 0));
+      if (*end == '.')
+	set_pep_name ("__minor_subsystem_version__",
+		     strtoul (end + 1, &end, 0));
+      if (*end != '\0')
+	einfo (_("%P: warning: bad version number in -subsystem option\n"));
+    }
+
+  /* Check for numeric subsystem.  */
+  temp_subsystem = strtoul (optarg, & end, 0);
+  if ((*end == ':' || *end == '\0') && (temp_subsystem < 65536))
+    {
+      /* Search list for a numeric match to use its entry point.  */
+      for (i = 0; v[i].name; i++)
+	if (v[i].value == (int) temp_subsystem)
+	  break;
+
+      /* If no match, use the default.  */
+      if (v[i].name != NULL)
+	entry = v[i].entry;
+      else
+	entry = default_entry;
+
+      /* Use this subsystem.  */
+      subsystem = (int) temp_subsystem;
+    }
+  else
+    {
+      /* Search for subsystem by name.  */
+      for (i = 0; v[i].name; i++)
+	if (strncmp (optarg, v[i].name, len) == 0
+	    && v[i].name[len] == '\0')
+	  break;
+
+      if (v[i].name == NULL)
+	{
+	  einfo (_("%P%F: invalid subsystem type %s\n"), optarg);
+	  return;
+	}
+
+      entry = v[i].entry;
+      subsystem = v[i].value;
+    }
+
+  set_pep_name ("__subsystem__", subsystem);
+
+  initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
+  if (*initial_symbol_char != '\0')
+    {
+      char *alc_entry;
+
+      /* lang_default_entry expects its argument to be permanently
+	 allocated, so we don't free this string.  */
+      alc_entry = xmalloc (strlen (initial_symbol_char)
+			   + strlen (entry)
+			   + 1);
+      strcpy (alc_entry, initial_symbol_char);
+      strcat (alc_entry, entry);
+      entry = alc_entry;
+    }
+
+  lang_default_entry (entry);
+
+  return;
+}
+
+
+static void
+set_pep_value (char *name)
+{
+  char *end;
+
+  set_pep_name (name,  strtoul (optarg, &end, 0));
+
+  if (end == optarg)
+    einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg);
+
+  optarg = end;
+}
+
+
+static void
+set_pep_stack_heap (char *resname, char *comname)
+{
+  set_pep_value (resname);
+
+  if (*optarg == ',')
+    {
+      optarg++;
+      set_pep_value (comname);
+    }
+  else if (*optarg)
+    einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg);
+}
+
+
+static bfd_boolean
+gld${EMULATION_NAME}_handle_option (int optc)
+{
+  switch (optc)
+    {
+    default:
+      return FALSE;
+
+    case OPTION_BASE_FILE:
+      link_info.base_file = fopen (optarg, FOPEN_WB);
+      if (link_info.base_file == NULL)
+	{
+	  /* xgettext:c-format */
+	  fprintf (stderr, _("%s: Can't open base file %s\n"),
+		   program_name, optarg);
+	  xexit (1);
+	}
+      break;
+
+      /* PE options.  */
+    case OPTION_HEAP:
+      set_pep_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__");
+      break;
+    case OPTION_STACK:
+      set_pep_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__");
+      break;
+    case OPTION_SUBSYSTEM:
+      set_pep_subsystem ();
+      break;
+    case OPTION_MAJOR_OS_VERSION:
+      set_pep_value ("__major_os_version__");
+      break;
+    case OPTION_MINOR_OS_VERSION:
+      set_pep_value ("__minor_os_version__");
+      break;
+    case OPTION_MAJOR_SUBSYSTEM_VERSION:
+      set_pep_value ("__major_subsystem_version__");
+      break;
+    case OPTION_MINOR_SUBSYSTEM_VERSION:
+      set_pep_value ("__minor_subsystem_version__");
+      break;
+    case OPTION_MAJOR_IMAGE_VERSION:
+      set_pep_value ("__major_image_version__");
+      break;
+    case OPTION_MINOR_IMAGE_VERSION:
+      set_pep_value ("__minor_image_version__");
+      break;
+    case OPTION_FILE_ALIGNMENT:
+      set_pep_value ("__file_alignment__");
+      break;
+    case OPTION_SECTION_ALIGNMENT:
+      set_pep_value ("__section_alignment__");
+      break;
+    case OPTION_DLL:
+      set_pep_name ("__dll__", 1);
+      break;
+    case OPTION_IMAGE_BASE:
+      set_pep_value ("__image_base__");
+      break;
+    case OPTION_SUPPORT_OLD_CODE:
+      support_old_code = 1;
+      break;
+    case OPTION_THUMB_ENTRY:
+      thumb_entry_symbol = optarg;
+      break;
+#ifdef DLL_SUPPORT
+    case OPTION_OUT_DEF:
+      pep_out_def_filename = xstrdup (optarg);
+      break;
+    case OPTION_EXPORT_ALL:
+      pep_dll_export_everything = 1;
+      break;
+    case OPTION_EXCLUDE_SYMBOLS:
+      pep_dll_add_excludes (optarg, 0);
+      break;
+    case OPTION_EXCLUDE_LIBS:
+      pep_dll_add_excludes (optarg, 1);
+      break;
+    case OPTION_KILL_ATS:
+      pep_dll_kill_ats = 1;
+      break;
+    case OPTION_STDCALL_ALIASES:
+      pep_dll_stdcall_aliases = 1;
+      break;
+    case OPTION_ENABLE_STDCALL_FIXUP:
+      pep_enable_stdcall_fixup = 1;
+      break;
+    case OPTION_DISABLE_STDCALL_FIXUP:
+      pep_enable_stdcall_fixup = 0;
+      break;
+    case OPTION_IMPLIB_FILENAME:
+      pep_implib_filename = xstrdup (optarg);
+      break;
+    case OPTION_WARN_DUPLICATE_EXPORTS:
+      pep_dll_warn_dup_exports = 1;
+      break;
+    case OPTION_IMP_COMPAT:
+      pep_dll_compat_implib = 1;
+      break;
+    case OPTION_ENABLE_AUTO_IMAGE_BASE:
+      pep_enable_auto_image_base = 1;
+      break;
+    case OPTION_DISABLE_AUTO_IMAGE_BASE:
+      pep_enable_auto_image_base = 0;
+      break;
+    case OPTION_DLL_SEARCH_PREFIX:
+      pep_dll_search_prefix = xstrdup (optarg);
+      break;
+    case OPTION_NO_DEFAULT_EXCLUDES:
+      pep_dll_do_default_excludes = 0;
+      break;
+    case OPTION_DLL_ENABLE_AUTO_IMPORT:
+      link_info.pei386_auto_import = 1;
+      break;
+    case OPTION_DLL_DISABLE_AUTO_IMPORT:
+      link_info.pei386_auto_import = 0;
+      break;
+    case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC:
+      link_info.pei386_runtime_pseudo_reloc = 1;
+      break;
+    case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC:
+      link_info.pei386_runtime_pseudo_reloc = 0;
+      break;
+    case OPTION_ENABLE_EXTRA_PE_DEBUG:
+      pep_dll_extra_pe_debug = 1;
+      break;
+#endif
+    }
+  return TRUE;
+}
+\f
+
+#ifdef DLL_SUPPORT
+static unsigned long
+strhash (const char *str)
+{
+  const unsigned char *s;
+  unsigned long hash;
+  unsigned int c;
+  unsigned int len;
+
+  hash = 0;
+  len = 0;
+  s = (const unsigned char *) str;
+  while ((c = *s++) != '\0')
+    {
+      hash += c + (c << 17);
+      hash ^= hash >> 2;
+      ++len;
+    }
+  hash += len + (len << 17);
+  hash ^= hash >> 2;
+
+  return hash;
+}
+
+/* Use the output file to create a image base for relocatable DLLs.  */
+
+static unsigned long
+compute_dll_image_base (const char *ofile)
+{
+  unsigned long hash = strhash (ofile);
+  return 0x61300000 + ((hash << 16) & 0x0FFC0000);
+}
+#endif
+
+/* Assign values to the special symbols before the linker script is
+   read.  */
+
+static void
+gld_${EMULATION_NAME}_set_symbols (void)
+{
+  /* Run through and invent symbols for all the
+     names and insert the defaults.  */
+  int j;
+  lang_statement_list_type *save;
+
+  if (!init[IMAGEBASEOFF].inited)
+    {
+      if (link_info.relocatable)
+	init[IMAGEBASEOFF].value = 0;
+      else if (init[DLLOFF].value || (link_info.shared && !link_info.pie))
+#ifdef DLL_SUPPORT
+	init[IMAGEBASEOFF].value = (pep_enable_auto_image_base) ?
+	  compute_dll_image_base (output_filename) : NT_DLL_IMAGE_BASE;
+#else
+	init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE;
+#endif
+      else
+	init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE;
+	init[MSIMAGEBASEOFF].value=init[IMAGEBASEOFF].value;
+    }
+
+  /* Don't do any symbol assignments if this is a relocatable link.  */
+  if (link_info.relocatable)
+    return;
+
+  /* Glue the assignments into the abs section.  */
+  save = stat_ptr;
+
+  stat_ptr = &(abs_output_section->children);
+
+  for (j = 0; init[j].ptr; j++)
+    {
+      long val = init[j].value;
+      lang_assignment_statement_type *rv;
+      rv = lang_add_assignment (exp_assop ('=', init[j].symbol,
+					   exp_intop (val)));
+      if (init[j].size == sizeof (short))
+	*(short *) init[j].ptr = val;
+      else if (init[j].size == sizeof (int))
+	*(int *) init[j].ptr = val;
+      else if (init[j].size == sizeof (long))
+	*(long *) init[j].ptr = val;
+      /* This might be a long long or other special type.  */
+      else if (init[j].size == sizeof (bfd_vma))
+	*(bfd_vma *) init[j].ptr = val;
+      else	abort ();
+      if (j == IMAGEBASEOFF)
+	image_base_statement = rv;
+    }
+	/* Restore the pointer.  */
+  stat_ptr = save;
+
+  if (pep.FileAlignment >
+      pep.SectionAlignment)
+    {
+      einfo (_("%P: warning, file alignment > section alignment.\n"));
+    }
+}
+
+/* This is called after the linker script and the command line options
+   have been read.  */
+
+static void
+gld_${EMULATION_NAME}_after_parse (void)
+{
+  /* The Windows libraries are designed for the linker to treat the
+     entry point as an undefined symbol.  Otherwise, the .obj that
+     defines mainCRTStartup is brought in because it is the first
+     encountered in libc.lib and it has other symbols in it which will
+     be pulled in by the link process.  To avoid this, we act as
+     though the user specified -u with the entry point symbol.
+
+     This function is called after the linker script and command line
+     options have been read, so at this point we know the right entry
+     point.  This function is called before the input files are
+     opened, so registering the symbol as undefined will make a
+     difference.  */
+
+  if (! link_info.relocatable && entry_symbol.name != NULL)
+    ldlang_add_undef (entry_symbol.name);
+}
+
+/* pep-dll.c directly accesses pep_data_import_dll,
+   so it must be defined outside of #ifdef DLL_SUPPORT.
+   Note - this variable is deliberately not initialised.
+   This allows it to be treated as a common varaible, and only
+   exist in one incarnation in a multiple target enabled linker.  */
+char * pep_data_import_dll;
+
+#ifdef DLL_SUPPORT
+static struct bfd_link_hash_entry *pep_undef_found_sym;
+
+static bfd_boolean
+pep_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
+{
+  int sl;
+  char *string = inf;
+
+  sl = strlen (string);
+  if (h->type == bfd_link_hash_defined
+      && strncmp (h->root.string, string, sl) == 0
+      && h->root.string[sl] == '@')
+    {
+      pep_undef_found_sym = h;
+      return FALSE;
+    }
+  return TRUE;
+}
+
+static void
+pep_fixup_stdcalls (void)
+{
+  static int gave_warning_message = 0;
+  struct bfd_link_hash_entry *undef, *sym;
+
+  if (pep_dll_extra_pe_debug)
+    printf ("%s\n", __FUNCTION__);
+
+  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
+    if (undef->type == bfd_link_hash_undefined)
+      {
+	char* at = strchr (undef->root.string, '@');
+	int lead_at = (*undef->root.string == '@');
+	/* For now, don't try to fixup fastcall symbols.  */
+
+	if (at && !lead_at)
+	  {
+	    /* The symbol is a stdcall symbol, so let's look for a
+	       cdecl symbol with the same name and resolve to that.  */
+	    char *cname = xstrdup (undef->root.string /* + lead_at */);
+	    at = strchr (cname, '@');
+	    *at = 0;
+	    sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1);
+
+	    if (sym && sym->type == bfd_link_hash_defined)
+	      {
+		undef->type = bfd_link_hash_defined;
+		undef->u.def.value = sym->u.def.value;
+		undef->u.def.section = sym->u.def.section;
+
+		if (pep_enable_stdcall_fixup == -1)
+		  {
+		    einfo (_("Warning: resolving %s by linking to %s\n"),
+			   undef->root.string, cname);
+		    if (! gave_warning_message)
+		      {
+			gave_warning_message = 1;
+			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
+			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
+		      }
+		  }
+	      }
+	  }
+	else
+	  {
+	    /* The symbol is a cdecl symbol, so we look for stdcall
+	       symbols - which means scanning the whole symbol table.  */
+	    pep_undef_found_sym = 0;
+	    bfd_link_hash_traverse (link_info.hash, pep_undef_cdecl_match,
+				    (char *) undef->root.string);
+	    sym = pep_undef_found_sym;
+	    if (sym)
+	      {
+		undef->type = bfd_link_hash_defined;
+		undef->u.def.value = sym->u.def.value;
+		undef->u.def.section = sym->u.def.section;
+
+		if (pep_enable_stdcall_fixup == -1)
+		  {
+		    einfo (_("Warning: resolving %s by linking to %s\n"),
+			   undef->root.string, sym->root.string);
+		    if (! gave_warning_message)
+		      {
+			gave_warning_message = 1;
+			einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
+			einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
+		      }
+		  }
+	      }
+	  }
+      }
+}
+
+static int
+make_import_fixup (arelent *rel, asection *s)
+{
+  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
+  char addend[4];
+
+  if (pep_dll_extra_pe_debug)
+    printf ("arelent: %s@%#lx: add=%li\n", sym->name,
+	    (long) rel->address, (long) rel->addend);
+
+  if (! bfd_get_section_contents (s->owner, s, addend, rel->address, sizeof (addend)))
+    einfo (_("%C: Cannot get section contents - auto-import exception\n"),
+	   s->owner, s, rel->address);
+
+  pep_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend));
+
+  return 1;
+}
+
+static void
+pep_find_data_imports (void)
+{
+  struct bfd_link_hash_entry *undef, *sym;
+
+  if (link_info.pei386_auto_import == 0)
+    return;
+
+  for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
+    {
+      if (undef->type == bfd_link_hash_undefined)
+	{
+	  /* C++ symbols are *long*.  */
+	  char buf[4096];
+
+	  if (pep_dll_extra_pe_debug)
+	    printf ("%s:%s\n", __FUNCTION__, undef->root.string);
+
+	  sprintf (buf, "__imp_%s", undef->root.string);
+
+	  sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
+
+	  if (sym && sym->type == bfd_link_hash_defined)
+	    {
+	      bfd *b = sym->u.def.section->owner;
+	      asymbol **symbols;
+	      int nsyms, symsize, i;
+
+	      if (link_info.pei386_auto_import == -1)
+		info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
+			  undef->root.string, buf);
+
+	      symsize = bfd_get_symtab_upper_bound (b);
+	      symbols = (asymbol **) xmalloc (symsize);
+	      nsyms = bfd_canonicalize_symtab (b, symbols);
+
+	      for (i = 0; i < nsyms; i++)
+		{
+		  if (memcmp (symbols[i]->name, "__head_",
+			      sizeof ("__head_") - 1))
+		    continue;
+
+		  if (pep_dll_extra_pe_debug)
+		    printf ("->%s\n", symbols[i]->name);
+
+		  pep_data_import_dll = (char*) (symbols[i]->name +
+						sizeof ("__head_") - 1);
+		  break;
+		}
+
+	      pep_walk_relocs_of_symbol (&link_info, undef->root.string,
+					make_import_fixup);
+
+	      /* Let's differentiate it somehow from defined.  */
+	      undef->type = bfd_link_hash_defweak;
+	      /* We replace original name with __imp_ prefixed, this
+		 1) may trash memory 2) leads to duplicate symbol generation.
+		 Still, IMHO it's better than having name poluted.  */
+	      undef->root.string = sym->root.string;
+	      undef->u.def.value = sym->u.def.value;
+	      undef->u.def.section = sym->u.def.section;
+	    }
+	}
+    }
+}
+
+static bfd_boolean
+pr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
+{
+  if (pep_dll_extra_pe_debug)
+    printf ("+%s\n", h->string);
+
+  return TRUE;
+}
+#endif /* DLL_SUPPORT */
+
+
+static void
+gld_${EMULATION_NAME}_after_open (void)
+{
+#ifdef DLL_SUPPORT
+  if (pep_dll_extra_pe_debug)
+    {
+      bfd *a;
+      struct bfd_link_hash_entry *sym;
+
+      printf ("%s()\n", __FUNCTION__);
+
+      for (sym = link_info.hash->undefs; sym; sym=sym->u.undef.next)
+	printf ("-%s\n", sym->root.string);
+      bfd_hash_traverse (&link_info.hash->table, pr_sym, NULL);
+
+      for (a = link_info.input_bfds; a; a = a->link_next)
+	printf ("*%s\n",a->filename);
+    }
+#endif
+
+  /* Pass the wacky PE command line options into the output bfd.
+     FIXME: This should be done via a function, rather than by
+     including an internal BFD header.  */
+
+  if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == 0)
+    einfo (_("%F%P: PE operations on non PE file.\n"));
+
+  pe_data (output_bfd)->pe_opthdr = pep;
+  pe_data (output_bfd)->dll = init[DLLOFF].value;
+  pe_data (output_bfd)->real_flags |= real_flags;
+
+#ifdef DLL_SUPPORT
+  if (pep_enable_stdcall_fixup) /* -1=warn or 1=disable */
+    pep_fixup_stdcalls ();
+
+  pep_process_import_defs (output_bfd, & link_info);
+
+  pep_find_data_imports ();
+
+#ifndef TARGET_IS_i386pep
+  if (link_info.shared)
+#else
+  if (!link_info.relocatable)
+#endif
+    pep_dll_build_sections (output_bfd, &link_info);
+
+#ifndef TARGET_IS_i386pep
+  else
+    pep_exe_build_sections (output_bfd, &link_info);
+#endif
+#endif
+
+  {
+    /* This next chunk of code tries to detect the case where you have
+       two import libraries for the same DLL (specifically,
+       symbolically linking libm.a and libc.a in cygwin to
+       libcygwin.a).  In those cases, it's possible for function
+       thunks from the second implib to be used but without the
+       head/tail objects, causing an improper import table.  We detect
+       those cases and rename the "other" import libraries to match
+       the one the head/tail come from, so that the linker will sort
+       things nicely and produce a valid import table.  */
+
+    LANG_FOR_EACH_INPUT_STATEMENT (is)
+      {
+	if (is->the_bfd->my_archive)
+	  {
+	    int idata2 = 0, reloc_count=0, is_imp = 0;
+	    asection *sec;
+
+	    /* See if this is an import library thunk.  */
+	    for (sec = is->the_bfd->sections; sec; sec = sec->next)
+	      {
+		if (strcmp (sec->name, ".idata\$2") == 0)
+		  idata2 = 1;
+		if (strncmp (sec->name, ".idata\$", 7) == 0)
+		  is_imp = 1;
+		reloc_count += sec->reloc_count;
+	      }
+
+	    if (is_imp && !idata2 && reloc_count)
+	      {
+		/* It is, look for the reference to head and see if it's
+		   from our own library.  */
+		for (sec = is->the_bfd->sections; sec; sec = sec->next)
+		  {
+		    int i;
+		    long symsize;
+		    long relsize;
+		    asymbol **symbols;
+		    arelent **relocs;
+		    int nrelocs;
+
+		    symsize = bfd_get_symtab_upper_bound (is->the_bfd);
+		    if (symsize < 1)
+		      break;
+		    relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
+		    if (relsize < 1)
+		      break;
+
+		    symbols = (asymbol **) xmalloc (symsize);
+		    symsize = bfd_canonicalize_symtab (is->the_bfd, symbols);
+		    if (symsize < 0)
+		      {
+			einfo ("%X%P: unable to process symbols: %E");
+			return;
+		      }
+
+		    relocs = (arelent **) xmalloc ((size_t) relsize);
+		    nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec,
+						      relocs, symbols);
+		    if (nrelocs < 0)
+		      {
+			free (relocs);
+			einfo ("%X%P: unable to process relocs: %E");
+			return;
+		      }
+
+		    for (i = 0; i < nrelocs; i++)
+		      {
+			struct bfd_symbol *s;
+			struct bfd_link_hash_entry * blhe;
+			char *other_bfd_filename;
+			char *n;
+
+			s = (relocs[i]->sym_ptr_ptr)[0];
+
+			if (s->flags & BSF_LOCAL)
+			  continue;
+
+			/* Thunk section with reloc to another bfd.  */
+			blhe = bfd_link_hash_lookup (link_info.hash,
+						     s->name,
+						     FALSE, FALSE, TRUE);
+
+			if (blhe == NULL
+			    || blhe->type != bfd_link_hash_defined)
+			  continue;
+
+			other_bfd_filename
+			  = blhe->u.def.section->owner->my_archive
+			    ? bfd_get_filename (blhe->u.def.section->owner->my_archive)
+			    : bfd_get_filename (blhe->u.def.section->owner);
+
+			if (strcmp (bfd_get_filename (is->the_bfd->my_archive),
+				    other_bfd_filename) == 0)
+			  continue;
+
+			/* Rename this implib to match the other one.  */
+			n = xmalloc (strlen (other_bfd_filename) + 1);
+			strcpy (n, other_bfd_filename);
+			is->the_bfd->my_archive->filename = n;
+		      }
+
+		    free (relocs);
+		    /* Note - we do not free the symbols,
+		       they are now cached in the BFD.  */
+		  }
+	      }
+	  }
+      }
+  }
+
+  {
+    int is_ms_arch = 0;
+    bfd *cur_arch = 0;
+    lang_input_statement_type *is2;
+    lang_input_statement_type *is3;
+
+    /* Careful - this is a shell script.  Watch those dollar signs! */
+    /* Microsoft import libraries have every member named the same,
+       and not in the right order for us to link them correctly.  We
+       must detect these and rename the members so that they'll link
+       correctly.  There are three types of objects: the head, the
+       thunks, and the sentinel(s).  The head is easy; it's the one
+       with idata2.  We assume that the sentinels won't have relocs,
+       and the thunks will.  It's easier than checking the symbol
+       table for external references.  */
+    LANG_FOR_EACH_INPUT_STATEMENT (is)
+      {
+	if (is->the_bfd->my_archive)
+	  {
+	    char *pnt;
+	    bfd *arch = is->the_bfd->my_archive;
+
+	    if (cur_arch != arch)
+	      {
+		cur_arch = arch;
+		is_ms_arch = 1;
+
+		for (is3 = is;
+		     is3 && is3->the_bfd->my_archive == arch;
+		     is3 = (lang_input_statement_type *) is3->next)
+		  {
+		    /* A MS dynamic import library can also contain static
+		       members, so look for the first element with a .dll
+		       extension, and use that for the remainder of the
+		       comparisons.  */
+		    pnt = strrchr (is3->the_bfd->filename, '.');
+		    if (pnt != NULL && strcmp (pnt, ".dll") == 0)
+		      break;
+		  }
+
+		if (is3 == NULL)
+		  is_ms_arch = 0;
+		else
+		  {
+		    /* OK, found one.  Now look to see if the remaining
+		       (dynamic import) members use the same name.  */
+		    for (is2 = is;
+			 is2 && is2->the_bfd->my_archive == arch;
+			 is2 = (lang_input_statement_type *) is2->next)
+		      {
+			/* Skip static members, ie anything with a .obj
+			   extension.  */
+			pnt = strrchr (is2->the_bfd->filename, '.');
+			if (pnt != NULL && strcmp (pnt, ".obj") == 0)
+			  continue;
+
+			if (strcmp (is3->the_bfd->filename,
+				    is2->the_bfd->filename))
+			  {
+			    is_ms_arch = 0;
+			    break;
+			  }
+		      }
+		  }
+	      }
+
+	    /* This fragment might have come from an .obj file in a Microsoft
+	       import, and not an actual import record. If this is the case,
+	       then leave the filename alone.  */
+	    pnt = strrchr (is->the_bfd->filename, '.');
+
+	    if (is_ms_arch && (strcmp (pnt, ".dll") == 0))
+	      {
+		int idata2 = 0, reloc_count=0;
+		asection *sec;
+		char *new_name, seq;
+
+		for (sec = is->the_bfd->sections; sec; sec = sec->next)
+		  {
+		    if (strcmp (sec->name, ".idata\$2") == 0)
+		      idata2 = 1;
+		    reloc_count += sec->reloc_count;
+		  }
+
+		if (idata2) /* .idata2 is the TOC */
+		  seq = 'a';
+		else if (reloc_count > 0) /* thunks */
+		  seq = 'b';
+		else /* sentinel */
+		  seq = 'c';
+
+		new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
+		sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
+		is->the_bfd->filename = new_name;
+
+		new_name = xmalloc (strlen (is->filename) + 3);
+		sprintf (new_name, "%s.%c", is->filename, seq);
+		is->filename = new_name;
+	      }
+	  }
+      }
+  }
+}
+
+static void
+gld_${EMULATION_NAME}_before_allocation (void)
+{
+  before_allocation_default ();
+}
+
+#ifdef DLL_SUPPORT
+/* This is called when an input file isn't recognized as a BFD.  We
+   check here for .DEF files and pull them in automatically.  */
+
+static int
+saw_option (char *option)
+{
+  int i;
+
+  for (i = 0; init[i].ptr; i++)
+    if (strcmp (init[i].symbol, option) == 0)
+      return init[i].inited;
+  return 0;
+}
+#endif /* DLL_SUPPORT */
+
+static bfd_boolean
+gld_${EMULATION_NAME}_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
+{
+#ifdef DLL_SUPPORT
+  const char *ext = entry->filename + strlen (entry->filename) - 4;
+
+  if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0)
+    {
+      pep_def_file = def_file_parse (entry->filename, pep_def_file);
+
+      if (pep_def_file)
+	{
+	  int i, buflen=0, len;
+	  char *buf;
+
+	  for (i = 0; i < pep_def_file->num_exports; i++)
+	    {
+	      len = strlen (pep_def_file->exports[i].internal_name);
+	      if (buflen < len + 2)
+		buflen = len + 2;
+	    }
+
+	  buf = (char *) xmalloc (buflen);
+
+	  for (i = 0; i < pep_def_file->num_exports; i++)
+	    {
+	      struct bfd_link_hash_entry *h;
+
+	      sprintf (buf, "_%s", pep_def_file->exports[i].internal_name);
+
+	      h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE);
+	      if (h == (struct bfd_link_hash_entry *) NULL)
+		einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
+	      if (h->type == bfd_link_hash_new)
+		{
+		  h->type = bfd_link_hash_undefined;
+		  h->u.undef.abfd = NULL;
+		  bfd_link_add_undef (link_info.hash, h);
+		}
+	    }
+	  free (buf);
+
+	  /* def_file_print (stdout, pep_def_file); */
+	  if (pep_def_file->is_dll == 1)
+	    link_info.shared = 1;
+
+	  if (pep_def_file->base_address != (bfd_vma)(-1))
+	    {
+	      pep.ImageBase =
+		pe_data (output_bfd)->pe_opthdr.ImageBase =
+		init[IMAGEBASEOFF].value = pep_def_file->base_address;
+	      init[IMAGEBASEOFF].inited = 1;
+	      if (image_base_statement)
+		image_base_statement->exp =
+		  exp_assop ('=', "__image_base__", exp_intop (pep.ImageBase));
+	    }
+
+	  if (pep_def_file->stack_reserve != -1
+	      && ! saw_option ("__size_of_stack_reserve__"))
+	    {
+	      pep.SizeOfStackReserve = pep_def_file->stack_reserve;
+	      if (pep_def_file->stack_commit != -1)
+		pep.SizeOfStackCommit = pep_def_file->stack_commit;
+	    }
+	  if (pep_def_file->heap_reserve != -1
+	      && ! saw_option ("__size_of_heap_reserve__"))
+	    {
+	      pep.SizeOfHeapReserve = pep_def_file->heap_reserve;
+	      if (pep_def_file->heap_commit != -1)
+		pep.SizeOfHeapCommit = pep_def_file->heap_commit;
+	    }
+	  return TRUE;
+	}
+    }
+#endif
+  return FALSE;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
+{
+#ifdef DLL_SUPPORT
+#ifdef TARGET_IS_i386pep
+  pep_dll_id_target ("pei-x86-64");
+#endif
+  if (bfd_get_format (entry->the_bfd) == bfd_object)
+    {
+      char fbuf[LD_PATHMAX + 1];
+      const char *ext;
+
+      if (REALPATH (entry->filename, fbuf) == NULL)
+	strncpy (fbuf, entry->filename, sizeof (fbuf));
+
+      ext = fbuf + strlen (fbuf) - 4;
+
+      if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0)
+	return pep_implied_import_dll (fbuf);
+    }
+#endif
+  return FALSE;
+}
+
+static void
+gld_${EMULATION_NAME}_finish (void)
+{
+#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe)
+  struct bfd_link_hash_entry * h;
+
+  if (thumb_entry_symbol != NULL)
+    {
+      h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
+				FALSE, FALSE, TRUE);
+
+      if (h != (struct bfd_link_hash_entry *) NULL
+	  && (h->type == bfd_link_hash_defined
+	      || h->type == bfd_link_hash_defweak)
+	  && h->u.def.section->output_section != NULL)
+	{
+	  static char buffer[32];
+	  bfd_vma val;
+
+	  /* Special procesing is required for a Thumb entry symbol.  The
+	     bottom bit of its address must be set.  */
+	  val = (h->u.def.value
+		 + bfd_get_section_vma (output_bfd,
+					h->u.def.section->output_section)
+		 + h->u.def.section->output_offset);
+
+	  val |= 1;
+
+	  /* Now convert this value into a string and store it in entry_symbol
+	     where the lang_finish() function will pick it up.  */
+	  buffer[0] = '0';
+	  buffer[1] = 'x';
+
+	  sprintf_vma (buffer + 2, val);
+
+	  if (entry_symbol.name != NULL && entry_from_cmdline)
+	    einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
+		   thumb_entry_symbol, entry_symbol.name);
+	  entry_symbol.name = buffer;
+	}
+      else
+	einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol);
+    }
+#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) */
+
+  finish_default ();
+
+#ifdef DLL_SUPPORT
+  if (link_info.shared
+    || (!link_info.relocatable && pep_def_file->num_exports != 0)
+    )
+    {
+      pep_dll_fill_sections (output_bfd, &link_info);
+      if (pep_implib_filename)
+	pep_dll_generate_implib (pep_def_file, pep_implib_filename);
+    }
+
+  if (pep_out_def_filename)
+    pep_dll_generate_def_file (pep_out_def_filename);
+#endif /* DLL_SUPPORT */
+
+  /* I don't know where .idata gets set as code, but it shouldn't be.  */
+  {
+    asection *asec = bfd_get_section_by_name (output_bfd, ".idata");
+
+    if (asec)
+      {
+	asec->flags &= ~SEC_CODE;
+	asec->flags |= SEC_DATA;
+      }
+  }
+}
+
+\f
+/* Place an orphan section.
+
+   We use this to put sections in a reasonable place in the file, and
+   to ensure that they are aligned as required.
+
+   We handle grouped sections here as well.  A section named .foo$nn
+   goes into the output section .foo.  All grouped sections are sorted
+   by name.
+
+   Grouped sections for the default sections are handled by the
+   default linker script using wildcards, and are sorted by
+   sort_sections.  */
+
+static bfd_boolean
+gld_${EMULATION_NAME}_place_orphan (asection *s)
+{
+  const char *secname;
+  const char *orig_secname;
+  char *dollar = NULL;
+  lang_output_section_statement_type *os;
+  lang_statement_list_type add_child;
+
+  secname = bfd_get_section_name (s->owner, s);
+
+  /* Look through the script to see where to place this section.  */
+  orig_secname = secname;
+  if (!link_info.relocatable
+      && (dollar = strchr (secname, '$')) != NULL)
+    {
+      size_t len = dollar - orig_secname;
+      char *newname = xmalloc (len + 1);
+      memcpy (newname, orig_secname, len);
+      newname[len] = '\0';
+      secname = newname;
+    }
+
+  os = lang_output_section_find (secname);
+
+  lang_list_init (&add_child);
+
+  if (os != NULL
+      && (os->bfd_section == NULL
+	  || os->bfd_section->flags == 0
+	  || ((s->flags ^ os->bfd_section->flags)
+	      & (SEC_LOAD | SEC_ALLOC)) == 0))
+    {
+      /* We already have an output section statement with this
+	 name, and its bfd section, if any, has compatible flags.
+	 If the section already exists but does not have any flags set,
+	 then it has been created by the linker, probably as a result of
+	 a --section-start command line switch.  */
+      lang_add_section (&add_child, s, os);
+    }
+  else
+    {
+      static struct orphan_save hold[] =
+	{
+	  { ".text",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
+	    0, 0, 0, 0 },
+	  { ".rdata",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
+	    0, 0, 0, 0 },
+	  { ".data",
+	    SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
+	    0, 0, 0, 0 },
+	  { ".bss",
+	    SEC_ALLOC,
+	    0, 0, 0, 0 }
+	};
+      enum orphan_save_index
+	{
+	  orphan_text = 0,
+	  orphan_rodata,
+	  orphan_data,
+	  orphan_bss
+	};
+      static int orphan_init_done = 0;
+      struct orphan_save *place;
+      lang_output_section_statement_type *after;
+      etree_type *address;
+
+      if (!orphan_init_done)
+	{
+	  struct orphan_save *ho;
+	  for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
+	    if (ho->name != NULL)
+	      {
+		ho->os = lang_output_section_find (ho->name);
+		if (ho->os != NULL && ho->os->flags == 0)
+		  ho->os->flags = ho->flags;
+	      }
+	  orphan_init_done = 1;
+	}
+
+      /* Try to put the new output section in a reasonable place based
+	 on the section name and section flags.  */
+
+      place = NULL;
+      if ((s->flags & SEC_ALLOC) == 0)
+	;
+      else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+	place = &hold[orphan_bss];
+      else if ((s->flags & SEC_READONLY) == 0)
+	place = &hold[orphan_data];
+      else if ((s->flags & SEC_CODE) == 0)
+	place = &hold[orphan_rodata];
+      else
+	place = &hold[orphan_text];
+
+      after = NULL;
+      if (place != NULL)
+	{
+	  if (place->os == NULL)
+	    place->os = lang_output_section_find (place->name);
+	  after = place->os;
+	  if (after == NULL)
+	    after = lang_output_section_find_by_flags (s, &place->os, NULL);
+	  if (after == NULL)
+	    /* *ABS* is always the first output section statement.  */
+	    after = (&lang_output_section_statement.head
+		     ->output_section_statement);
+	}
+
+      /* Choose a unique name for the section.  This will be needed if the
+	 same section name appears in the input file with different
+	 loadable or allocatable characteristics.  */
+      if (bfd_get_section_by_name (output_bfd, secname) != NULL)
+	{
+	  static int count = 1;
+	  secname = bfd_get_unique_section_name (output_bfd, secname, &count);
+	  if (secname == NULL)
+	    einfo ("%F%P: place_orphan failed: %E\n");
+	}
+
+      /* All sections in an executable must be aligned to a page boundary.  */
+      address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
+      os = lang_insert_orphan (s, secname, after, place, address, &add_child);
+    }
+
+  {
+    lang_statement_union_type **pl = &os->children.head;
+
+    if (dollar != NULL)
+      {
+	bfd_boolean found_dollar;
+
+	/* The section name has a '$'.  Sort it with the other '$'
+	   sections.  */
+	found_dollar = FALSE;
+	for ( ; *pl != NULL; pl = &(*pl)->header.next)
+	  {
+	    lang_input_section_type *ls;
+	    const char *lname;
+
+	    if ((*pl)->header.type != lang_input_section_enum)
+	      continue;
+
+	    ls = &(*pl)->input_section;
+
+	    lname = bfd_get_section_name (ls->section->owner, ls->section);
+	    if (strchr (lname, '$') == NULL)
+	      {
+		if (found_dollar)
+		  break;
+	      }
+	    else
+	      {
+		found_dollar = TRUE;
+		if (strcmp (orig_secname, lname) < 0)
+		  break;
+	      }
+	  }
+      }
+
+    if (add_child.head != NULL)
+      {
+	add_child.head->header.next = *pl;
+	*pl = add_child.head;
+      }
+  }
+
+  return TRUE;
+}
+
+static bfd_boolean
+gld_${EMULATION_NAME}_open_dynamic_archive
+  (const char *arch ATTRIBUTE_UNUSED, search_dirs_type *search,
+   lang_input_statement_type *entry)
+{
+  const char * filename;
+  char * string;
+
+  if (! entry->is_archive)
+    return FALSE;
+
+  filename = entry->filename;
+
+  string = (char *) xmalloc (strlen (search->name)
+			     + strlen (filename)
+			     + sizeof "/lib.a.dll"
+#ifdef DLL_SUPPORT
+			     + (pep_dll_search_prefix ? strlen (pep_dll_search_prefix) : 0)
+#endif
+			     + 1);
+
+  /* Try "libfoo.dll.a" first (preferred explicit import library for dll's.  */
+  sprintf (string, "%s/lib%s.dll.a", search->name, filename);
+
+  if (! ldfile_try_open_bfd (string, entry))
+    {
+      /* Try "foo.dll.a" next (alternate explicit import library for dll's.  */
+      sprintf (string, "%s/%s.dll.a", search->name, filename);
+      if (! ldfile_try_open_bfd (string, entry))
+	{
+	  /* Try libfoo.a next. Normally, this would be interpreted as a static
+	     library, but it *could* be an import library. For backwards compatibility,
+	     libfoo.a needs to ==precede== libfoo.dll and foo.dll in the search,
+	     or sometimes errors occur when building legacy packages.
+
+	     Putting libfoo.a here means that in a failure case (i.e. the library
+	     -lfoo is not found) we will search for libfoo.a twice before
+	     giving up -- once here, and once when searching for a "static" lib.
+	     for a "static" lib.  */
+	  /* Try "libfoo.a" (import lib, or static lib, but must
+	     take precedence over dll's).  */
+	  sprintf (string, "%s/lib%s.a", search->name, filename);
+	  if (! ldfile_try_open_bfd (string, entry))
+	    {
+#ifdef DLL_SUPPORT
+	      if (pep_dll_search_prefix)
+		{
+		  /* Try "<prefix>foo.dll" (preferred dll name, if specified).  */
+		  sprintf (string, "%s/%s%s.dll", search->name, pep_dll_search_prefix, filename);
+		  if (! ldfile_try_open_bfd (string, entry))
+		    {
+		      /* Try "libfoo.dll" (default preferred dll name).  */
+		      sprintf (string, "%s/lib%s.dll", search->name, filename);
+		      if (! ldfile_try_open_bfd (string, entry))
+			{
+			  /* Finally, try "foo.dll" (alternate dll name).  */
+			  sprintf (string, "%s/%s.dll", search->name, filename);
+			  if (! ldfile_try_open_bfd (string, entry))
+			    {
+			      free (string);
+			      return FALSE;
+			    }
+			}
+		    }
+		}
+	      else /* pep_dll_search_prefix not specified.  */
+#endif
+		{
+		  /* Try "libfoo.dll" (preferred dll name).  */
+		  sprintf (string, "%s/lib%s.dll", search->name, filename);
+		  if (! ldfile_try_open_bfd (string, entry))
+		    {
+		      /* Finally, try "foo.dll" (alternate dll name).  */
+		      sprintf (string, "%s/%s.dll", search->name, filename);
+		      if (! ldfile_try_open_bfd (string, entry))
+			{
+			  free (string);
+			  return FALSE;
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+  entry->filename = string;
+
+  return TRUE;
+}
+
+static int
+gld_${EMULATION_NAME}_find_potential_libraries
+  (char *name, lang_input_statement_type *entry)
+{
+  return ldfile_open_file_search (name, entry, "", ".lib");
+}
+\f
+static char *
+gld_${EMULATION_NAME}_get_script (int *isfile)
+EOF
+# Scripts compiled in.
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{
+  *isfile = 0;
+
+  if (link_info.relocatable && config.build_constructors)
+    return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu			>> e${EMULATION_NAME}.c
+echo '  ; else if (link_info.relocatable) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr			>> e${EMULATION_NAME}.c
+echo '  ; else if (!config.text_read_only) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn			>> e${EMULATION_NAME}.c
+echo '  ; else if (!config.magic_demand_paged) return'	>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn			>> e${EMULATION_NAME}.c
+echo '  ; else return'					>> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x			>> e${EMULATION_NAME}.c
+echo '; }'						>> e${EMULATION_NAME}.c
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
+{
+  gld_${EMULATION_NAME}_before_parse,
+  syslib_default,
+  hll_default,
+  gld_${EMULATION_NAME}_after_parse,
+  gld_${EMULATION_NAME}_after_open,
+  after_allocation_default,
+  set_output_arch_default,
+  ldemul_default_target,
+  gld_${EMULATION_NAME}_before_allocation,
+  gld_${EMULATION_NAME}_get_script,
+  "${EMULATION_NAME}",
+  "${OUTPUT_FORMAT}",
+  gld_${EMULATION_NAME}_finish,
+  NULL, /* Create output section statements.  */
+  gld_${EMULATION_NAME}_open_dynamic_archive,
+  gld_${EMULATION_NAME}_place_orphan,
+  gld_${EMULATION_NAME}_set_symbols,
+  NULL, /* parse_args */
+  gld${EMULATION_NAME}_add_options,
+  gld${EMULATION_NAME}_handle_option,
+  gld_${EMULATION_NAME}_unrecognized_file,
+  gld_${EMULATION_NAME}_list_options,
+  gld_${EMULATION_NAME}_recognized_file,
+  gld_${EMULATION_NAME}_find_potential_libraries,
+  NULL	/* new_vers_pattern.  */
+};
+EOF
diff -rNbu binutils_060913_org/ld/pe-dll.c binutils_060913/ld/pe-dll.c
--- binutils_060913_org/ld/pe-dll.c	2006-08-21 10:12:46.000000000 +0200
+++ binutils_060913/ld/pe-dll.c	2006-09-11 18:04:18.000000000 +0200
@@ -40,7 +40,27 @@
 #include "coff/internal.h"
 #include "../bfd/libcoff.h"
 #include "deffile.h"
+
+#ifdef pe_use_x86_64
+#define PE_IDATA4_SIZE	8
+#define PE_IDATA5_SIZE	8
+
+#include "pep-dll.h"
+
+#undef AOUTSZ
+#define AOUTSZ		PEPAOUTSZ
+#define PEAOUTHDR	PEPAOUTHDR
+#else
 #include "pe-dll.h"
+#endif
+
+#ifndef PE_IDATA4_SIZE
+#define PE_IDATA4_SIZE	4
+#endif
+
+#ifndef PE_IDATA4_SIZE
+#define PE_IDATA4_SIZE	4
+#endif
 
 /*  This file turns a regular Windows PE image into a DLL.  Because of
     the complexity of this operation, it has been broken down into a
@@ -49,7 +69,7 @@
     normally only called once, so static variables are used to reduce
     the number of parameters and return values required.
 
-    See also: ld/emultempl/pe.em.  */
+    See also: ld/emultempl/pe.em and ld/emultempl/pep.em.  */
 
 /*  Auto-import feature by Paul Sokolovsky
 
@@ -144,14 +164,14 @@
 static int runtime_pseudo_relocs_created = 0;
 
 typedef struct
-{
+  {
   char *name;
   int len;
-}
+  }
 autofilter_entry_type;
 
 typedef struct
-{
+  {
   char *target_name;
   char *object_target;
   unsigned int imagebase_reloc;
@@ -159,7 +179,7 @@
   int bfd_arch;
   bfd_boolean underscored;
   autofilter_entry_type* autofilter_symbollist; 
-}
+  }
 pe_details_type;
 
 static autofilter_entry_type autofilter_symbollist_generic[] =
@@ -212,9 +232,15 @@
 static pe_details_type pe_detail_list[] =
 {
   {
+#ifndef pe_use_x86_64
     "pei-i386",
     "pe-i386",
     7 /* R_IMAGEBASE */,
+#else    
+	"pei-x86-64",
+    "pe-x86-64",
+    3 /* R_IMAGEBASE */,
+#endif
     PE_ARCH_i386,
     bfd_arch_i386,
     TRUE,
@@ -480,6 +506,7 @@
 	 it is too restrictive.  Instead we have
 	 a target specific list to use:  */
       afptr = pe_details->autofilter_symbollist; 
+
       while (afptr->name)
 	{
 	  if (strcmp (n, afptr->name) == 0)
@@ -590,7 +617,6 @@
 		  {
 		    char *name = xmalloc (strlen (sn) + 2 + 6);
 		    sprintf (name, "%s%s", U("_imp_"), sn);
-
 		    blhe = bfd_link_hash_lookup (info->hash, name,
 						 FALSE, FALSE, FALSE);
 		    free (name);
@@ -1235,6 +1261,12 @@
 		      reloc_data[total_relocs].type = 5;
 		      total_relocs++;
 		      break;
+#ifdef pe_use_x86_64
+			case BITS_AND_SHIFT (64, 0):
+				  reloc_data[total_relocs].type = 10;
+				  total_relocs++;
+				  break;
+#endif
 		    case BITS_AND_SHIFT (24, 2):
 		      /* FIXME: 0 is ARM_26D, it is defined in bfd/coff-arm.c
 			 Those ARM_xxx definitions should go in proper
@@ -1312,14 +1344,15 @@
 
       bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12),
 		  reloc_d + reloc_sz);
-      reloc_sz += 2;
 
+      reloc_sz += 2;
       if (reloc_data[i].type == 4)
 	{
 	  bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);
 	  reloc_sz += 2;
 	}
 
+
       page_count++;
     }
 
@@ -1630,10 +1663,12 @@
 
  	.section	.idata$5
  	.long		0
+ 	[ .long		0] for PE+
    fthunk:
 
  	.section	.idata$4
  	.long		0
+ 	[ .long		0] for PE+
    hname:                              */
 
 static bfd *
@@ -1679,21 +1714,21 @@
   quick_reloc (abfd, 16, BFD_RELOC_RVA, 1);
   save_relocs (id2);
 
-  bfd_set_section_size (abfd, id5, 4);
-  d5 = xmalloc (4);
+  bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
+  d5 = xmalloc (PE_IDATA5_SIZE);
   id5->contents = d5;
-  memset (d5, 0, 4);
+  memset (d5, 0, PE_IDATA5_SIZE);
 
-  bfd_set_section_size (abfd, id4, 4);
-  d4 = xmalloc (4);
+  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
+  d4 = xmalloc (PE_IDATA4_SIZE);
   id4->contents = d4;
-  memset (d4, 0, 4);
+  memset (d4, 0, PE_IDATA4_SIZE);
 
   bfd_set_symtab (abfd, symtab, symptr);
 
   bfd_set_section_contents (abfd, id2, d2, 0, 20);
-  bfd_set_section_contents (abfd, id5, d5, 0, 4);
-  bfd_set_section_contents (abfd, id4, d4, 0, 4);
+  bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
+  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
 
   bfd_make_readable (abfd);
   return abfd;
@@ -1701,8 +1736,10 @@
 
 /*	.section	.idata$4
  	.long		0
+  	[.long		0] for PE+
  	.section	.idata$5
  	.long		0
+ 	[.long		0] for PE+
  	.section	idata$7
  	.global		__my_dll_iname
   __my_dll_iname:
@@ -1735,15 +1772,15 @@
   id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
   quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0);
 
-  bfd_set_section_size (abfd, id4, 4);
-  d4 = xmalloc (4);
+  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
+  d4 = xmalloc (PE_IDATA4_SIZE);
   id4->contents = d4;
-  memset (d4, 0, 4);
+  memset (d4, 0, PE_IDATA4_SIZE);
 
-  bfd_set_section_size (abfd, id5, 4);
-  d5 = xmalloc (4);
+  bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
+  d5 = xmalloc (PE_IDATA5_SIZE);
   id5->contents = d5;
-  memset (d5, 0, 4);
+  memset (d5, 0, PE_IDATA5_SIZE);
 
   len = strlen (dll_filename) + 1;
   if (len & 1)
@@ -1755,8 +1792,8 @@
 
   bfd_set_symtab (abfd, symtab, symptr);
 
-  bfd_set_section_contents (abfd, id4, d4, 0, 4);
-  bfd_set_section_contents (abfd, id5, d5, 0, 4);
+  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
+  bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
   bfd_set_section_contents (abfd, id7, d7, 0, len);
 
   bfd_make_readable (abfd);
@@ -1820,7 +1857,6 @@
   0,    0,    0,    0
 };
 
-
 static bfd *
 make_one (def_file_export *exp, bfd *parent)
 {
@@ -1943,16 +1979,16 @@
   quick_reloc (abfd, 0, BFD_RELOC_RVA, 5);
   save_relocs (id7);
 
-  bfd_set_section_size (abfd, id5, 4);
-  d5 = xmalloc (4);
+  bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
+  d5 = xmalloc (PE_IDATA5_SIZE);
   id5->contents = d5;
-  memset (d5, 0, 4);
+  memset (d5, 0, PE_IDATA5_SIZE);
 
   if (exp->flag_noname)
     {
       d5[0] = exp->ordinal;
       d5[1] = exp->ordinal >> 8;
-      d5[3] = 0x80;
+      d5[PE_IDATA5_SIZE-1] = 0x80;
     }
   else
     {
@@ -1960,16 +1996,16 @@
       save_relocs (id5);
     }
 
-  bfd_set_section_size (abfd, id4, 4);
-  d4 = xmalloc (4);
+  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
+  d4 = xmalloc (PE_IDATA4_SIZE);
   id4->contents = d4;
-  memset (d4, 0, 4);
+  memset (d4, 0, PE_IDATA4_SIZE);
 
   if (exp->flag_noname)
     {
       d4[0] = exp->ordinal;
       d4[1] = exp->ordinal >> 8;
-      d4[3] = 0x80;
+      d4[PE_IDATA4_SIZE-1] = 0x80;
     }
   else
     {
@@ -2000,8 +2036,8 @@
 
   bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count);
   bfd_set_section_contents (abfd, id7, d7, 0, 4);
-  bfd_set_section_contents (abfd, id5, d5, 0, 4);
-  bfd_set_section_contents (abfd, id4, d4, 0, 4);
+  bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
+  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
   if (!exp->flag_noname)
     bfd_set_section_contents (abfd, id6, d6, 0, len);
 
@@ -2035,16 +2071,16 @@
   quick_symbol (abfd, U ("_nm_thnk_"), import, "", id4, BSF_GLOBAL, 0);
   quick_symbol (abfd, U ("_nm_"), import, "", UNDSEC, BSF_GLOBAL, 0);
 
-  bfd_set_section_size (abfd, id4, 8);
-  d4 = xmalloc (4);
+  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
+  d4 = xmalloc (PE_IDATA4_SIZE);
   id4->contents = d4;
-  memset (d4, 0, 8);
+  memset (d4, 0, PE_IDATA4_SIZE);
   quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);
   save_relocs (id4);
 
   bfd_set_symtab (abfd, symtab, symptr);
 
-  bfd_set_section_contents (abfd, id4, d4, 0, 8);
+  bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
 
   bfd_make_readable (abfd);
   return abfd;
@@ -2557,14 +2593,21 @@
 
   /* Get pe_header, optional header and numbers of export entries.  */
   pe_header_offset = pe_get32 (dll, 0x3c);
-  opthdr_ofs = pe_header_offset + 4 + 20;
+  opthdr_ofs = pe_header_offset + 4 + 20; // Magic of opt header
+#ifndef pe_use_x86_64
   num_entries = pe_get32 (dll, opthdr_ofs + 92);
-
+#else
+  num_entries = pe_get32 (dll, opthdr_ofs + 92 +4*4); //  &NumberOfRvaAndSizes
+#endif
   if (num_entries < 1) /* No exports.  */
     return FALSE;
-
+#ifndef pe_use_x86_64
   export_rva = pe_get32 (dll, opthdr_ofs + 96);
   export_size = pe_get32 (dll, opthdr_ofs + 100);
+#else
+  export_rva = pe_get32 (dll, opthdr_ofs + 96+4*4);
+  export_size = pe_get32 (dll, opthdr_ofs + 100+4*4);
+#endif
   nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
   secptr = (pe_header_offset + 4 + 20 +
 	    pe_get16 (dll, pe_header_offset + 4 + 16));
diff -rNbu binutils_060913_org/ld/pep-dll.c binutils_060913/ld/pep-dll.c
--- binutils_060913_org/ld/pep-dll.c	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/ld/pep-dll.c	2006-09-11 18:04:06.000000000 +0200
@@ -0,0 +1,58 @@
+/* Routines to help build PEPI-format DLLs (Win64 etc)
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define COFF_WITH_pex64
+
+/* Local defined globals */
+#define pe_def_file	pep_def_file
+#define pe_details	pep_details
+#define pe_dll_compat_implib pep_dll_compat_implib
+#define pe_dll_extra_pe_debug pep_dll_extra_pe_debug
+#define pe_dll_export_everything pep_dll_export_everything
+#define pe_dll_do_default_excludes pep_dll_do_default_excludes
+#define pe_dll_kill_ats pep_dll_kill_ats
+#define pe_dll_stdcall_aliases pep_dll_stdcall_aliases
+#define pe_dll_warn_dup_exports pep_dll_warn_dup_exports
+
+/* external globals */
+#define pe_data_import_dll pep_data_import_dll
+
+/* Unique global name for functions to avoid double defined symbols */
+#define pe_create_import_fixup pep_create_import_fixup
+#define pe_dll_generate_def_file pep_dll_generate_def_file
+#define pe_process_import_defs pep_process_import_defs
+#define pe_dll_id_target pep_dll_id_target
+#define pe_implied_import_dll pep_implied_import_dll
+#define pe_dll_build_sections pep_dll_build_sections
+#define pe_exe_build_sections pep_exe_build_sections
+#define pe_dll_fill_sections pep_dll_fill_sections
+#define pe_exe_fill_sections pep_exe_fill_sections
+#define pe_dll_generate_implib pep_dll_generate_implib
+#define pe_dll_add_excludes pep_dll_add_excludes
+#define pe_walk_relocs_of_symbol pep_walk_relocs_of_symbol
+
+// Uses x86_64 PE+
+#define pe_use_x86_64
+
+#include "pe-dll.c"
diff -rNbu binutils_060913_org/ld/pep-dll.h binutils_060913/ld/pep-dll.h
--- binutils_060913_org/ld/pep-dll.h	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/ld/pep-dll.h	2006-08-17 09:13:36.000000000 +0200
@@ -0,0 +1,64 @@
+/* pep-dll.h: Header file for routines used to build Windows DLLs.
+   Copyright 1995, 1996, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
+
+   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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+   
+   Written by Kai Tietz, OneVision Software GmbH&CoKg.
+*/
+
+#ifndef PEP_DLL_H
+#define PEP_DLL_H
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "deffile.h"
+
+extern def_file *pep_def_file;
+extern int pep_dll_export_everything;
+extern int pep_dll_do_default_excludes;
+extern int pep_dll_kill_ats;
+extern int pep_dll_stdcall_aliases;
+extern int pep_dll_warn_dup_exports;
+extern int pep_dll_compat_implib;
+extern int pep_dll_extra_pe_debug;
+
+extern void pep_dll_id_target
+  (const char *);
+extern void pep_dll_add_excludes
+  (const char *, const int);
+extern void pep_dll_generate_def_file
+  (const char *);
+extern void pep_dll_generate_implib
+  (def_file *, const char *);
+extern void pep_process_import_defs
+  (bfd *, struct bfd_link_info *);
+extern bfd_boolean pep_implied_import_dll
+  (const char *);
+extern void pep_dll_build_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_exe_build_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_dll_fill_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_exe_fill_sections
+  (bfd *, struct bfd_link_info *);
+extern void pep_walk_relocs_of_symbol
+  (struct bfd_link_info *, const char *, int (*) (arelent *, asection *));
+extern void pep_create_import_fixup
+  (arelent * rel, asection *, int);
+#endif /* PE_DLL_H */
diff -rNbu binutils_060913_org/ld/scripttempl/pep.sc binutils_060913/ld/scripttempl/pep.sc
--- binutils_060913_org/ld/scripttempl/pep.sc	1970-01-01 01:00:00.000000000 +0100
+++ binutils_060913/ld/scripttempl/pep.sc	2006-07-28 14:12:24.000000000 +0200
@@ -0,0 +1,272 @@
+# Linker script for PE.
+
+if test -z "${RELOCATEABLE_OUTPUT_FORMAT}"; then
+  RELOCATEABLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
+fi
+
+# We can't easily and portably get an unquoted $ in a shell
+# substitution, so we do this instead.
+# Sorting of the .foo$* sections is required by the definition of
+# grouped sections in PE.
+# Sorting of the file names in R_IDATA is required by the
+# current implementation of dlltool (this could probably be changed to
+# use grouped sections instead).
+if test "${RELOCATING}"; then
+  R_TEXT='*(SORT(.text$*))'
+  R_DATA='*(SORT(.data$*))'
+  R_RDATA='*(SORT(.rdata$*))'
+  R_IDATA='
+    SORT(*)(.idata$2)
+    SORT(*)(.idata$3)
+    /* These zeroes mark the end of the import list.  */
+    LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
+    SORT(*)(.idata$4)
+    SORT(*)(.idata$5)
+    SORT(*)(.idata$6)
+    SORT(*)(.idata$7)'
+  R_CRT_XC='*(SORT(.CRT$XC*))  /* C initialization */'
+  R_CRT_XI='*(SORT(.CRT$XI*))  /* C++ initialization */'
+  R_CRT_XL='*(SORT(.CRT$XL*))  /* TLS callbacks */'
+  R_CRT_XP='*(SORT(.CRT$XP*))  /* Pre-termination */'
+  R_CRT_XT='*(SORT(.CRT$XT*))  /* Termination */'
+  R_TLS='
+    *(.tls)
+    *(.tls$)
+    *(SORT(.tls$*))'
+  R_RSRC='*(SORT(.rsrc$*))'
+else
+  R_TEXT=
+  R_DATA=
+  R_RDATA=
+  R_IDATA=
+  R_CRT=
+  R_RSRC=
+fi
+
+cat <<EOF
+${RELOCATING+OUTPUT_FORMAT(${OUTPUT_FORMAT})}
+${RELOCATING-OUTPUT_FORMAT(${RELOCATEABLE_OUTPUT_FORMAT})}
+${OUTPUT_ARCH+OUTPUT_ARCH(${OUTPUT_ARCH})}
+
+${LIB_SEARCH_DIRS}
+
+SECTIONS
+{
+  ${RELOCATING+/* Make the virtual address and file offset synced if the alignment is}
+  ${RELOCATING+   lower than the target page size. */}
+  ${RELOCATING+. = SIZEOF_HEADERS;}
+  ${RELOCATING+. = ALIGN(__section_alignment__);}
+  .text ${RELOCATING+ __image_base__ + ( __section_alignment__ < ${TARGET_PAGE_SIZE} ? . : __section_alignment__ )} : 
+  {
+    ${RELOCATING+ *(.init)}
+    *(.text)
+    ${R_TEXT}
+    *(.glue_7t)
+    *(.glue_7)
+    ${CONSTRUCTING+ ___CTOR_LIST__ = .; __CTOR_LIST__ = . ; 
+			LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*));  LONG (0); }
+    ${CONSTRUCTING+ ___DTOR_LIST__ = .; __DTOR_LIST__ = . ; 
+			LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*));  LONG (0); }
+    ${RELOCATING+ *(.fini)}
+    /* ??? Why is .gcc_exc here?  */
+    ${RELOCATING+ *(.gcc_exc)}
+    ${RELOCATING+PROVIDE (etext = .);}
+    *(.gcc_except_table)
+  }
+
+  /* The Cygwin32 library uses a section to avoid copying certain data
+     on fork.  This used to be named ".data$nocopy".  The linker used
+     to include this between __data_start__ and __data_end__, but that
+     breaks building the cygwin32 dll.  Instead, we name the section
+     ".data_cygwin_nocopy" and explictly include it after __data_end__. */
+
+  .data ${RELOCATING+BLOCK(__section_alignment__)} : 
+  {
+    ${RELOCATING+__data_start__ = . ;}
+    *(.data)
+    *(.data2)
+    ${R_DATA}
+    *(.jcr)
+    ${RELOCATING+__data_end__ = . ;}
+    ${RELOCATING+*(.data_cygwin_nocopy)}
+  }
+
+  .rdata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.rdata)
+    ${R_RDATA}
+    *(.eh_frame)
+    ${RELOCATING+___RUNTIME_PSEUDO_RELOC_LIST__ = .;}
+    ${RELOCATING+__RUNTIME_PSEUDO_RELOC_LIST__ = .;}
+    *(.rdata_runtime_pseudo_reloc)
+    ${RELOCATING+___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;}
+    ${RELOCATING+__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;}
+  }
+
+  .pdata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.pdata)
+  }
+
+  .bss ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    ${RELOCATING+__bss_start__ = . ;}
+    *(.bss)
+    *(COMMON)
+    ${RELOCATING+__bss_end__ = . ;}
+  }
+
+  .edata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    *(.edata)
+  }
+
+  /DISCARD/ :
+  {
+    *(.debug\$S)
+    *(.debug\$T)
+    *(.debug\$F)
+    *(.drectve)
+  }
+
+  .idata ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    /* This cannot currently be handled with grouped sections.
+	See pep.em:sort_sections.  */
+    ${R_IDATA}
+  }
+  .CRT ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    ${RELOCATING+___crt_xc_start__ = . ;}
+    ${R_CRT_XC}
+    ${RELOCATING+___crt_xc_end__ = . ;}
+    ${RELOCATING+___crt_xi_start__ = . ;}
+    ${R_CRT_XI}
+    ${RELOCATING+___crt_xi_end__ = . ;}
+    ${RELOCATING+___crt_xl_start__ = . ;}
+    ${R_CRT_XL}
+    /* ___crt_xl_end__ is defined in the TLS Directory support code */
+    ${RELOCATING+___crt_xp_start__ = . ;}
+    ${R_CRT_XP}
+    ${RELOCATING+___crt_xp_end__ = . ;}
+    ${RELOCATING+___crt_xt_start__ = . ;}
+    ${R_CRT_XT}
+    ${RELOCATING+___crt_xt_end__ = . ;}
+  }
+
+  .tls ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    ${RELOCATING+___tls_start__ = . ;}
+    ${R_TLS}
+    ${RELOCATING+___tls_end__ = . ;}
+  }
+
+  .endjunk ${RELOCATING+BLOCK(__section_alignment__)} :
+  {
+    /* end is deprecated, don't use it */
+    ${RELOCATING+PROVIDE (end = .);}
+    ${RELOCATING+PROVIDE ( _end = .);}
+    ${RELOCATING+ __end__ = .;}
+  }
+
+  .rsrc ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    *(.rsrc)
+    ${R_RSRC}
+  }
+
+  .reloc ${RELOCATING+BLOCK(__section_alignment__)} :
+  { 					
+    *(.reloc)
+  }
+
+  .stab ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.stab)
+  }
+
+  .stabstr ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.stabstr)
+  }
+
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section.  Unlike other targets that fake this by putting the
+     section VMA at 0, the PE format will not allow it.  */
+     
+  /* DWARF 1.1 and DWARF 2.  */
+  .debug_aranges ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_aranges)
+  }
+
+  .debug_pubnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_pubnames)
+  }
+
+  /* DWARF 2.  */
+  .debug_info ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_info) *(.gnu.linkonce.wi.*)
+  }
+
+  .debug_abbrev ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_abbrev)
+  }
+
+  .debug_line ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_line)
+  }
+
+  .debug_frame ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_frame)
+  }
+
+  .debug_str ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_str)
+  }
+
+  .debug_loc ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_loc)
+  }
+
+  .debug_macinfo ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_macinfo)
+  }
+
+  /* SGI/MIPS DWARF 2 extensions.  */
+  .debug_weaknames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_weaknames)
+  }
+
+  .debug_funcnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_funcnames)
+  }
+
+  .debug_typenames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_typenames)
+  }
+
+  .debug_varnames ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_varnames)
+  }
+
+  /* DWARF 3.  */
+  .debug_ranges ${RELOCATING+BLOCK(__section_alignment__)} ${RELOCATING+(NOLOAD)} :
+  {
+    *(.debug_ranges)
+  }
+}
+EOF
diff -rNbu binutils_060913_org/ld/testsuite/ChangeLog binutils_060913/ld/testsuite/ChangeLog
--- binutils_060913_org/ld/testsuite/ChangeLog	2006-09-13 00:10:31.000000000 +0200
+++ binutils_060913/ld/testsuite/ChangeLog	2006-09-13 11:12:23.000000000 +0200
@@ -1,3 +1,15 @@
+2006-09-13	Kai Tietz	<Kai.Tietz@onevision.com>
+
+	* bootstrap/bootstrap.exp:		Enable target test
+	* ld-fastcall/fastcall.exp:		Enable target test
+	* ld-scripts/align.exp:		Enable target test
+	* ld-scripts/align2a.d:		Enable target test
+	* ld-scripts/defined.exp:		Enable target test
+	* ld-scripts/provide.exp:		Enable target test
+	* ld-scripts/script.exp:		Enable target test
+	* ld-scripts/weak.exp:		Enable target test
+	* lib/ld-lib.exp:		Detect target as pecoff file format
+
 2006-09-12  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR ld/3197
diff -rNbu binutils_060913_org/ld/testsuite/ld-bootstrap/bootstrap.exp binutils_060913/ld/testsuite/ld-bootstrap/bootstrap.exp
--- binutils_060913_org/ld/testsuite/ld-bootstrap/bootstrap.exp	2005-11-15 09:32:01.000000000 +0100
+++ binutils_060913/ld/testsuite/ld-bootstrap/bootstrap.exp	2006-09-11 14:54:48.000000000 +0200
@@ -140,7 +140,7 @@
 	|| [istarget "*-*-wince"]
 	|| [istarget "*-*-cygwin*"]
 	|| [istarget "*-*-winnt*"]
-	|| [istarget "*-*-mingw32*"]
+	|| [istarget "*-*-mingw*"]
 	|| [istarget "*-*-interix*"]
 	|| [istarget "*-*-beospe*"]
 	|| [istarget "*-*-netbsdpe*"]} {
diff -rNbu binutils_060913_org/ld/testsuite/ld-fastcall/fastcall.exp binutils_060913/ld/testsuite/ld-fastcall/fastcall.exp
--- binutils_060913_org/ld/testsuite/ld-fastcall/fastcall.exp	2005-05-12 09:32:06.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-fastcall/fastcall.exp	2006-09-11 14:55:40.000000000 +0200
@@ -17,13 +17,13 @@
 
 set testname "ld (fastcall symbols)"
 
-if {![istarget "i*86-*-*"]} {
+if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw64*"] } {
     return
 }
 
 if {  !([istarget "i*86-*-*pe*"] && ![istarget "i*86-*-opensd*"]) \
     && ![istarget "i*86-*-cygwin*"] \
-    && ![istarget "i*86-*-mingw32*"] } {
+    && ![istarget "i*86-*-mingw*"] } {
     return
 }
 
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/align.exp binutils_060913/ld/testsuite/ld-scripts/align.exp
--- binutils_060913_org/ld/testsuite/ld-scripts/align.exp	2005-10-25 19:40:12.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-scripts/align.exp	2006-09-11 14:57:56.000000000 +0200
@@ -30,12 +30,19 @@
 }
 
 # Doesn't work on PECOFF, appears to be a genuine bug
-if [is_pecoff_format] {
+# mingw64 targets need to set the image base to 0 to avoid auto image-basing.
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+} else {
+  if [is_pecoff_format] {
   global target_triplet
   setup_xfail $target_triplet
+  }
 }
 
-if ![ld_simple_link $ld tmpdir/align "-T $srcdir/$subdir/align.t tmpdir/align.o"] {
+if ![ld_simple_link $ld tmpdir/align "$LDFLAGS -T $srcdir/$subdir/align.t tmpdir/align.o"] {
     fail $testname
 } else {
     pass $testname
@@ -50,3 +57,4 @@
     run_dump_test align2b
 }
 run_dump_test align2c
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/align2a.d binutils_060913/ld/testsuite/ld-scripts/align2a.d
--- binutils_060913_org/ld/testsuite/ld-scripts/align2a.d	2005-02-21 09:18:49.000000000 +0100
+++ binutils_060913/ld/testsuite/ld-scripts/align2a.d	2006-09-06 15:34:34.000000000 +0200
@@ -1,12 +1,12 @@
-# ld: --defsym data_align=16 -T align2.t
-# objdump: --section-headers
+#ld: --defsym data_align=16 -T align2.t
+#objdump: --section-headers
 
 [^:]+: +file format.*
 
 Sections:
 Idx +Name +Size +VMA +LMA +File +off +Algn
- +0 +\.text +[^ ]* +0+ +0+ .*
- +CONTENTS, +ALLOC, +LOAD,.* CODE
- +1 +\.data +[^ ]* +0+10 +0+10 .*
- +CONTENTS, +ALLOC, +LOAD, +DATA
+[	 ]+0 +\.text +[^ ]* +0+ +0+ .*
+[	 ]+CONTENTS, +ALLOC, +LOAD,.* CODE
+[	 ]+1 +\.data +[^ ]* +0+10 +0+10 .*
+[	 ]+CONTENTS, +ALLOC, +LOAD, +DATA
 #pass
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/defined.exp binutils_060913/ld/testsuite/ld-scripts/defined.exp
--- binutils_060913_org/ld/testsuite/ld-scripts/defined.exp	2005-05-12 09:32:08.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-scripts/defined.exp	2006-09-06 17:02:32.000000000 +0200
@@ -20,12 +20,19 @@
 set testname "DEFINED"
 set prms_id 5699
 
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+}
+
 if ![ld_assemble $as $srcdir/$subdir/defined.s tmpdir/def.o] {
     unresolved $testname
+    set LDFLAGS "$saved_LDFLAGS"
     return
 }
 
-if ![ld_simple_link $ld tmpdir/def "-T $srcdir/$subdir/defined.t tmpdir/def.o"] {
+if ![ld_simple_link $ld tmpdir/def "$LDFLAGS -T $srcdir/$subdir/defined.t tmpdir/def.o"] {
     fail $testname
 } else {
     if ![ld_nm $nm "" tmpdir/def] {
@@ -57,3 +64,4 @@
 set prms_id 0
 run_dump_test "defined2"
 run_dump_test "defined3"
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/provide.exp binutils_060913/ld/testsuite/ld-scripts/provide.exp
--- binutils_060913_org/ld/testsuite/ld-scripts/provide.exp	2005-06-01 06:04:19.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-scripts/provide.exp	2006-09-06 17:04:32.000000000 +0200
@@ -29,7 +29,15 @@
     return
 }
 
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+}
+
+
 run_dump_test provide-1
 run_dump_test provide-2
 setup_xfail *-*-*
 run_dump_test provide-3
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/script.exp binutils_060913/ld/testsuite/ld-scripts/script.exp
--- binutils_060913_org/ld/testsuite/ld-scripts/script.exp	2005-05-12 09:32:08.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-scripts/script.exp	2006-09-11 15:00:32.000000000 +0200
@@ -95,7 +95,7 @@
 set flags ""
 if {[istarget "*-*-pe*"] \
     || [istarget "*-*-cygwin*"] \
-    || [istarget "*-*-mingw32*"] \
+    || [istarget "*-*-mingw*"] \
     || [istarget "*-*-winnt*"] \
     || [istarget "*-*-nt"] \
     || [istarget "*-*-interix*"] } then {
diff -rNbu binutils_060913_org/ld/testsuite/ld-scripts/weak.exp binutils_060913/ld/testsuite/ld-scripts/weak.exp
--- binutils_060913_org/ld/testsuite/ld-scripts/weak.exp	2005-08-18 09:51:07.000000000 +0200
+++ binutils_060913/ld/testsuite/ld-scripts/weak.exp	2006-09-06 17:33:38.000000000 +0200
@@ -29,11 +29,11 @@
 # Weak symbols are broken for non-i386 PE targets.
 if {! [istarget i?86-*-*]} {
     setup_xfail *-*-pe*
+    setup_xfail *-*-mingw64*
 }
 
 # hppa64 and or32 are incredibly broken
 setup_xfail hppa64-*-* or32-*-*
-
 if {! [ld_assemble $as $srcdir/$subdir/weak1.s tmpdir/weak1.o]
     || ! [ld_assemble $as $srcdir/$subdir/weak2.s tmpdir/weak2.o]} then {
     # It's OK if .weak doesn't work on this target.
@@ -41,6 +41,12 @@
     return
 }
 
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+if [istarget "*-*-mingw64*"] then {
+  set LDFLAGS "$LDFLAGS --image-base 0"
+}
+
 set weak_regexp_big \
 ".*Contents of section .text:.*1000 00001008 0000200c 12121212 34343434.*Contents of section .data:.*2000 00001008 0000200c 56565656 78787878.*"
 
@@ -67,3 +73,4 @@
 	fail $testname
     }
 }
+set LDFLAGS "$saved_LDFLAGS"
diff -rNbu binutils_060913_org/ld/testsuite/lib/ld-lib.exp binutils_060913/ld/testsuite/lib/ld-lib.exp
--- binutils_060913_org/ld/testsuite/lib/ld-lib.exp	2006-09-07 19:16:34.000000000 +0200
+++ binutils_060913/ld/testsuite/lib/ld-lib.exp	2006-09-11 15:02:02.000000000 +0200
@@ -434,7 +434,7 @@
 # True if the object format is known to be PE COFF.
 #
 proc is_pecoff_format {} {
-    if { ![istarget *-*-mingw32*] \
+    if { ![istarget *-*-mingw*] \
 	 && ![istarget *-*-cygwin*] \
 	 && ![istarget *-*-pe*] } {
 	return 0

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: PE+ and new COFF format for x86_64 target for XP64 and Vista binaries
       [not found] <OF549439E3.7A0AEA72-ONC12571E2.005485EF-C12571E2.0057AE96@LocalDomain>
@ 2006-09-07 16:03 ` Kai Tietz
  0 siblings, 0 replies; 17+ messages in thread
From: Kai Tietz @ 2006-09-07 16:03 UTC (permalink / raw)
  To: binutils; +Cc: H. J. Lu

Until now I haven't posted it to other groups.
By the way the changes to ChangeLog are at the beginning of the file, but 
I assume you merged the diff is against an newer binutils-2.17 version 
than I had.

Regards,
 i.A. Kai Tietz

----------------------------------------
  Kai Tietz - Software engineering
  OneVision Software Entwicklungs GmbH & Co KG
  Dr.-Leo-Ritter-Str. 9, 93049 Regensburg, Germany
  Phone: +49-941-78004-0
  FAX:   +49-941-78004-489
  WWW:   http://www.OneVision.com


On Thu, Sep 07, 2006 at 03:40:14PM +0200, Kai Tietz wrote:
> Ok, the copyright paper is on the way to FSF.
> Additionally I added the ChangeLog entries. Also the testcases of 
> binutils, gas, and ld are extended for supporting the new target.
> Most testcases work proper, just there seems to be a problem with the 
weak 
> alias test. It fails for some reason I didn't got it.
> Also the align test case seems to work for this new target (for pe 
target 
> it was defined as xfail ...).
> 

There are no need to include patches for Makefile.in and configure.
They are generated files. Please use the correct format for ChangeLog
entries and put all ChangeLog entries in the beginning. You can take
a look at existing ChangeLog entries to see how they are written.

Other people will have more comments. BTW, have you posted it to
cygwin and mingw mailing lists?

H.J.




^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2006-09-20 14:48 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-08-17 16:25 PE+ and new COFF format for x86_64 target for XP64 and Vista binaries Kai Tietz
2006-08-17 16:45 ` H. J. Lu
2006-09-07 13:41   ` Kai Tietz
2006-09-07 15:04     ` H. J. Lu
2006-09-08  9:48 ` Pedro Alves
2006-09-08 10:23   ` Kai Tietz
2006-09-08 17:46     ` Phil Lello
2006-09-11  7:26       ` Kai Tietz
     [not found] <OF549439E3.7A0AEA72-ONC12571E2.005485EF-C12571E2.0057AE96@LocalDomain>
2006-09-07 16:03 ` Kai Tietz
2006-09-13  9:43 Kai Tietz
2006-09-13 10:52 ` Pedro Alves
2006-09-13 11:50   ` Kai Tietz
2006-09-13 11:54   ` Kai Tietz
2006-09-13 12:02   ` Kai Tietz
2006-09-13 12:07   ` Kai Tietz
2006-09-20 13:06     ` Nick Clifton
2006-09-20 18:49       ` Kai Tietz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).