public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: Discussion about merging Go frontend
       [not found]             ` <4CC60C5E.6050605@gmail.com>
@ 2010-10-29  6:56               ` Ian Lance Taylor
  2010-10-29 13:19                 ` Dave Korn
                                   ` (7 more replies)
  0 siblings, 8 replies; 68+ messages in thread
From: Ian Lance Taylor @ 2010-10-29  6:56 UTC (permalink / raw)
  To: Dave Korn; +Cc: Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

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

Dave Korn <dave.korn.cygwin@gmail.com> writes:

>   What would be even nicer would be if we could share the same code-reader
> interface between lto and go (and the lto-plugin), thereby getting object
> format independence equally everywhere for no extra cost.

How about this?

This implements an object file reader/writer which does everything
required by LTO and gccgo.  The ELF code works.  I have not tested the
Mach-O and COFF code at all beyond compiling it; I hope that somebody
else can test those targets and fix them.

With this patch, libelf is no longer needed.

I've bootstrapped this on x86_64-unknown-linux-gnu, and I've run the LTO
testsuite.

This patch puts the code in libiberty, but it could equally well go in
gcc.  Anybody want to make an argument one way or another?

Does the general interface look OK?

This patch requires approval from the LTO maintainers.  I don't need
approval for the libiberty changes (if the code stays in libiberty) but
of course I would appreciate it if somebody could look it over.  I think
the configure and Makefile changes are sufficiently obvious given the
other changes as to not require approval.

If this patch is accepted, then gccgo will not require elfcpp.

Ian


include/ChangeLog:

2010-10-28  Ian Lance Taylor  <iant@google.com>

	* objfile.h: New file.

libiberty/ChangeLog:

2010-10-28  Ian Lance Taylor  <iant@google.com>

	* objfile.c: New file.
	* objfile-common.h: New file.
	* objfile-elf.c: New file.
	* objfile-mach-o.c: New file.
	* objfile-coff.c: New file.
	* configure.ac: Add AC_TYPE_SSIZE_T.
	* Makefile.in: Rebuild dependencies.
	(CFILES): Add objfile.c, objfile-coff, objfile-elf.c,
	objfile-mach-o.c.
	(REQUIRED_OFILES): Add corresponding object files.
	* configure: Rebuild.
	* config.in: Rebuild.

gcc/ChangeLog:

2010-10-28  Ian Lance Taylor  <iant@google.com>

	* configure.ac: Remove elf_getshdrstrndx test.  Don't substitute
	LTO_BINARY_READER or LTO_USE_LIBELF.  Remove LIBELFLIBS and
	LIBELFINC.  Remove HAVE_libelf.
	* gcc/config.gcc: Don't set lto_binary_reader.
	* gcc/Makefile.in (LIBELFLIBS, LIBELFINC): Remove variables.
	(LTO_BINARY_READER, LTO_USE_LIBELF): Remove variables.
	(LIBS): Remove $(LIBELFLIBS).
	(INCLUDES): Remove $(LIBELFINC).
	* doc/install.texi (Prerequisites): Remove libelf paragraphs.
	(Configuration): Mention --disable-lto.  Remove --with-libelf
	paragraph.
	* configure: Rebuild.
	* config.in: Rebuild.

gcc/lto/ChangeLog:

2010-10-28  Ian Lance Taylor  <iant@google.com>

	* lto-objfile.c: New file.
	* lto-elf.c: Remove file.
	* lto-macho.c: Remove file.
	* lto-macho.h: Remove file.
	* lto-coff.c: Remove file.
	* lto-coff.h: Remove file.
	* Make-lang.in (LTO_OBJS): Change lto/$(LTO_BINARY_READER).o to
	lto/lto-objfile.o.
	($(LTO_EXE)): Remove $(LTO_USE_LIBELF)
	(lto/lto-objfile.o): New target.
	(lto/lto-elf.o, lto/lto-coff.o, lto/lto-macho.o): Remove targets.

./ChangeLog:

2010-10-28  Ian Lance Taylor  <iant@google.com>

	* configure.ac: Don't set default_enable_lto.  Remove libelf tests.
	* configure: Rebuild.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: objfile --]
[-- Type: text/x-diff, Size: 231860 bytes --]

Index: include/objfile.h
===================================================================
--- include/objfile.h	(revision 0)
+++ include/objfile.h	(revision 0)
@@ -0,0 +1,198 @@
+/* objfile.h -- routines to manipulate object files
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+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, 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, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#ifndef OBJFILE_H
+#define OBJFILE_H
+
+#include <stddef.h>
+#include <sys/types.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This header file provides four types with associated functions.
+   They are used to read and write object files.  This is a minimal
+   interface, intended to support the needs of gcc without bringing in
+   all the power and complexity of BFD.  */
+
+/* The type objfile_read * is used to read an existing object
+   file.  */
+
+typedef struct objfile_read_struct objfile_read;
+
+/* Create an objfile_rd given DESCRIPTOR, an open file descriptor, and
+   OFFSET, an offset within the file.  The offset is for use with
+   archives, and should be 0 for an ordinary object file.  The
+   descriptor must remain open until done with the returned
+   objfile_read.  SEGMENT_NAME is used on Mach-O and is required on
+   that platform: it means to only look at sections within the segment
+   with that name.  It is ignored for other object file formats.  On
+   error, this function returns NULL, and sets *ERRMSG to an error
+   string and sets *ERR to an errno value or 0 if there is no relevant
+   errno.  */
+
+extern objfile_read *
+objfile_open_read (int descriptor, off_t offset, const char *segment_name,
+		   const char **errmsg, int *err);
+
+/* Call PFN for each section in OBJFILE, passing it the section name,
+   offset within the file of the section contents, and length of the
+   section contents.  The offset within the file is relative to the
+   offset passed to objfile_open_read.  The DATA argument to
+   objfile_find_sections is passed on to PFN.  If PFN returns 0, the
+   loop is stopped and objfile_find_sections returns.  If PFN returns
+   non-zero, the loop continues.  On success this returns NULL.  On
+   error it returns an error string, and sets *ERR to an errno value
+   or 0 if there is no relevant errno.  */
+
+extern const char *
+objfile_find_sections (objfile_read *objfile,
+		       int (*pfn) (void *data, const char *, off_t offset,
+				   off_t length),
+		       void *data,
+		       int *err);
+
+/* Look for the section NAME in OBJFILE.  This returns information for
+   the first section NAME in OBJFILE.
+
+   If found, return 1 and set *OFFSET to the offset in the file of the
+   section contents and set *LENGTH to the length of the section
+   contents.  *OFFSET will be relative to the offset passed to
+   objfile_open_read.
+
+   If the section is not found, and no error occurs, return 0 and set
+   *ERRMSG to NULL.
+
+   If an error occurs, return 0, set *ERRMSG to an error message, and
+   set *ERR to an errno value or 0 if there is no relevant errno.  */
+
+extern int
+objfile_find_section (objfile_read *objfile, const char *name,
+		      off_t *offset, off_t *length,
+		      const char **errmsg, int *err);
+
+/* Release all resources associated with OBJFILE.  This does not close
+   the file descriptor.  */
+
+extern void
+objfile_release_read (objfile_read *);
+
+/* The type objfile_attributes holds the attributes of an object file
+   that matter for creating a file or ensuring that two files are
+   compatible.  This is a set of magic numbers.  */
+
+typedef struct objfile_attributes_struct objfile_attributes;
+
+/* Fetch the attributes of OBJFILE.  This information will persist
+   until objfile_attributes_release is called, even if OBJFILE is
+   closed.  On error this returns NULL, sets *ERRMSG to an error
+   message, and sets *ERR to an errno value or 0 if there isn't
+   one.  */
+
+extern objfile_attributes *
+objfile_fetch_attributes (objfile_read *objfile, const char **errmsg,
+			  int *err);
+
+/* Compare ATTRS1 and ATTRS2.  If they could be linked together
+   without error, return NULL.  Otherwise, return an error message,
+   set *ERR to an errno value or 0 if there isn't one.  */
+
+extern const char *
+objfile_attributes_compare (objfile_attributes *attrs1,
+			    objfile_attributes *attrs2,
+			    int *err);
+
+/* Release all resources associated with ATTRS.  */
+
+extern void
+objfile_release_attributes (objfile_attributes *attrs);
+
+/* The type objfile_write is used to create a new object file.  */
+
+typedef struct objfile_write_struct objfile_write;
+
+/* Start creating a new object file which is like ATTRS.  You must
+   fetch attribute information from an existing object file before you
+   can create a new one.  There is currently no support for creating
+   an object file de novo.  The segment name is only used on Mach-O,
+   where it is required.  It means that all sections are created
+   within that segment.  It is ignored for other object file formats.
+   On error this function returns NULL, sets *ERRMSG to an error
+   message, and sets *ERR to an errno value or 0 if there isn't
+   one.  */
+
+extern objfile_write *
+objfile_start_write (objfile_attributes *ATTRS, const char *segment_name,
+		     const char **errmsg, int *err);
+
+/* The type objfile_write_section is a handle for a section which is
+   being written.  */
+
+typedef struct objfile_write_section_struct objfile_write_section;
+
+/* Add a section to OBJFILE.  NAME is the name of the new section.
+   ALIGN is the required alignment expressed as the number of required
+   low-order 0 bits (e.g., 2 for alignment to a 32-bit boundary).  The
+   section is created as containing data, readable, not writable, not
+   executable, not loaded at runtime.  On error this returns NULL,
+   sets *ERRMSG to an error message, and sets *ERR to an errno value
+   or 0 if there isn't one.  */
+
+extern objfile_write_section *
+objfile_write_create_section (objfile_write *objfile, const char *name,
+			      unsigned int align, const char **errmsg,
+			      int *err);
+
+/* Add data BUFFER/SIZE to SECTION in OBJFILE.  If COPY is non-zero,
+   the data will be copied into memory if necessary.  If COPY is zero,
+   BUFFER must persist until OBJFILE is released.  On success this
+   returns NULL.  On error this returns an error message, and sets
+   *ERR to an errno value or 0 if there isn't one.  */
+
+extern const char *
+objfile_write_add_data (objfile_write *objfile,
+			objfile_write_section *section,
+			const void *buffer, size_t size,
+			int copy, int *err);
+
+/* Write the complete object file to DESCRIPTOR, an open file
+   descriptor.  This returns NULL on success.  On error this returns
+   an error message, and sets *ERR to an errno value or 0 if there
+   isn't one.  */
+
+extern const char *
+objfile_write_to_file (objfile_write *objfile, int descriptor,
+		       int *err);
+
+/* Release all resources associated with OBJFILE, including any
+   objfile_write_section's that may have been created.  */
+
+extern void
+objfile_release_write (objfile_write *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: libiberty/objfile-mach-o.c
===================================================================
--- libiberty/objfile-mach-o.c	(revision 0)
+++ libiberty/objfile-mach-o.c	(revision 0)
@@ -0,0 +1,1014 @@
+/* objfile-mach-o.c -- routines to manipulate Mach-O object files.
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+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, 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, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "libiberty.h"
+#include "objfile.h"
+
+#include <stddef.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "objfile-common.h"
+
+/* Mach-O structures and constants.  */
+
+/* Mach-O header (32-bit version).  */
+
+struct mach_o_header_32
+{
+  unsigned char magic[4];	/* Magic number.  */
+  unsigned char cputype[4];	/* CPU that this object is for.  */
+  unsigned char cpusubtype[4];	/* CPU subtype.  */
+  unsigned char filetype[4];	/* Type of file.  */
+  unsigned char ncmds[4];	/* Number of load commands.  */
+  unsigned char sizeofcmds[4];	/* Total size of load commands.  */
+  unsigned char flags[4];	/* Flags for special featues.  */
+};
+
+/* Mach-O header (64-bit version).  */
+
+struct mach_o_header_64
+{
+  unsigned char magic[4];	/* Magic number.  */
+  unsigned char cputype[4];	/* CPU that this object is for.  */
+  unsigned char cpusubtype[4];	/* CPU subtype.  */
+  unsigned char filetype[4];	/* Type of file.  */
+  unsigned char ncmds[4];	/* Number of load commands.  */
+  unsigned char sizeofcmds[4];	/* Total size of load commands.  */
+  unsigned char flags[4];	/* Flags for special featues.  */
+  unsigned char reserved[4];	/* Reserved.  Duh.  */
+};
+
+/* For magic field in header.  */
+
+#define MACH_O_MH_MAGIC			0xfeedface
+#define MACH_O_MH_MAGIC_64		0xfeedfacf
+
+/* For filetype field in header.  */
+
+#define MACH_O_MH_OBJECT		0x01
+
+/* A Mach-O file is a list of load commands.  This is the header of a
+   load command.  */
+
+struct mach_o_load_command
+{
+  unsigned char cmd[4];		/* The type of load command.  */
+  unsigned char cmdsize[4];	/* Size in bytes of entire command.  */
+};
+
+/* For cmd field in load command.   */
+
+#define MACH_O_LC_SEGMENT		0x01
+#define MACH_O_LC_SEGMENT_64		0x19
+
+/* LC_SEGMENT load command.  */
+
+struct mach_o_segment_command_32
+{
+  unsigned char cmd[4];		/* The type of load command (LC_SEGMENT).  */
+  unsigned char cmdsize[4];	/* Size in bytes of entire command.  */
+  unsigned char segname[16];	/* Name of this segment.  */
+  unsigned char vmaddr[4];	/* Virtual memory address of this segment.  */
+  unsigned char vmsize[4];	/* Size there, in bytes.  */
+  unsigned char fileoff[4];	/* Offset in bytes of the data to be mapped.  */
+  unsigned char filesize[4];	/* Size in bytes on disk.  */
+  unsigned char maxprot[4];	/* Maximum permitted vmem protection.  */
+  unsigned char initprot[4];	/* Initial vmem protection.  */
+  unsigned char nsects[4];	/* Number of sections in this segment.  */
+  unsigned char flags[4];	/* Flags that affect the loading.  */
+};
+
+/* LC_SEGMENT_64 load command.  */
+
+struct mach_o_segment_command_64
+{
+  unsigned char cmd[4];		/* The type of load command (LC_SEGMENT_64).  */
+  unsigned char cmdsize[4];	/* Size in bytes of entire command.  */
+  unsigned char segname[16];	/* Name of this segment.  */
+  unsigned char vmaddr[8];	/* Virtual memory address of this segment.  */
+  unsigned char vmsize[8];	/* Size there, in bytes.  */
+  unsigned char fileoff[8];	/* Offset in bytes of the data to be mapped.  */
+  unsigned char filesize[8];	/* Size in bytes on disk.  */
+  unsigned char maxprot[4];	/* Maximum permitted vmem protection.  */
+  unsigned char initprot[4];	/* Initial vmem protection.  */
+  unsigned char nsects[4];	/* Number of sections in this segment.  */
+  unsigned char flags[4];	/* Flags that affect the loading.  */
+};
+
+/* 32-bit section header.  */
+
+struct mach_o_section_32
+{
+  unsigned char sectname[16];	/* Section name.  */
+  unsigned char segname[16];	/* Segment that the section belongs to.  */
+  unsigned char addr[4];	/* Address of this section in memory.  */
+  unsigned char size[4];	/* Size in bytes of this section.  */
+  unsigned char offset[4];	/* File offset of this section.  */
+  unsigned char align[4];	/* log2 of this section's alignment.  */
+  unsigned char reloff[4];	/* File offset of this section's relocs.  */
+  unsigned char nreloc[4];	/* Number of relocs for this section.  */
+  unsigned char flags[4];	/* Section flags/attributes.  */
+  unsigned char reserved1[4];
+  unsigned char reserved2[4];
+};
+
+/* 64-bit section header.  */
+
+struct mach_o_section_64
+{
+  unsigned char sectname[16];	/* Section name.  */
+  unsigned char segname[16];	/* Segment that the section belongs to.  */
+  unsigned char addr[8];	/* Address of this section in memory.  */
+  unsigned char size[8];	/* Size in bytes of this section.  */
+  unsigned char offset[4];	/* File offset of this section.  */
+  unsigned char align[4];	/* log2 of this section's alignment.  */
+  unsigned char reloff[4];	/* File offset of this section's relocs.  */
+  unsigned char nreloc[4];	/* Number of relocs for this section.  */
+  unsigned char flags[4];	/* Section flags/attributes.  */
+  unsigned char reserved1[4];
+  unsigned char reserved2[4];
+  unsigned char reserved3[4];
+};
+
+/* Flags for Mach-O sections.  */
+
+#define MACH_O_S_ATTR_DEBUG			0x02000000
+
+/* The length of a segment or section name.  */
+
+#define MACH_O_NAME_LEN (16)
+
+/* A GNU specific extension for long section names.  */
+
+#define GNU_SECTION_NAMES "__section_names"
+
+/* Private data for an objfile_read.  */
+
+struct objfile_mach_o_read
+{
+  /* User specified segment name.  */
+  char *segment_name;
+  /* Magic number.  */
+  unsigned int magic;
+  /* Whether this file is big-endian.  */
+  int is_big_endian;
+  /* CPU type from header.  */
+  unsigned int cputype;
+  /* CPU subtype from header.  */
+  unsigned int cpusubtype;
+  /* Number of commands, from header.  */
+  unsigned int ncmds;
+  /* Flags from header.  */
+  unsigned int flags;
+  /* Reserved field from header, only used on 64-bit.  */
+  unsigned int reserved;
+};
+
+/* Private data for an objfile_attributes.  */
+
+struct objfile_mach_o_attributes
+{
+  /* Magic number.  */
+  unsigned int magic;
+  /* Whether this file is big-endian.  */
+  int is_big_endian;
+  /* CPU type from header.  */
+  unsigned int cputype;
+  /* CPU subtype from header.  */
+  unsigned int cpusubtype;
+  /* Flags from header.  */
+  unsigned int flags;
+  /* Reserved field from header, only used on 64-bit.  */
+  unsigned int reserved;
+};
+
+/* See if we have a Mach-O file.  */
+
+static void *
+objfile_mach_o_match (unsigned char header[OBJFILE_MATCH_HEADER_LEN],
+		      int descriptor, off_t offset, const char *segment_name,
+		      const char **errmsg, int *err)
+{
+  unsigned int magic;
+  int is_big_endian;
+  unsigned int (*fetch_32) (const unsigned char *);
+  unsigned int filetype;
+  struct objfile_mach_o_read *omr;
+  unsigned char buf[sizeof (struct mach_o_header_64)];
+  unsigned char *b;
+
+  magic = objfile_fetch_big_32 (header);
+  if (magic == MACH_O_MH_MAGIC || magic == MACH_O_MH_MAGIC_64)
+    is_big_endian = 1;
+  else
+    {
+      magic = objfile_fetch_little_32 (header);
+      if (magic == MACH_O_MH_MAGIC || magic == MACH_O_MH_MAGIC_64)
+	is_big_endian = 0;
+      else
+	{
+	  *errmsg = NULL;
+	  *err = 0;
+	  return NULL;
+	}
+    }
+
+#ifndef UNSIGNED_64BIT_TYPE
+  if (magic == MACH_O_MH_MAGIC_64)
+    {
+      *errmsg = "64-bit Mach-O objects not supported";
+      *err = 0;
+      return NULL;
+    }
+#endif
+
+  /* We require the user to provide a segment name.  This is
+     unfortunate but I don't see any good choices here.  */
+
+  if (segment_name == NULL)
+    {
+      *errmsg = "Mach-O file found but no segment name specified";
+      *err = 0;
+      return NULL;
+    }
+
+  if (strlen (segment_name) > MACH_O_NAME_LEN)
+    {
+      *errmsg = "Mach-O segment name too long";
+      *err = 0;
+      return NULL;
+    }
+
+  /* The 32-bit and 64-bit headers are similar enough that we can use
+     the same code.  */
+
+  fetch_32 = is_big_endian ? objfile_fetch_big_32 : objfile_fetch_little_32;
+
+  if (!objfile_internal_read (descriptor, offset, buf,
+			      (magic == MACH_O_MH_MAGIC
+			       ? sizeof (struct mach_o_header_32)
+			       : sizeof (struct mach_o_header_64)),
+			      errmsg, err))
+    return NULL;
+
+  b = &buf[0];
+
+  filetype = (*fetch_32) (b + offsetof (struct mach_o_header_32, filetype));
+  if (filetype != MACH_O_MH_OBJECT)
+    {
+      *errmsg = "Mach-O file is not object file";
+      *err = 0;
+      return NULL;
+    }
+
+  omr = XNEW (struct objfile_mach_o_read);
+  omr->segment_name = xstrdup (segment_name);
+  omr->magic = magic;
+  omr->is_big_endian = is_big_endian;
+  omr->cputype = (*fetch_32) (b + offsetof (struct mach_o_header_32, cputype));
+  omr->cpusubtype = (*fetch_32) (b
+				 + offsetof (struct mach_o_header_32,
+					     cpusubtype));
+  omr->ncmds = (*fetch_32) (b + offsetof (struct mach_o_header_32, ncmds));
+  omr->flags = (*fetch_32) (b + offsetof (struct mach_o_header_32, flags));
+  if (magic == MACH_O_MH_MAGIC)
+    omr->reserved = 0;
+  else
+    omr->reserved = (*fetch_32) (b
+				 + offsetof (struct mach_o_header_64,
+					     reserved));
+
+  return (void *) omr;
+}
+
+/* Get the file offset and size from a section header.  */
+
+static void
+objfile_mach_o_section_info (int is_big_endian, int is_32,
+			     const unsigned char *sechdr, off_t *offset,
+			     size_t *size)
+{
+  unsigned int (*fetch_32) (const unsigned char *);
+  ulong_type (*fetch_64) (const unsigned char *);
+
+  fetch_32 = (is_big_endian
+	      ? objfile_fetch_big_32
+	      : objfile_fetch_little_32);
+
+  fetch_64 = NULL;
+#ifdef UNSIGNED_64BIT_TYPE
+  fetch_64 = (is_big_endian
+	      ? objfile_fetch_big_64
+	      : objfile_fetch_little_64);
+#endif
+
+  if (is_32)
+    {
+      *offset = fetch_32 (sechdr
+			  + offsetof (struct mach_o_section_32, offset));
+      *size = fetch_32 (sechdr
+			+ offsetof (struct mach_o_section_32, size));
+    }
+  else
+    {
+      *offset = fetch_32 (sechdr
+			  + offsetof (struct mach_o_section_64, offset));
+      *size = fetch_64 (sechdr
+			+ offsetof (struct mach_o_section_64, size));
+    }
+}
+
+/* Handle a segment in a Mach-O file.  Return 1 if we should continue,
+   0 if the caller should return.  */
+
+static int
+objfile_mach_o_segment (objfile_read *objfile, off_t offset,
+			const unsigned char *segbuf,
+			int (*pfn) (void *, const char *, off_t offset,
+				    off_t length),
+			void *data,
+			const char **errmsg, int *err)
+{
+  struct objfile_mach_o_read *omr =
+    (struct objfile_mach_o_read *) objfile->data;
+  unsigned int (*fetch_32) (const unsigned char *);
+  ulong_type (*fetch_64) (const unsigned char *);
+  int is_32;
+  size_t seghdrsize;
+  size_t sechdrsize;
+  size_t sectname_offset;
+  unsigned int nsects;
+  unsigned char *secdata;
+  unsigned int i;
+  unsigned int strtab_index;
+  char *strtab;
+  size_t strtab_size;
+
+  fetch_32 = (omr->is_big_endian
+	      ? objfile_fetch_big_32
+	      : objfile_fetch_little_32);
+
+  fetch_64 = NULL;
+#ifdef UNSIGNED_64BIT_TYPE
+  fetch_64 = (omr->is_big_endian
+	      ? objfile_fetch_big_64
+	      : objfile_fetch_little_64);
+#endif
+
+  is_32 = omr->magic == MACH_O_MH_MAGIC;
+
+  if (is_32)
+    {
+      seghdrsize = sizeof (struct mach_o_segment_command_32);
+      sechdrsize = sizeof (struct mach_o_section_32);
+      sectname_offset = offsetof (struct mach_o_section_32, sectname);
+      nsects = (*fetch_32) (segbuf
+			    + offsetof (struct mach_o_segment_command_32,
+					nsects));
+    }
+  else
+    {
+      seghdrsize = sizeof (struct mach_o_segment_command_64);
+      sechdrsize = sizeof (struct mach_o_section_64);
+      sectname_offset = offsetof (struct mach_o_section_64, sectname);
+      nsects = (*fetch_32) (segbuf
+			    + offsetof (struct mach_o_segment_command_64,
+					nsects));
+    }
+
+  secdata = XNEWVEC (unsigned char, nsects * sechdrsize);
+  if (!objfile_internal_read (objfile->descriptor, offset + seghdrsize,
+			      secdata, nsects * sechdrsize, errmsg, err))
+    {
+      XDELETEVEC (secdata);
+      return 0;
+    }
+
+  /* Scan for a __section_names section.  This is in effect a GNU
+     extension that permits section names longer than 16 chars.  */
+
+  for (i = 0; i < nsects; ++i)
+    {
+      size_t nameoff;
+
+      nameoff = i * sechdrsize + sectname_offset;
+      if (strcmp ((char *) secdata + nameoff, GNU_SECTION_NAMES) == 0)
+	break;
+    }
+
+  strtab_index = i;
+  if (strtab_index >= nsects)
+    {
+      strtab = NULL;
+      strtab_size = 0;
+    }
+  else
+    {
+      off_t strtab_offset;
+
+      objfile_mach_o_section_info (omr->is_big_endian, is_32,
+				   secdata + strtab_index * sechdrsize,
+				   &strtab_offset, &strtab_size);
+      strtab = XNEWVEC (char, strtab_size);
+      if (!objfile_internal_read (objfile->descriptor, strtab_offset,
+				  (unsigned char *) strtab, strtab_size,
+				  errmsg, err))
+	{
+	  XDELETEVEC (strtab);
+	  XDELETEVEC (secdata);
+	  return 0;
+	}
+    }
+
+  /* Process the sections.  */
+
+  for (i = 0; i < nsects; ++i)
+    {
+      const unsigned char *sechdr;
+      char namebuf[MACH_O_NAME_LEN + 1];
+      char *name;
+      off_t secoffset;
+      size_t secsize;
+
+      if (i == strtab_index)
+	continue;
+
+      sechdr = secdata + i * sechdrsize;
+      memcpy (name, sechdr + sectname_offset, MACH_O_NAME_LEN);
+      namebuf[MACH_O_NAME_LEN] = '\0';
+
+      name = &namebuf[0];
+      if (strtab != NULL && name[0] == '_' && name[1] == '_')
+	{
+	  unsigned long stringoffset;
+
+	  if (sscanf (name + 2, "%08lX", &stringoffset) == 1)
+	    {
+	      if (stringoffset >= strtab_size)
+		{
+		  *errmsg = "section name offset out of range";
+		  *err = 0;
+		  XDELETEVEC (strtab);
+		  XDELETEVEC (secdata);
+		  return 0;
+		}
+
+	      name = strtab + stringoffset;
+	    }
+	}
+
+      objfile_mach_o_section_info (omr->is_big_endian, is_32, sechdr,
+				   &secoffset, &secsize);
+
+      if (!(*pfn) (data, name, secoffset, secsize))
+	{
+	  *errmsg = NULL;
+	  *err = 0;
+	  XDELETEVEC (strtab);
+	  XDELETEVEC (secdata);
+	  return 0;
+	}
+    }
+
+  XDELETEVEC (strtab);
+  XDELETEVEC (secdata);
+
+  return 1;
+}
+
+/* Find all sections in a Mach-O file.  */
+
+static const char *
+objfile_mach_o_find_sections (objfile_read *objfile,
+			      int (*pfn) (void *, const char *, off_t offset,
+					  off_t length),
+			      void *data,
+			      int *err)
+{
+  struct objfile_mach_o_read *omr =
+    (struct objfile_mach_o_read *) objfile->data;
+  off_t offset;
+  size_t seghdrsize;
+  unsigned int (*fetch_32) (const unsigned char *);
+  const char *errmsg;
+  unsigned int i;
+
+  if (omr->magic == MACH_O_MH_MAGIC)
+    {
+      offset = sizeof (struct mach_o_header_32);
+      seghdrsize = sizeof (struct mach_o_segment_command_32);
+    }
+  else
+    {
+      offset = sizeof (struct mach_o_header_64);
+      seghdrsize = sizeof (struct mach_o_segment_command_64);
+    }
+
+  fetch_32 = (omr->is_big_endian
+	      ? objfile_fetch_big_32
+	      : objfile_fetch_little_32);
+
+  for (i = 0; i < omr->ncmds; ++i)
+    {
+      unsigned char loadbuf[sizeof (struct mach_o_load_command)];
+      unsigned int cmd;
+      unsigned int cmdsize;
+
+      if (!objfile_internal_read (objfile->descriptor,
+				  objfile->offset + offset,
+				  loadbuf, sizeof (struct mach_o_load_command),
+				  &errmsg, err))
+	return errmsg;
+
+      cmd = (*fetch_32) (loadbuf + offsetof (struct mach_o_load_command, cmd));
+      cmdsize = (*fetch_32) (loadbuf
+			     + offsetof (struct mach_o_load_command, cmdsize));
+
+      if (cmd == MACH_O_LC_SEGMENT || cmd == MACH_O_LC_SEGMENT_64)
+	{
+	  unsigned char segbuf[sizeof (struct mach_o_segment_command_64)];
+	  char *segname;
+
+	  if (!objfile_internal_read (objfile->descriptor, offset, segbuf,
+				      seghdrsize, &errmsg, err))
+	    return errmsg;
+
+	  /* The segment name is in the same position for both 32-bit
+	     and 64-bit.  */
+	  segname = (char *) (&segbuf[0]
+			      + offsetof (struct mach_o_segment_command_32,
+					  segname));
+	  if (strncmp (omr->segment_name, segname, MACH_O_NAME_LEN) == 0)
+	    {
+	      int r;
+
+	      r = objfile_mach_o_segment (objfile, offset, segbuf, pfn,
+					  data, &errmsg, err);
+	      if (!r)
+		return errmsg;
+
+	      /* We can probably just return NULL here.  There
+		 probably won't be another function with the same
+		 name.  */
+	    }
+	}
+
+      offset += cmdsize;
+    }
+
+  return NULL;
+}
+
+/* Fetch the attributes for an objfile_read.  */
+
+static void *
+objfile_mach_o_fetch_attributes (objfile_read *objfile,
+				 const char **errmsg ATTRIBUTE_UNUSED,
+				 int *err ATTRIBUTE_UNUSED)
+{
+  struct objfile_mach_o_read *omr =
+    (struct objfile_mach_o_read *) objfile->data;
+  struct objfile_mach_o_attributes *ret;
+
+  ret = XNEW (struct objfile_mach_o_attributes);
+  ret->magic = omr->magic;
+  ret->is_big_endian = omr->is_big_endian;
+  ret->cputype = omr->cputype;
+  ret->cpusubtype = omr->cpusubtype;
+  ret->flags = omr->flags;
+  ret->reserved = omr->reserved;
+  return ret;
+}
+
+/* Release the private data for an objfile_read.  */
+
+static void
+objfile_mach_o_release_read (void *data)
+{
+  struct objfile_mach_o_read *omr =
+    (struct objfile_mach_o_read *) data;
+
+  free (omr->segment_name);
+  XDELETE (omr);
+}
+
+/* Compare two attributes structures.  */
+
+static const char *
+objfile_mach_o_attributes_compare (void *data1, void *data2, int *err)
+{
+  struct objfile_mach_o_attributes *attrs1 =
+    (struct objfile_mach_o_attributes *) data1;
+  struct objfile_mach_o_attributes *attrs2 =
+    (struct objfile_mach_o_attributes *) data2;
+
+  if (attrs1->magic != attrs2->magic
+      || attrs1->is_big_endian != attrs2->is_big_endian
+      || attrs1->cputype != attrs2->cputype)
+    {
+      *err = 0;
+      return "Mach-O object format mismatch";
+    }
+  return NULL;
+}
+
+/* Release the private data for an attributes structure.  */
+
+static void
+objfile_mach_o_release_attributes (void *data)
+{
+  XDELETE (data);
+}
+
+/* Prepare to write out a file.  */
+
+static void *
+objfile_mach_o_start_write (void *attributes_data,
+			    const char **errmsg ATTRIBUTE_UNUSED,
+			    int *err ATTRIBUTE_UNUSED)
+{
+  struct objfile_mach_o_attributes *attrs =
+    (struct objfile_mach_o_attributes *) attributes_data;
+  struct objfile_mach_o_attributes *ret;
+
+  /* We're just going to record the attributes, but we need to make a
+     copy because the user may delete them.  */
+  ret = XNEW (struct objfile_mach_o_attributes);
+  *ret = *attrs;
+  return ret;
+}
+
+/* Write out the header of a Mach-O file.  */
+
+static int
+objfile_mach_o_write_header (objfile_write *objfile, int descriptor,
+			     size_t nsects, const char **errmsg, int *err)
+{
+  struct objfile_mach_o_attributes *attrs =
+    (struct objfile_mach_o_attributes *) objfile->data;
+  void (*set_32) (unsigned char *, unsigned int);
+  unsigned char hdrbuf[sizeof (struct mach_o_header_64)];
+  unsigned char *hdr;
+  size_t wrsize;
+
+  set_32 = (attrs->is_big_endian
+	    ? objfile_set_big_32
+	    : objfile_set_little_32);
+
+  memset (hdrbuf, 0, sizeof hdrbuf);
+
+  /* The 32-bit and 64-bit headers start out the same.  */
+
+  hdr = &hdrbuf[0];
+  set_32 (hdr + offsetof (struct mach_o_header_32, magic), attrs->magic);
+  set_32 (hdr + offsetof (struct mach_o_header_32, cputype), attrs->cputype);
+  set_32 (hdr + offsetof (struct mach_o_header_32, cpusubtype),
+	  attrs->cpusubtype);
+  set_32 (hdr + offsetof (struct mach_o_header_32, filetype), MACH_O_MH_OBJECT);
+  set_32 (hdr + offsetof (struct mach_o_header_32, ncmds), 1);
+  set_32 (hdr + offsetof (struct mach_o_header_32, flags), attrs->flags);
+  if (attrs->magic == MACH_O_MH_MAGIC)
+    {
+      wrsize = sizeof (struct mach_o_header_32);
+      set_32 (hdr + offsetof (struct mach_o_header_32, sizeofcmds),
+	      (sizeof (struct mach_o_segment_command_32)
+	       + nsects * sizeof (struct mach_o_section_32)));
+    }
+  else
+    {
+      set_32 (hdr + offsetof (struct mach_o_header_64, sizeofcmds),
+	      (sizeof (struct mach_o_segment_command_64)
+	       + nsects * sizeof (struct mach_o_section_64)));
+      set_32 (hdr + offsetof (struct mach_o_header_64, reserved),
+	      attrs->reserved);
+      wrsize = sizeof (struct mach_o_header_64);
+    }
+
+  return objfile_internal_write (descriptor, 0, hdrbuf, wrsize, errmsg, err);
+}
+
+/* Write a Mach-O section header.  */
+
+static int
+objfile_mach_o_write_section_header (objfile_write *objfile, int descriptor,
+				     size_t sechdr_offset, const char *name,
+				     size_t secaddr, size_t secsize,
+				     size_t offset, unsigned int align,
+				     const char **errmsg, int *err)
+{
+  struct objfile_mach_o_attributes *attrs =
+    (struct objfile_mach_o_attributes *) objfile->data;
+  void (*set_32) (unsigned char *, unsigned int);
+  unsigned char hdrbuf[sizeof (struct mach_o_section_64)];
+  unsigned char *hdr;
+  size_t sechdrsize;
+
+  set_32 = (attrs->is_big_endian
+	    ? objfile_set_big_32
+	    : objfile_set_little_32);
+
+  memset (hdrbuf, 0, sizeof hdrbuf);
+
+  hdr = &hdrbuf[0];
+  if (attrs->magic == MACH_O_MH_MAGIC)
+    {
+      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, sectname),
+	       name, MACH_O_NAME_LEN);
+      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, segname),
+	       objfile->segment_name, MACH_O_NAME_LEN);
+      set_32 (hdr + offsetof (struct mach_o_section_32, addr), secaddr);
+      set_32 (hdr + offsetof (struct mach_o_section_32, size), secsize);
+      set_32 (hdr + offsetof (struct mach_o_section_32, offset), offset);
+      set_32 (hdr + offsetof (struct mach_o_section_32, align), align);
+      /* reloff left as zero.  */
+      /* nreloc left as zero.  */
+      set_32 (hdr + offsetof (struct mach_o_section_32, flags),
+	      MACH_O_S_ATTR_DEBUG);
+      /* reserved1 left as zero.  */
+      /* reserved2 left as zero.  */
+      sechdrsize = sizeof (struct mach_o_section_32);
+    }
+  else
+    {
+#ifdef UNSIGNED_64BIT_TYPE
+      void (*set_64) (unsigned char *, ulong_type);
+
+      set_64 = (attrs->is_big_endian
+		? objfile_set_big_64
+		: objfile_set_little_64);
+
+      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, sectname),
+	       name, MACH_O_NAME_LEN);
+      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, segname),
+	       objfile->segment_name, MACH_O_NAME_LEN);
+      set_64 (hdr + offsetof (struct mach_o_section_64, addr), secaddr);
+      set_64 (hdr + offsetof (struct mach_o_section_64, size), secsize);
+      set_32 (hdr + offsetof (struct mach_o_section_64, offset), offset);
+      set_32 (hdr + offsetof (struct mach_o_section_64, align), align);
+      /* reloff left as zero.  */
+      /* nreloc left as zero.  */
+      set_32 (hdr + offsetof (struct mach_o_section_64, flags),
+	      MACH_O_S_ATTR_DEBUG);
+      /* reserved1 left as zero.  */
+      /* reserved2 left as zero.  */
+      /* reserved3 left as zero.  */
+#endif
+      sechdrsize = sizeof (struct mach_o_section_64);
+    }
+
+  return objfile_internal_write (descriptor, sechdr_offset, hdr,
+				 sechdrsize, errmsg, err);
+}
+
+/* Write out the single segment and the sections of a Mach-O file.  */
+
+static int
+objfile_mach_o_write_segment (objfile_write *objfile, int descriptor,
+			      size_t nsects, const char **errmsg, int *err)
+{
+  struct objfile_mach_o_attributes *attrs =
+    (struct objfile_mach_o_attributes *) objfile->data;
+  void (*set_32) (unsigned char *, unsigned int);
+  size_t hdrsize;
+  size_t seghdrsize;
+  size_t sechdrsize;
+  size_t cmdsize;
+  size_t offset;
+  size_t sechdr_offset;
+  size_t secaddr;
+  unsigned int name_offset;
+  objfile_write_section *section;
+  unsigned char hdrbuf[sizeof (struct mach_o_segment_command_64)];
+  unsigned char *hdr;
+
+  set_32 = (attrs->is_big_endian
+	    ? objfile_set_big_32
+	    : objfile_set_little_32);
+
+  /* Write out the sections first.  */
+
+  if (attrs->magic == MACH_O_MH_MAGIC)
+    {
+      hdrsize = sizeof (struct mach_o_header_32);
+      seghdrsize = sizeof (struct mach_o_segment_command_32);
+      sechdrsize = sizeof (struct mach_o_section_32);
+    }
+  else
+    {
+      hdrsize = sizeof (struct mach_o_header_64);
+      seghdrsize = sizeof (struct mach_o_segment_command_64);
+      sechdrsize = sizeof (struct mach_o_section_64);
+    }
+
+  sechdr_offset = hdrsize + seghdrsize;
+  cmdsize = seghdrsize + nsects * sechdrsize;
+  offset = hdrsize + cmdsize;
+  name_offset = 0;
+  secaddr = 0;
+
+  for (section = objfile->sections; section != NULL; section = section->next)
+    {
+      size_t mask;
+      size_t new_offset;
+      size_t secsize;
+      struct objfile_write_section_buffer *buffer;
+      char namebuf[MACH_O_NAME_LEN + 1];
+
+      mask = (1U << section->align) - 1;
+      new_offset = offset + mask;
+      new_offset &= ~ mask;
+      while (new_offset > offset)
+	{
+	  unsigned char zeroes[16];
+	  size_t write;
+
+	  memset (zeroes, 0, sizeof zeroes);
+	  write = new_offset - offset;
+	  if (write > sizeof zeroes)
+	    write = sizeof zeroes;
+	  if (!objfile_internal_write (descriptor, offset, zeroes, write,
+				       errmsg, err))
+	    return 0;
+	  offset += write;
+	}
+
+      secsize = 0;
+      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
+	{
+	  if (!objfile_internal_write (descriptor, offset + secsize,
+				       (const unsigned char *) buffer->buffer,
+				       buffer->size, errmsg, err))
+	    return 0;
+	  secsize += buffer->size;
+	}
+
+      snprintf (namebuf, sizeof namebuf, "__%08X", name_offset);
+      if (!objfile_mach_o_write_section_header (objfile, descriptor,
+						sechdr_offset, namebuf,
+						secaddr, secsize, offset,
+						section->align, errmsg, err))
+	return 0;
+
+      sechdr_offset += sechdrsize;
+      offset += secsize;
+      name_offset += strlen (section->name) + 1;
+      secaddr += secsize;
+    }
+
+  /* Write out the section names.  */
+
+  if (!objfile_mach_o_write_section_header (objfile, descriptor, sechdr_offset,
+					    GNU_SECTION_NAMES, secaddr,
+					    name_offset, offset, 0,
+					    errmsg, err))
+    return 0;
+
+  for (section = objfile->sections; section != NULL; section = section->next)
+    {
+      size_t namelen;
+
+      namelen = strlen (section->name) + 1;
+      if (!objfile_internal_write (descriptor, offset,
+				   (const unsigned char *) section->name,
+				   namelen, errmsg, err))
+	return 0;
+      offset += namelen;
+    }
+
+  /* Write out the segment header.  */
+
+  memset (hdrbuf, 0, sizeof hdrbuf);
+
+  hdr = &hdrbuf[0];
+  if (attrs->magic == MACH_O_MH_MAGIC)
+    {
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd),
+	      MACH_O_LC_SEGMENT);
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
+	      cmdsize);
+      strncpy (((char *) hdr
+		+ offsetof (struct mach_o_segment_command_32, segname)),
+	       objfile->segment_name, MACH_O_NAME_LEN);
+      /* vmaddr left as zero.  */
+      /* vmsize left as zero.  */
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
+	      hdrsize + cmdsize);
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, filesize),
+	      offset - (hdrsize + cmdsize));
+      /* maxprot left as zero.  */
+      /* initprot left as zero.  */
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
+	      nsects);
+      /* flags left as zero.  */
+    }
+  else
+    {
+#ifdef UNSIGNED_64BIT_TYPE
+      void (*set_64) (unsigned char *, ulong_type);
+
+      set_64 = (attrs->is_big_endian
+		? objfile_set_big_64
+		: objfile_set_little_64);
+
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd),
+	      MACH_O_LC_SEGMENT);
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
+	      cmdsize);
+      strncpy (((char *) hdr
+		+ offsetof (struct mach_o_segment_command_32, segname)),
+	       objfile->segment_name, MACH_O_NAME_LEN);
+      /* vmaddr left as zero.  */
+      /* vmsize left as zero.  */
+      set_64 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
+	      hdrsize + cmdsize);
+      set_64 (hdr + offsetof (struct mach_o_segment_command_32, filesize),
+	      offset - (hdrsize + cmdsize));
+      /* maxprot left as zero.  */
+      /* initprot left as zero.  */
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
+	      nsects);
+      /* flags left as zero.  */
+#endif
+    }
+
+  return objfile_internal_write (descriptor, hdrsize, hdr, seghdrsize,
+				 errmsg, err);
+}
+
+/* Write out a complete Mach-O file.  */
+
+static const char *
+objfile_mach_o_write_to_file (objfile_write *objfile, int descriptor, int *err)
+{
+  size_t nsects;
+  objfile_write_section *section;
+  const char *errmsg;
+
+  /* Start at 1 for symbol_names section.  */
+  nsects = 1;
+  for (section = objfile->sections; section != NULL; section = section->next)
+    ++nsects;
+
+  if (!objfile_mach_o_write_header (objfile, descriptor, nsects, &errmsg, err))
+    return errmsg;
+
+  if (!objfile_mach_o_write_segment (objfile, descriptor, nsects, &errmsg, err))
+    return errmsg;
+
+  return NULL;
+}
+
+/* Release the private data for an objfile_write structure.  */
+
+static void
+objfile_mach_o_release_write (void *data)
+{
+  XDELETE (data);
+}
+
+/* The Mach-O functions.  */
+
+const struct objfile_functions objfile_mach_o_functions =
+{
+  objfile_mach_o_match,
+  objfile_mach_o_find_sections,
+  objfile_mach_o_fetch_attributes,
+  objfile_mach_o_release_read,
+  objfile_mach_o_attributes_compare,
+  objfile_mach_o_release_attributes,
+  objfile_mach_o_start_write,
+  objfile_mach_o_write_to_file,
+  objfile_mach_o_release_write
+};
Index: libiberty/configure.ac
===================================================================
--- libiberty/configure.ac	(revision 166002)
+++ libiberty/configure.ac	(working copy)
@@ -290,6 +290,7 @@ fi
 
 AC_TYPE_INTPTR_T
 AC_TYPE_UINTPTR_T
+AC_TYPE_SSIZE_T
 
 # Given the above check, we always have uintptr_t or a fallback
 # definition.  So define HAVE_UINTPTR_T in case any imported code
Index: libiberty/objfile-common.h
===================================================================
--- libiberty/objfile-common.h	(revision 0)
+++ libiberty/objfile-common.h	(revision 0)
@@ -0,0 +1,352 @@
+/* objfile-common.h -- common structs for object file manipulation.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If not,
+write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+/* Forward reference.  */
+struct objfile_functions;
+
+/* An object file opened for reading.  */
+
+struct objfile_read_struct
+{
+  /* The file descriptor.  */
+  int descriptor;
+  /* The offset within the file.  */
+  off_t offset;
+  /* The functions which do the actual work.  */
+  const struct objfile_functions *functions;
+  /* Private data for the object file format.  */
+  void *data;
+};
+
+/* Object file attributes.  */
+
+struct objfile_attributes_struct
+{
+  /* The functions which do the actual work.  */
+  const struct objfile_functions *functions;
+  /* Private data for the object file format.  */
+  void *data;
+};
+
+/* An object file being created.  */
+
+struct objfile_write_struct
+{
+  /* The functions which do the actual work.  */
+  const struct objfile_functions *functions;
+  /* The segment_name argument from the user.  */
+  char *segment_name;
+  /* The start of the list of sections.  */
+  objfile_write_section *sections;
+  /* The last entry in the list of sections.  */
+  objfile_write_section *last_section;
+  /* Private data for the object file format.  */
+  void *data;
+};
+
+/* A section in an object file being created.  */
+
+struct objfile_write_section_struct
+{
+  /* Next in the list of sections attached to an objfile_write.  */
+  objfile_write_section *next;
+  /* The name of this section.  */
+  char *name;
+  /* The required alignment.  */
+  unsigned int align;
+  /* The first data attached to this section.  */
+  struct objfile_write_section_buffer *buffers;
+  /* The last data attached to this section.  */
+  struct objfile_write_section_buffer *last_buffer;
+};
+
+/* Data attached to a section.  */
+
+struct objfile_write_section_buffer
+{
+  /* The next data for this section.  */
+  struct objfile_write_section_buffer *next;
+  /* The size of the buffer.  */
+  size_t size;
+  /* The actual bytes.  */
+  const void *buffer;
+  /* A buffer to free, or NULL.  */
+  void *free_buffer;
+};
+
+/* The number of bytes we read from the start of the file to pass to
+   the match function.  */
+#define OBJFILE_MATCH_HEADER_LEN (16)
+
+/* Format-specific object file functions.  */
+
+struct objfile_functions
+{
+  /* If this file matches these functions, return a new value for the
+     private data for an objfile_read.  HEADER is the first 16 bytes
+     of the file.  DESCRIPTOR, OFFSET, SEGMENT_NAME, ERRMSG, and ERR
+     are as for objfile_open_read.  If this file does not match, this
+     function should return NULL with *ERRMSG set to NULL.  */
+  void *(*match) (unsigned char header[OBJFILE_MATCH_HEADER_LEN],
+		  int descriptor, off_t offset, const char *segment_name,
+		  const char **errmsg, int *err);
+
+  /* Implement objfile_find_sections.  */
+  const char *(*find_sections) (objfile_read *,
+				int (*pfn) (void *, const char *,
+					    off_t offset, off_t length),
+				void *data,
+				int *err);
+
+  /* Return the private data for the attributes for OBJFILE.  */
+  void *(*fetch_attributes) (objfile_read *objfile, const char **errmsg,
+			     int *err);
+
+  /* Release the private data for an objfile_read.  */
+  void (*release_read) (void *);
+
+  /* Compare the private data for the attributes of two files.  If
+     they are the same, in the sense that they could be linked
+     together, return NULL.  Otherwise return an error message.  */
+  const char *(*attributes_compare) (void *, void *, int *err);
+
+  /* Release the private data for an objfile_attributes.  */
+  void (*release_attributes) (void *);
+
+  /* Start creating an object file.  */
+  void *(*start_write) (void *attributes_data, const char **errmsg,
+			int *err);
+
+  /* Write the complete object file.  */
+  const char *(*write_to_file) (objfile_write *objfile, int descriptor,
+				int *err);
+
+  /* Release the private data for an objfile_write.  */
+  void (*release_write) (void *);
+};
+
+/* The known object file formats.  */
+
+extern const struct objfile_functions objfile_coff_functions;
+extern const struct objfile_functions objfile_elf_functions;
+extern const struct objfile_functions objfile_mach_o_functions;
+
+/* Read SIZE bytes from DESCRIPTOR at file offset OFFSET into BUFFER.
+   Return non-zero on success.  On failure return 0 and set *ERRMSG
+   and *ERR.  */
+
+extern int
+objfile_internal_read (int descriptor, off_t offset, unsigned char *buffer,
+		       size_t size, const char **errmsg, int *err);
+
+/* Write SIZE bytes from BUFFER to DESCRIPTOR at file offset OFFSET.
+   Return non-zero on success.  On failure return 0 and set *ERRMSG
+   and *ERR.  */
+
+extern int
+objfile_internal_write (int descriptor, off_t offset,
+			const unsigned char *buffer, size_t size,
+			const char **errmsg, int *err);
+
+/* Define ulong_type as an unsigned 64-bit type if available.
+   Otherwise just make it unsigned long.  */
+
+#ifdef UNSIGNED_64BIT_TYPE
+__extension__ typedef UNSIGNED_64BIT_TYPE ulong_type;
+#else
+typedef unsigned long ulong_type;
+#endif
+
+/* Fetch a big-endian 16-bit value.  */
+
+static inline unsigned short
+objfile_fetch_big_16 (const unsigned char *buf)
+{
+  return ((unsigned short) buf[0] << 8) | (unsigned short) buf[1];
+}
+
+/* Fetch a little-endian 16-bit value.  */
+
+static inline unsigned short
+objfile_fetch_little_16 (const unsigned char *buf)
+{
+  return ((unsigned short) buf[1] << 8) | (unsigned short) buf[0];
+}
+
+/* Fetch a big-endian 32-bit value.  */
+
+static inline unsigned int
+objfile_fetch_big_32 (const unsigned char *buf)
+{
+  return (((unsigned int) buf[0] << 24)
+	  | ((unsigned int) buf[1] << 16)
+	  | ((unsigned int) buf[2] << 8)
+	  | (unsigned int) buf[3]);
+}
+
+/* Fetch a little-endian 32-bit value.  */
+
+static inline unsigned int
+objfile_fetch_little_32 (const unsigned char *buf)
+{
+  return (((unsigned int) buf[3] << 24)
+	  | ((unsigned int) buf[2] << 16)
+	  | ((unsigned int) buf[1] << 8)
+	  | (unsigned int) buf[0]);
+}
+
+/* Fetch a big-endian 32-bit value as a ulong_type.  */
+
+static inline ulong_type
+objfile_fetch_big_32_ulong (const unsigned char *buf)
+{
+  return (ulong_type) objfile_fetch_big_32 (buf);
+}
+
+/* Fetch a little-endian 32-bit value as a ulong_type.  */
+
+static inline ulong_type
+objfile_fetch_little_32_ulong (const unsigned char *buf)
+{
+  return (ulong_type) objfile_fetch_little_32 (buf);
+}
+
+#ifdef UNSIGNED_64BIT_TYPE
+
+/* Fetch a big-endian 64-bit value.  */
+
+static inline ulong_type
+objfile_fetch_big_64 (const unsigned char *buf)
+{
+  return (((ulong_type) buf[0] << 56)
+	  | ((ulong_type) buf[1] << 48)
+	  | ((ulong_type) buf[2] << 40)
+	  | ((ulong_type) buf[3] << 32)
+	  | ((ulong_type) buf[4] << 24)
+	  | ((ulong_type) buf[5] << 16)
+	  | ((ulong_type) buf[6] << 8)
+	  | (ulong_type) buf[7]);
+}
+
+/* Fetch a little-endian 64-bit value.  */
+
+static inline ulong_type
+objfile_fetch_little_64 (const unsigned char *buf)
+{
+  return (((ulong_type) buf[7] << 56)
+	  | ((ulong_type) buf[6] << 48)
+	  | ((ulong_type) buf[5] << 40)
+	  | ((ulong_type) buf[4] << 32)
+	  | ((ulong_type) buf[3] << 24)
+	  | ((ulong_type) buf[2] << 16)
+	  | ((ulong_type) buf[1] << 8)
+	  | (ulong_type) buf[0]);
+}
+
+#endif
+
+/* Store a big-endian 16-bit value.  */
+
+static inline void
+objfile_set_big_16 (unsigned char *buf, unsigned short val)
+{
+  buf[0] = (val >> 8) & 0xff;
+  buf[1] = val & 0xff;
+}
+
+/* Store a little-endian 16-bit value.  */
+
+static inline void
+objfile_set_little_16 (unsigned char *buf, unsigned short val)
+{
+  buf[1] = (val >> 8) & 0xff;
+  buf[0] = val & 0xff;
+}
+
+/* Store a big-endian 32-bit value.  */
+
+static inline void
+objfile_set_big_32 (unsigned char *buf, unsigned int val)
+{
+  buf[0] = (val >> 24) & 0xff;
+  buf[1] = (val >> 16) & 0xff;
+  buf[2] = (val >> 8) & 0xff;
+  buf[3] = val & 0xff;
+}
+
+/* Store a little-endian 32-bit value.  */
+
+static inline void
+objfile_set_little_32 (unsigned char *buf, unsigned int val)
+{
+  buf[3] = (val >> 24) & 0xff;
+  buf[2] = (val >> 16) & 0xff;
+  buf[1] = (val >> 8) & 0xff;
+  buf[0] = val & 0xff;
+}
+
+/* Store a big-endian 32-bit value coming in as a ulong_type.  */
+
+static inline void
+objfile_set_big_32_ulong (unsigned char *buf, ulong_type val)
+{
+  objfile_set_big_32 (buf, val);
+}
+
+/* Store a little-endian 32-bit value coming in as a ulong_type.  */
+
+static inline void
+objfile_set_little_32_ulong (unsigned char *buf, ulong_type val)
+{
+  objfile_set_little_32 (buf, val);
+}
+
+#ifdef UNSIGNED_64BIT_TYPE
+
+/* Store a big-endian 64-bit value.  */
+
+static inline void
+objfile_set_big_64 (unsigned char *buf, ulong_type val)
+{
+  buf[0] = (val >> 56) & 0xff;
+  buf[1] = (val >> 48) & 0xff;
+  buf[2] = (val >> 40) & 0xff;
+  buf[3] = (val >> 32) & 0xff;
+  buf[4] = (val >> 24) & 0xff;
+  buf[5] = (val >> 16) & 0xff;
+  buf[6] = (val >> 8) & 0xff;
+  buf[7] = val & 0xff;
+}
+
+/* Store a little-endian 64-bit value.  */
+
+static inline void
+objfile_set_little_64 (unsigned char *buf, ulong_type val)
+{
+  buf[7] = (val >> 56) & 0xff;
+  buf[6] = (val >> 48) & 0xff;
+  buf[5] = (val >> 40) & 0xff;
+  buf[4] = (val >> 32) & 0xff;
+  buf[3] = (val >> 24) & 0xff;
+  buf[2] = (val >> 16) & 0xff;
+  buf[1] = (val >> 8) & 0xff;
+  buf[0] = val & 0xff;
+}
+
+#endif
Index: libiberty/objfile.c
===================================================================
--- libiberty/objfile.c	(revision 0)
+++ libiberty/objfile.c	(revision 0)
@@ -0,0 +1,418 @@
+/* objfile.c -- routines to manipulate object files.
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+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, 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, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "libiberty.h"
+#include "objfile.h"
+
+#include <errno.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#include "objfile-common.h"
+
+/* The known object file formats.  */
+
+static const struct objfile_functions * const format_functions[] =
+{
+  &objfile_elf_functions,
+  &objfile_mach_o_functions,
+  &objfile_coff_functions
+};
+
+/* Read data from a file using the objfile error reporting
+   conventions.  */
+
+int
+objfile_internal_read (int descriptor, off_t offset, unsigned char *buffer,
+		       size_t size, const char **errmsg, int *err)
+{
+  ssize_t got;
+
+  if (lseek (descriptor, offset, SEEK_SET) < 0)
+    {
+      *errmsg = "lseek";
+      *err = errno;
+      return 0;
+    }
+
+  got = read (descriptor, buffer, size);
+  if (got < 0)
+    {
+      *errmsg = "read";
+      *err = errno;
+      return 0;
+    }
+
+  if ((size_t) got < size)
+    {
+      *errmsg = "file too short";
+      *err = 0;
+      return 0;
+    }
+
+  return 1;
+}
+
+/* Write data to a file using the objfile error reporting
+   conventions.  */
+
+int
+objfile_internal_write (int descriptor, off_t offset,
+			const unsigned char *buffer, size_t size,
+			const char **errmsg, int *err)
+{
+  ssize_t wrote;
+
+  if (lseek (descriptor, offset, SEEK_SET) < 0)
+    {
+      *errmsg = "lseek";
+      *err = errno;
+      return 0;
+    }
+
+  wrote = write (descriptor, buffer, size);
+  if (wrote < 0)
+    {
+      *errmsg = "write";
+      *err = errno;
+      return 0;
+    }
+
+  if ((size_t) wrote < size)
+    {
+      *errmsg = "short write";
+      *err = 0;
+      return 0;
+    }
+
+  return 1;
+}
+
+/* Open for read.  */
+
+objfile_read *
+objfile_open_read (int descriptor, off_t offset, const char *segment_name,
+		   const char **errmsg, int *err)
+{
+  unsigned char header[OBJFILE_MATCH_HEADER_LEN];
+  size_t len, i;
+
+  if (!objfile_internal_read (descriptor, offset, header,
+			      OBJFILE_MATCH_HEADER_LEN,
+			      errmsg, err))
+    return NULL;
+
+  len = sizeof (format_functions) / sizeof (format_functions[0]);
+  for (i = 0; i < len; ++i)
+    {
+      void *data;
+
+      data = format_functions[i]->match (header, descriptor, offset,
+					 segment_name, errmsg, err);
+      if (data != NULL)
+	{
+	  objfile_read *ret;
+
+	  ret = XNEW (objfile_read);
+	  ret->descriptor = descriptor;
+	  ret->offset = offset;
+	  ret->functions = format_functions[i];
+	  ret->data = data;
+	  return ret;
+	}
+    }
+
+  *errmsg = "file not recognized";
+  *err = 0;
+  return NULL;
+}
+
+/* Find all sections.  */
+
+const char *
+objfile_find_sections (objfile_read *objfile,
+		       int (*pfn) (void *, const char *, off_t, off_t),
+		       void *data,
+		       int *err)
+{
+  return objfile->functions->find_sections (objfile, pfn, data, err);
+}
+
+/* Internal data passed to find_one_section.  */
+
+struct find_one_section_data
+{
+  /* The section we are looking for.  */
+  const char *name;
+  /* Where to store the section offset.  */
+  off_t *offset;
+  /* Where to store the section length.  */
+  off_t *length;
+  /* Set if the name is found.  */
+  int found;
+};
+
+/* Internal function passed to find_sections.  */
+
+static int
+find_one_section (void *data, const char *name, off_t offset, off_t length)
+{
+  struct find_one_section_data *fosd = (struct find_one_section_data *) data;
+
+  if (strcmp (name, fosd->name) != 0)
+    return 1;
+
+  *fosd->offset = offset;
+  *fosd->length = length;
+  fosd->found = 1;
+
+  /* Stop iteration.  */
+  return 0;
+}
+
+/* Find a section.  */
+
+int
+objfile_find_section (objfile_read *objfile, const char *name,
+		      off_t *offset, off_t *length,
+		      const char **errmsg, int *err)
+{
+  struct find_one_section_data fosd;
+
+  fosd.name = name;
+  fosd.offset = offset;
+  fosd.length = length;
+  fosd.found = 0;
+
+  *errmsg = objfile_find_sections (objfile, find_one_section,
+				   (void *) &fosd, err);
+  if (*errmsg != NULL)
+    return 0;
+  if (!fosd.found)
+    return 0;
+  return 1;
+}
+
+/* Fetch attributes.  */
+
+objfile_attributes *
+objfile_fetch_attributes (objfile_read *objfile, const char **errmsg,
+			  int *err)
+{
+  void *data;
+  objfile_attributes *ret;
+
+  data = objfile->functions->fetch_attributes (objfile, errmsg, err);
+  if (data == NULL)
+    return NULL;
+  ret = XNEW (objfile_attributes);
+  ret->functions = objfile->functions;
+  ret->data = data;
+  return ret;
+}
+
+/* Release an objfile_read.  */
+
+void
+objfile_release_read (objfile_read *objfile)
+{
+  objfile->functions->release_read (objfile->data);
+  XDELETE (objfile);
+}
+
+/* Compare attributes.  */
+
+const char *
+objfile_attributes_compare (objfile_attributes *attrs1,
+			    objfile_attributes *attrs2,
+			    int *err)
+{
+  if (attrs1->functions != attrs2->functions)
+    {
+      *err = 0;
+      return "different object file format";
+    }
+  return attrs1->functions->attributes_compare (attrs1->data, attrs2->data,
+						err);
+}
+
+/* Release an attributes structure.  */
+
+void
+objfile_release_attributes (objfile_attributes *attrs)
+{
+  attrs->functions->release_attributes (attrs->data);
+  XDELETE (attrs);
+}
+
+/* Start creating an object file.  */
+
+objfile_write *
+objfile_start_write (objfile_attributes *attrs, const char *segment_name,
+		     const char **errmsg, int *err)
+{
+  void *data;
+  objfile_write *ret;
+
+  data = attrs->functions->start_write (attrs->data, errmsg, err);
+  if (data == NULL)
+    return NULL;
+  ret = XNEW (objfile_write);
+  ret->functions = attrs->functions;
+  ret->segment_name = xstrdup (segment_name);
+  ret->sections = NULL;
+  ret->last_section = NULL;
+  ret->data = data;
+  return ret;
+}
+
+/* Start creating a section.  */
+
+objfile_write_section *
+objfile_write_create_section (objfile_write *objfile, const char *name,
+			      unsigned int align,
+			      const char **errmsg ATTRIBUTE_UNUSED,
+			      int *err ATTRIBUTE_UNUSED)
+{
+  objfile_write_section *ret;
+
+  ret = XNEW (objfile_write_section);
+  ret->next = NULL;
+  ret->name = xstrdup (name);
+  ret->align = align;
+  ret->buffers = NULL;
+  ret->last_buffer = NULL;
+
+  if (objfile->last_section == NULL)
+    {
+      objfile->sections = ret;
+      objfile->last_section = ret;
+    }
+  else
+    {
+      objfile->last_section->next = ret;
+      objfile->last_section = ret;
+    }
+
+  return ret;
+}
+
+/* Add data to a section.  */
+
+const char *
+objfile_write_add_data (objfile_write *objfile ATTRIBUTE_UNUSED,
+			objfile_write_section *section, const void *buffer,
+			size_t size, int copy,
+			int *err ATTRIBUTE_UNUSED)
+{
+  struct objfile_write_section_buffer *wsb;
+
+  wsb = XNEW (struct objfile_write_section_buffer);
+  wsb->next = NULL;
+  wsb->size = size;
+
+  if (!copy)
+    {
+      wsb->buffer = buffer;
+      wsb->free_buffer = NULL;
+    }
+  else
+    {
+      wsb->free_buffer = (void *) XNEWVEC (char, size);
+      memcpy (wsb->free_buffer, buffer, size);
+      wsb->buffer = wsb->free_buffer;
+    }
+
+  if (section->last_buffer == NULL)
+    {
+      section->buffers = wsb;
+      section->last_buffer = wsb;
+    }
+  else
+    {
+      section->last_buffer->next = wsb;
+      section->last_buffer = wsb;
+    }
+
+  return NULL;
+}
+
+/* Write the complete object file.  */
+
+const char *
+objfile_write_to_file (objfile_write *objfile, int descriptor, int *err)
+{
+  return objfile->functions->write_to_file (objfile, descriptor, err);
+}
+
+/* Release an objfile_write.  */
+
+void
+objfile_release_write (objfile_write *objfile)
+{
+  objfile_write_section *section;
+
+  free (objfile->segment_name);
+
+  section = objfile->sections;
+  while (section != NULL)
+    {
+      struct objfile_write_section_buffer *buffer;
+      objfile_write_section *next_section;
+
+      buffer = section->buffers;
+      while (buffer != NULL)
+	{
+	  struct objfile_write_section_buffer *next_buffer;
+
+	  if (buffer->free_buffer != NULL)
+	    XDELETEVEC (buffer->free_buffer);
+	  next_buffer = buffer->next;
+	  XDELETE (buffer);
+	  buffer = next_buffer;
+	}
+
+      next_section = section->next;
+      free (section->name);
+      XDELETE (section);
+      section = next_section;
+    }
+
+  objfile->functions->release_write (objfile->data);
+  XDELETE (objfile);
+}
Index: libiberty/Makefile.in
===================================================================
--- libiberty/Makefile.in	(revision 166002)
+++ libiberty/Makefile.in	(working copy)
@@ -138,7 +138,9 @@ CFILES = alloca.c argv.c asprintf.c atex
 	make-relative-prefix.c						\
 	make-temp-file.c md5.c memchr.c memcmp.c memcpy.c memmem.c	\
 	 memmove.c mempcpy.c memset.c mkstemps.c			\
-	objalloc.c obstack.c						\
+	objalloc.c							\
+	 objfile.c objfile-coff.c objfile-elf.c objfile-mach-o.c	\
+	 obstack.c							\
 	partition.c pexecute.c						\
 	 pex-common.c pex-djgpp.c pex-msdos.c pex-one.c			\
 	 pex-unix.c pex-win32.c						\
@@ -172,7 +174,10 @@ REQUIRED_OFILES =							\
 	./getruntime.$(objext) ./hashtab.$(objext) ./hex.$(objext)	\
 	./lbasename.$(objext) ./lrealpath.$(objext)			\
 	./make-relative-prefix.$(objext) ./make-temp-file.$(objext)	\
-	./objalloc.$(objext) ./obstack.$(objext)			\
+	./objalloc.$(objext)						\
+	./objfile.$(objext) ./objfile-coff.$(objext)			\
+	./objfile-elf.$(objext)	./objfile-mach-o.$(objext)		\
+	./obstack.$(objext)						\
 	./partition.$(objext) ./pexecute.$(objext) ./physmem.$(objext)	\
 	./pex-common.$(objext) ./pex-one.$(objext)			\
 	./@pexecute@.$(objext)						\
@@ -833,6 +838,38 @@ $(CONFIGURED_OFILES): stamp-picdir
 	else true; fi
 	$(COMPILE.c) $(srcdir)/objalloc.c $(OUTPUT_OPTION)
 
+./objfile-coff.$(objext): $(srcdir)/objfile-coff.c config.h $(INCDIR)/ansidecl.h \
+	$(INCDIR)/libiberty.h $(srcdir)/objfile-common.h \
+	$(INCDIR)/objfile.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/objfile-coff.c -o pic/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/objfile-coff.c $(OUTPUT_OPTION)
+
+./objfile-elf.$(objext): $(srcdir)/objfile-elf.c config.h $(INCDIR)/ansidecl.h \
+	$(INCDIR)/libiberty.h $(srcdir)/objfile-common.h \
+	$(INCDIR)/objfile.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/objfile-elf.c -o pic/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/objfile-elf.c $(OUTPUT_OPTION)
+
+./objfile-mach-o.$(objext): $(srcdir)/objfile-mach-o.c config.h \
+	$(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
+	$(srcdir)/objfile-common.h $(INCDIR)/objfile.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/objfile-mach-o.c -o pic/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/objfile-mach-o.c $(OUTPUT_OPTION)
+
+./objfile.$(objext): $(srcdir)/objfile.c config.h $(INCDIR)/ansidecl.h \
+	$(INCDIR)/libiberty.h $(srcdir)/objfile-common.h \
+	$(INCDIR)/objfile.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/objfile.c -o pic/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/objfile.c $(OUTPUT_OPTION)
+
 ./obstack.$(objext): $(srcdir)/obstack.c config.h $(INCDIR)/obstack.h
 	if [ x"$(PICFLAG)" != x ]; then \
 	  $(COMPILE.c) $(PICFLAG) $(srcdir)/obstack.c -o pic/$@; \
Index: libiberty/objfile-elf.c
===================================================================
--- libiberty/objfile-elf.c	(revision 0)
+++ libiberty/objfile-elf.c	(revision 0)
@@ -0,0 +1,909 @@
+/* objfile-elf.c -- routines to manipulate ELF object files.
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+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, 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, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "libiberty.h"
+#include "objfile.h"
+
+#include <errno.h>
+#include <stddef.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "objfile-common.h"
+
+/* ELF structures and constants.  */
+
+/* 32-bit ELF file header.  */
+
+typedef struct {
+  unsigned char	e_ident[16];		/* ELF "magic number" */
+  unsigned char	e_type[2];		/* Identifies object file type */
+  unsigned char	e_machine[2];		/* Specifies required architecture */
+  unsigned char	e_version[4];		/* Identifies object file version */
+  unsigned char	e_entry[4];		/* Entry point virtual address */
+  unsigned char	e_phoff[4];		/* Program header table file offset */
+  unsigned char	e_shoff[4];		/* Section header table file offset */
+  unsigned char	e_flags[4];		/* Processor-specific flags */
+  unsigned char	e_ehsize[2];		/* ELF header size in bytes */
+  unsigned char	e_phentsize[2];		/* Program header table entry size */
+  unsigned char	e_phnum[2];		/* Program header table entry count */
+  unsigned char	e_shentsize[2];		/* Section header table entry size */
+  unsigned char	e_shnum[2];		/* Section header table entry count */
+  unsigned char	e_shstrndx[2];		/* Section header string table index */
+} Elf32_External_Ehdr;
+
+/* 64-bit ELF file header.  */
+
+typedef struct {
+  unsigned char	e_ident[16];		/* ELF "magic number" */
+  unsigned char	e_type[2];		/* Identifies object file type */
+  unsigned char	e_machine[2];		/* Specifies required architecture */
+  unsigned char	e_version[4];		/* Identifies object file version */
+  unsigned char	e_entry[8];		/* Entry point virtual address */
+  unsigned char	e_phoff[8];		/* Program header table file offset */
+  unsigned char	e_shoff[8];		/* Section header table file offset */
+  unsigned char	e_flags[4];		/* Processor-specific flags */
+  unsigned char	e_ehsize[2];		/* ELF header size in bytes */
+  unsigned char	e_phentsize[2];		/* Program header table entry size */
+  unsigned char	e_phnum[2];		/* Program header table entry count */
+  unsigned char	e_shentsize[2];		/* Section header table entry size */
+  unsigned char	e_shnum[2];		/* Section header table entry count */
+  unsigned char	e_shstrndx[2];		/* Section header string table index */
+} Elf64_External_Ehdr;
+
+/* Indexes and values in e_ident field of Ehdr.  */
+
+#define EI_MAG0		0	/* File identification byte 0 index */
+#define ELFMAG0		   0x7F	/* Magic number byte 0 */
+
+#define EI_MAG1		1	/* File identification byte 1 index */
+#define ELFMAG1		    'E'	/* Magic number byte 1 */
+
+#define EI_MAG2		2	/* File identification byte 2 index */
+#define ELFMAG2		    'L'	/* Magic number byte 2 */
+
+#define EI_MAG3		3	/* File identification byte 3 index */
+#define ELFMAG3		    'F'	/* Magic number byte 3 */
+
+#define EI_CLASS	4	/* File class */
+#define ELFCLASSNONE	      0	/* Invalid class */
+#define ELFCLASS32	      1	/* 32-bit objects */
+#define ELFCLASS64	      2	/* 64-bit objects */
+
+#define EI_DATA		5	/* Data encoding */
+#define ELFDATANONE	      0	/* Invalid data encoding */
+#define ELFDATA2LSB	      1	/* 2's complement, little endian */
+#define ELFDATA2MSB	      2	/* 2's complement, big endian */
+
+#define EI_VERSION	6	/* File version */
+#define EV_CURRENT	1		/* Current version */
+
+#define EI_OSABI	7	/* Operating System/ABI indication */
+
+/* Values for e_type field of Ehdr.  */
+
+#define ET_REL		1	/* Relocatable file */
+
+/* Special section index values.  */
+
+#define SHN_LORESERVE	0xFF00		/* Begin range of reserved indices */
+#define SHN_XINDEX	0xFFFF		/* Section index is held elsewhere */
+
+/* 32-bit ELF program header.  */
+
+typedef struct {
+  unsigned char	p_type[4];		/* Identifies program segment type */
+  unsigned char	p_offset[4];		/* Segment file offset */
+  unsigned char	p_vaddr[4];		/* Segment virtual address */
+  unsigned char	p_paddr[4];		/* Segment physical address */
+  unsigned char	p_filesz[4];		/* Segment size in file */
+  unsigned char	p_memsz[4];		/* Segment size in memory */
+  unsigned char	p_flags[4];		/* Segment flags */
+  unsigned char	p_align[4];		/* Segment alignment, file & memory */
+} Elf32_External_Phdr;
+
+/* 64-bit ELF program header.  */
+
+typedef struct {
+  unsigned char	p_type[4];		/* Identifies program segment type */
+  unsigned char	p_flags[4];		/* Segment flags */
+  unsigned char	p_offset[8];		/* Segment file offset */
+  unsigned char	p_vaddr[8];		/* Segment virtual address */
+  unsigned char	p_paddr[8];		/* Segment physical address */
+  unsigned char	p_filesz[8];		/* Segment size in file */
+  unsigned char	p_memsz[8];		/* Segment size in memory */
+  unsigned char	p_align[8];		/* Segment alignment, file & memory */
+} Elf64_External_Phdr;
+
+/* 32-bit ELF section header */
+
+typedef struct {
+  unsigned char	sh_name[4];		/* Section name, index in string tbl */
+  unsigned char	sh_type[4];		/* Type of section */
+  unsigned char	sh_flags[4];		/* Miscellaneous section attributes */
+  unsigned char	sh_addr[4];		/* Section virtual addr at execution */
+  unsigned char	sh_offset[4];		/* Section file offset */
+  unsigned char	sh_size[4];		/* Size of section in bytes */
+  unsigned char	sh_link[4];		/* Index of another section */
+  unsigned char	sh_info[4];		/* Additional section information */
+  unsigned char	sh_addralign[4];	/* Section alignment */
+  unsigned char	sh_entsize[4];		/* Entry size if section holds table */
+} Elf32_External_Shdr;
+
+/* 64-bit ELF section header.  */
+
+typedef struct {
+  unsigned char	sh_name[4];		/* Section name, index in string tbl */
+  unsigned char	sh_type[4];		/* Type of section */
+  unsigned char	sh_flags[8];		/* Miscellaneous section attributes */
+  unsigned char	sh_addr[8];		/* Section virtual addr at execution */
+  unsigned char	sh_offset[8];		/* Section file offset */
+  unsigned char	sh_size[8];		/* Size of section in bytes */
+  unsigned char	sh_link[4];		/* Index of another section */
+  unsigned char	sh_info[4];		/* Additional section information */
+  unsigned char	sh_addralign[8];	/* Section alignment */
+  unsigned char	sh_entsize[8];		/* Entry size if section holds table */
+} Elf64_External_Shdr;
+
+/* Values for sh_type field.  */
+
+#define SHT_PROGBITS	1		/* Program data */
+#define SHT_STRTAB	3		/* A string table */
+
+/* Functions to fetch and store different ELF types, depending on the
+   endianness and size.  */
+
+struct elf_type_functions
+{
+  unsigned short (*fetch_Elf_Half) (const unsigned char *);
+  unsigned int (*fetch_Elf_Word) (const unsigned char *);
+  ulong_type (*fetch_Elf_Addr) (const unsigned char *);
+  void (*set_Elf_Half) (unsigned char *, unsigned short);
+  void (*set_Elf_Word) (unsigned char *, unsigned int);
+  void (*set_Elf_Addr) (unsigned char *, ulong_type);
+};
+
+static const struct elf_type_functions elf_big_32_functions =
+{
+  objfile_fetch_big_16,
+  objfile_fetch_big_32,
+  objfile_fetch_big_32_ulong,
+  objfile_set_big_16,
+  objfile_set_big_32,
+  objfile_set_big_32_ulong
+};
+
+static const struct elf_type_functions elf_little_32_functions =
+{
+  objfile_fetch_little_16,
+  objfile_fetch_little_32,
+  objfile_fetch_little_32_ulong,
+  objfile_set_little_16,
+  objfile_set_little_32,
+  objfile_set_little_32_ulong
+};
+
+#ifdef UNSIGNED_64BIT_TYPE
+
+static const struct elf_type_functions elf_big_64_functions =
+{
+  objfile_fetch_big_16,
+  objfile_fetch_big_32,
+  objfile_fetch_big_64,
+  objfile_set_big_16,
+  objfile_set_big_32,
+  objfile_set_big_64
+};
+
+static const struct elf_type_functions elf_little_64_functions =
+{
+  objfile_fetch_little_16,
+  objfile_fetch_little_32,
+  objfile_fetch_little_64,
+  objfile_set_little_16,
+  objfile_set_little_32,
+  objfile_set_little_64
+};
+
+#endif
+
+/* Hideous macro to fetch the value of a field from an external ELF
+   struct of some sort.  TYPEFUNCS is the set of type functions.
+   BUFFER points to the external data.  STRUCTTYPE is the appropriate
+   struct type.  FIELD is a field within the struct.  TYPE is the type
+   of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr.  */
+
+#define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \
+  ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD)))
+
+/* Even more hideous macro to fetch the value of FIELD from BUFFER.
+   SIZE is 32 or 64.  STRUCTTYPE is the name of the struct from
+   elf/external.h: Ehdr, Shdr, etc.  FIELD is the name of a field in
+   the struct.  TYPE is the type of the field in the struct: Elf_Half,
+   Elf_Word, or Elf_Addr.  */
+
+#define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER,	\
+			      FIELD, TYPE)				\
+  ELF_FETCH_STRUCT_FIELD (TYPEFUNCS,					\
+			  Elf ## SIZE ## _External_ ## STRUCTTYPE,	\
+			  FIELD, BUFFER, TYPE)
+
+/* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value.  */
+
+#define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER,		\
+			FIELD, TYPE)					\
+  ((CLASS) == ELFCLASS32						\
+    ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,	\
+			     TYPE)					\
+    : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,	\
+			     TYPE))
+
+/* Hideous macro to set the value of a field in an external ELF
+   structure to VAL.  TYPEFUNCS is the set of type functions.  BUFFER
+   points to the external data.  STRUCTTYPE is the appropriate
+   structure type.  FIELD is a field within the struct.  TYPE is the
+   type of the field in the struct: Elf_Half, Elf_Word, or
+   Elf_Addr.  */
+
+#define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \
+  (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL))
+
+/* Even more hideous macro to set the value of FIELD in BUFFER to VAL.
+   SIZE is 32 or 64.  STRUCTTYPE is the name of the struct from
+   elf/external.h: Ehdr, Shdr, etc.  FIELD is the name of a field in
+   the struct.  TYPE is the type of the field in the struct: Elf_Half,
+   Elf_Word, or Elf_Addr.  */
+
+#define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \
+			    TYPE, VAL)					\
+  ELF_SET_STRUCT_FIELD (TYPEFUNCS,					\
+			Elf ## SIZE ## _External_ ## STRUCTTYPE,	\
+			FIELD, BUFFER, TYPE, VAL)
+
+/* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value.  */
+
+#define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD,	\
+		      TYPE, VAL)					\
+  ((CLASS) == ELFCLASS32						\
+    ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,	\
+			   TYPE, VAL)					\
+    : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,	\
+			   TYPE, VAL))
+
+/* Private data for an objfile_read.  */
+
+struct objfile_elf_read
+{
+  /* Type functions.  */
+  const struct elf_type_functions* type_functions;
+  /* Elf data.  */
+  unsigned char ei_data;
+  /* Elf class.  */
+  unsigned char ei_class;
+  /* ELF OS ABI.  */
+  unsigned char ei_osabi;
+  /* Elf machine number.  */
+  unsigned short machine;
+  /* Processor specific flags.  */
+  unsigned int flags;
+  /* File offset of section headers.  */
+  ulong_type shoff;
+  /* Number of sections.  */
+  unsigned int shnum;
+  /* Index of string table section header.  */
+  unsigned int shstrndx;
+};
+
+/* Private data for an objfile_attributes.  */
+
+struct objfile_elf_attributes
+{
+  /* Type functions.  */
+  const struct elf_type_functions* type_functions;
+  /* Elf data.  */
+  unsigned char ei_data;
+  /* Elf class.  */
+  unsigned char ei_class;
+  /* ELF OS ABI.  */
+  unsigned char ei_osabi;
+  /* Elf machine number.  */
+  unsigned short machine;
+  /* Processor specific flags.  */
+  unsigned int flags;
+};
+
+/* See if we have an ELF file.  */
+
+static void *
+objfile_elf_match (unsigned char header[OBJFILE_MATCH_HEADER_LEN],
+		   int descriptor, off_t offset,
+		   const char *segment_name ATTRIBUTE_UNUSED,
+		   const char **errmsg, int *err)
+{
+  unsigned char ei_data;
+  unsigned char ei_class;
+  const struct elf_type_functions *type_functions;
+  unsigned char ehdr[sizeof (Elf64_External_Ehdr)];
+  struct objfile_elf_read *eor;
+
+  if (header[EI_MAG0] != ELFMAG0
+      || header[EI_MAG1] != ELFMAG1
+      || header[EI_MAG2] != ELFMAG2
+      || header[EI_MAG3] != ELFMAG3
+      || header[EI_VERSION] != EV_CURRENT)
+    {
+      *errmsg = NULL;
+      *err = 0;
+      return NULL;
+    }
+
+  ei_data = header[EI_DATA];
+  if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB)
+    {
+      *errmsg = "unknown ELF endianness";
+      *err = 0;
+      return NULL;
+    }
+
+  ei_class = header[EI_CLASS];
+  switch (ei_class)
+    {
+    case ELFCLASS32:
+      type_functions = (ei_data == ELFDATA2LSB
+			? &elf_little_32_functions
+			: &elf_big_32_functions);
+      break;
+
+    case ELFCLASS64:
+#ifndef UNSIGNED_64BIT_TYPE
+      *errmsg = "64-bit ELF objects not supported";
+      *err = 0;
+      return NULL;
+#else
+      type_functions = (ei_data == ELFDATA2LSB
+			? &elf_little_64_functions
+			: &elf_big_64_functions);
+      break;
+#endif
+
+    default:
+      *errmsg = "unrecognized ELF size";
+      *err = 0;
+      return NULL;
+    }
+
+  if (!objfile_internal_read (descriptor, offset, ehdr, sizeof ehdr,
+			      errmsg, err))
+    return NULL;
+
+  eor = XNEW (struct objfile_elf_read);
+  eor->type_functions = type_functions;
+  eor->ei_data = ei_data;
+  eor->ei_class = ei_class;
+  eor->ei_osabi = header[EI_OSABI];
+  eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
+				  e_machine, Elf_Half);
+  eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
+				e_flags, Elf_Word);
+  eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
+				e_shoff, Elf_Addr);
+  eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
+				e_shnum, Elf_Half);
+  eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
+				   e_shstrndx, Elf_Half);
+
+  if ((eor->shnum == 0 || eor->shstrndx == SHN_XINDEX)
+      && eor->shoff != 0)
+    {
+      unsigned char shdr[sizeof (Elf64_External_Shdr)];
+
+      /* Object file has more than 0xffff sections.  */
+
+      if (!objfile_internal_read (descriptor, offset + eor->shoff, shdr,
+				  (ei_class == ELFCLASS32
+				   ? sizeof (Elf32_External_Shdr)
+				   : sizeof (Elf64_External_Shdr)),
+				  errmsg, err))
+	{
+	  XDELETE (eor);
+	  return NULL;
+	}
+
+      if (eor->shnum == 0)
+	eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				      shdr, sh_size, Elf_Addr);
+
+      if (eor->shstrndx == SHN_XINDEX)
+	{
+	  eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+					   shdr, sh_link, Elf_Word);
+
+	  /* Versions of the GNU binutils between 2.12 and 2.18 did
+	     not handle objects with more than SHN_LORESERVE sections
+	     correctly.  All large section indexes were offset by
+	     0x100.  There is more information at
+	     http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .
+	     Fortunately these object files are easy to detect, as the
+	     GNU binutils always put the section header string table
+	     near the end of the list of sections.  Thus if the
+	     section header string table index is larger than the
+	     number of sections, then we know we have to subtract
+	     0x100 to get the real section index.  */
+	  if (eor->shstrndx >= eor->shnum
+	      && eor->shstrndx >= SHN_LORESERVE + 0x100)
+	    eor->shstrndx -= 0x100;
+	}
+    }
+
+  if (eor->shstrndx >= eor->shnum)
+    {
+      *errmsg = "invalid ELF shstrndx >= shnum";
+      *err = 0;
+      XDELETE (eor);
+      return NULL;
+    }
+
+  return (void *) eor;
+}
+
+/* Find all sections in an ELF file.  */
+
+static const char *
+objfile_elf_find_sections (objfile_read *objfile,
+			   int (*pfn) (void *, const char *, off_t offset,
+				       off_t length),
+			   void *data,
+			   int *err)
+{
+  struct objfile_elf_read *eor = (struct objfile_elf_read *) objfile->data;
+  const struct elf_type_functions *type_functions = eor->type_functions;
+  unsigned char ei_class = eor->ei_class;
+  size_t shdr_size;
+  unsigned int shnum;
+  unsigned char *shdrs;
+  const char *errmsg;
+  unsigned char *shstrhdr;
+  size_t name_size;
+  off_t shstroff;
+  unsigned char *names;
+  unsigned int i;
+
+  shdr_size = (ei_class == ELFCLASS32
+	       ? sizeof (Elf32_External_Shdr)
+	       : sizeof (Elf64_External_Shdr));
+
+  /* Read the section headers.  We skip section 0, which is not a
+     useful section.  */
+
+  shnum = eor->shnum;
+  shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
+
+  if (!objfile_internal_read (objfile->descriptor,
+			      objfile->offset + eor->shoff + shdr_size,
+			      shdrs,
+			      shdr_size * (shnum - 1),
+			      &errmsg, err))
+    {
+      XDELETEVEC (shdrs);
+      return errmsg;
+    }
+
+  /* Read the section names.  */
+
+  shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
+  name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+			       shstrhdr, sh_size, Elf_Addr);
+  shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+			      shstrhdr, sh_offset, Elf_Addr);
+  names = XNEWVEC (unsigned char, name_size);
+  if (!objfile_internal_read (objfile->descriptor,
+			      objfile->offset + shstroff,
+			      names, name_size, &errmsg, err))
+    {
+      XDELETEVEC (names);
+      XDELETEVEC (shdrs);
+      return errmsg;
+    }
+
+  for (i = 1; i < shnum; ++i)
+    {
+      unsigned char *shdr;
+      unsigned int sh_name;
+      const char *name;
+      off_t offset;
+      off_t length;
+
+      shdr = shdrs + (i - 1) * shdr_size;
+      sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				 shdr, sh_name, Elf_Word);
+      if (sh_name >= name_size)
+	{
+	  *err = 0;
+	  XDELETEVEC (names);
+	  XDELETEVEC (shdrs);
+	  return "ELF section name out of range";
+	}
+
+      name = (const char *) names + sh_name;
+      offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				shdr, sh_offset, Elf_Addr);
+      length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				shdr, sh_size, Elf_Addr);
+
+      if (!(*pfn) (data, name, offset, length))
+	break;
+    }
+
+  XDELETEVEC (names);
+  XDELETEVEC (shdrs);
+
+  return NULL;
+}
+
+/* Fetch the attributes for an objfile_read.  */
+
+static void *
+objfile_elf_fetch_attributes (objfile_read *objfile,
+			      const char **errmsg ATTRIBUTE_UNUSED,
+			      int *err ATTRIBUTE_UNUSED)
+{
+  struct objfile_elf_read *eor = (struct objfile_elf_read *) objfile->data;
+  struct objfile_elf_attributes *ret;
+
+  ret = XNEW (struct objfile_elf_attributes);
+  ret->type_functions = eor->type_functions;
+  ret->ei_data = eor->ei_data;
+  ret->ei_class = eor->ei_class;
+  ret->ei_osabi = eor->ei_osabi;
+  ret->machine = eor->machine;
+  ret->flags = eor->flags;
+  return ret;
+}
+
+/* Release the privata data for an objfile_read.  */
+
+static void
+objfile_elf_release_read (void *data)
+{
+  XDELETE (data);
+}
+
+/* Compare two attributes structures.  */
+
+static const char *
+objfile_elf_attributes_compare (void *data1, void *data2, int *err)
+{
+  struct objfile_elf_attributes *attrs1 =
+    (struct objfile_elf_attributes *) data1;
+  struct objfile_elf_attributes *attrs2 =
+    (struct objfile_elf_attributes *) data2;
+
+  if (attrs1->ei_data != attrs2->ei_data
+      || attrs1->ei_class != attrs2->ei_class
+      || attrs1->machine != attrs2->machine)
+    {
+      *err = 0;
+      return "ELF object format mismatch";
+    }
+  return NULL;
+}
+
+/* Release the private data for an attributes structure.  */
+
+static void
+objfile_elf_release_attributes (void *data)
+{
+  XDELETE (data);
+}
+
+/* Prepare to write out a file.  */
+
+static void *
+objfile_elf_start_write (void *attributes_data,
+			 const char **errmsg ATTRIBUTE_UNUSED,
+			 int *err ATTRIBUTE_UNUSED)
+{
+  struct objfile_elf_attributes *attrs =
+    (struct objfile_elf_attributes *) attributes_data;
+  struct objfile_elf_attributes *ret;
+
+  /* We're just going to record the attributes, but we need to make a
+     copy because the user may delete them.  */
+  ret = XNEW (struct objfile_elf_attributes);
+  *ret = *attrs;
+  return ret;
+}
+
+/* Write out an ELF ehdr.  */
+
+static int
+objfile_elf_write_ehdr (objfile_write *objfile, int descriptor,
+			const char **errmsg, int *err)
+{
+  struct objfile_elf_attributes *attrs =
+    (struct objfile_elf_attributes *) objfile->data;
+  const struct elf_type_functions* fns;
+  unsigned char cl;
+  size_t ehdr_size;
+  unsigned char buf[sizeof (Elf64_External_Ehdr)];
+  objfile_write_section *section;
+  unsigned int shnum;
+
+  fns = attrs->type_functions;
+  cl = attrs->ei_class;
+
+  shnum = 0;
+  for (section = objfile->sections; section != NULL; section = section->next)
+    ++shnum;
+  if (shnum > 0)
+    {
+      /* Add a section header for the dummy section and one for
+	 .shstrtab.  */
+      shnum += 2;
+    }
+
+  ehdr_size = (cl == ELFCLASS32
+	       ? sizeof (Elf32_External_Ehdr)
+	       : sizeof (Elf64_External_Ehdr));
+  memset (buf, 0, ehdr_size);
+
+  buf[EI_MAG0] = ELFMAG0;
+  buf[EI_MAG1] = ELFMAG1;
+  buf[EI_MAG2] = ELFMAG2;
+  buf[EI_MAG3] = ELFMAG3;
+  buf[EI_CLASS] = cl;
+  buf[EI_DATA] = attrs->ei_data;
+  buf[EI_VERSION] = EV_CURRENT;
+  buf[EI_OSABI] = attrs->ei_osabi;
+
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_type, Elf_Half, ET_REL);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_machine, Elf_Half, attrs->machine);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_version, Elf_Word, EV_CURRENT);
+  /* e_entry left as zero.  */
+  /* e_phoff left as zero.  */
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shoff, Elf_Addr, ehdr_size);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_flags, Elf_Word, attrs->flags);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_ehsize, Elf_Half, ehdr_size);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_phentsize, Elf_Half,
+		 (cl == ELFCLASS32
+		  ? sizeof (Elf32_External_Phdr)
+		  : sizeof (Elf64_External_Phdr)));
+  /* e_phnum left as zero.  */
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shentsize, Elf_Half,
+		 (cl == ELFCLASS32
+		  ? sizeof (Elf32_External_Shdr)
+		  : sizeof (Elf64_External_Shdr)));
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half, shnum);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half,
+		 shnum == 0 ? 0 : shnum - 1);
+
+  return objfile_internal_write (descriptor, 0, buf, ehdr_size, errmsg, err);
+}
+
+/* Write out an ELF shdr.  */
+
+static int
+objfile_elf_write_shdr (objfile_write *objfile, int descriptor, off_t offset,
+			unsigned int sh_name, unsigned int sh_type,
+			unsigned int sh_flags, unsigned int sh_offset,
+			unsigned int sh_size, unsigned int sh_addralign,
+			const char **errmsg, int *err)
+{
+  struct objfile_elf_attributes *attrs =
+    (struct objfile_elf_attributes *) objfile->data;
+  const struct elf_type_functions* fns;
+  unsigned char cl;
+  size_t shdr_size;
+  unsigned char buf[sizeof (Elf64_External_Shdr)];
+
+  fns = attrs->type_functions;
+  cl = attrs->ei_class;
+
+  shdr_size = (cl == ELFCLASS32
+	       ? sizeof (Elf32_External_Shdr)
+	       : sizeof (Elf64_External_Shdr));
+  memset (buf, 0, shdr_size);
+
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
+  /* sh_link left as zero.  */
+  /* sh_info left as zero.  */
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
+  /* sh_entsize left as zero.  */
+
+  return objfile_internal_write (descriptor, offset, buf, shdr_size,
+				 errmsg, err);
+}
+
+/* Write out a complete ELF file.
+   Ehdr
+   initial dummy Shdr
+   user-created Shdrs
+   .shstrtab Shdr
+   user-created section data
+   .shstrtab data  */
+
+static const char *
+objfile_elf_write_to_file (objfile_write *objfile, int descriptor, int *err)
+{
+  struct objfile_elf_attributes *attrs =
+    (struct objfile_elf_attributes *) objfile->data;
+  unsigned char cl;
+  size_t ehdr_size;
+  size_t shdr_size;
+  const char *errmsg;
+  objfile_write_section *section;
+  unsigned int shnum;
+  size_t shdr_offset;
+  size_t sh_offset;
+  size_t sh_name;
+  unsigned char zero;
+
+  if (!objfile_elf_write_ehdr (objfile, descriptor, &errmsg, err))
+    return errmsg;
+
+  cl = attrs->ei_class;
+  if (cl == ELFCLASS32)
+    {
+      ehdr_size = sizeof (Elf32_External_Ehdr);
+      shdr_size = sizeof (Elf32_External_Shdr);
+    }
+  else
+    {
+      ehdr_size = sizeof (Elf64_External_Ehdr);
+      shdr_size = sizeof (Elf64_External_Shdr);
+    }
+
+  shnum = 0;
+  for (section = objfile->sections; section != NULL; section = section->next)
+    ++shnum;
+  if (shnum == 0)
+    return NULL;
+
+  /* Add initial dummy Shdr and .shstrtab.  */
+  shnum += 2;
+
+  shdr_offset = ehdr_size;
+  sh_offset = shdr_offset + shnum * shdr_size;
+
+  if (!objfile_elf_write_shdr (objfile, descriptor, shdr_offset,
+			       0, 0, 0, 0, 0, 0, &errmsg, err))
+    return errmsg;
+
+  shdr_offset += shdr_size;
+
+  sh_name = 1;
+  for (section = objfile->sections; section != NULL; section = section->next)
+    {
+      size_t mask;
+      size_t new_sh_offset;
+      size_t sh_size;
+      struct objfile_write_section_buffer *buffer;
+
+      mask = (1U << section->align) - 1;
+      new_sh_offset = sh_offset + mask;
+      new_sh_offset &= ~ mask;
+      while (new_sh_offset > sh_offset)
+	{
+	  unsigned char zeroes[16];
+	  size_t write;
+
+	  memset (zeroes, 0, sizeof zeroes);
+	  write = new_sh_offset - sh_offset;
+	  if (write > sizeof zeroes)
+	    write = sizeof zeroes;
+	  if (!objfile_internal_write (descriptor, sh_offset, zeroes,
+				       write, &errmsg, err))
+	    return errmsg;
+	  sh_offset += write;
+	}
+
+      sh_size = 0;
+      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
+	{
+	  if (!objfile_internal_write (descriptor, sh_offset + sh_size,
+				       (const unsigned char *) buffer->buffer,
+				       buffer->size, &errmsg, err))
+	    return errmsg;
+	  sh_size += buffer->size;
+	}
+
+      if (!objfile_elf_write_shdr (objfile, descriptor, shdr_offset,
+				   sh_name, SHT_PROGBITS, 0, sh_offset,
+				   sh_size, 1U << section->align,
+				   &errmsg, err))
+	return errmsg;
+
+      shdr_offset += shdr_size;
+      sh_name += strlen (section->name) + 1;
+      sh_offset += sh_size;
+    }
+
+  if (!objfile_elf_write_shdr (objfile, descriptor, shdr_offset,
+			       sh_name, SHT_STRTAB, 0, sh_offset,
+			       sh_name + strlen (".shstrtab") + 1,
+			       1, &errmsg, err))
+    return errmsg;
+
+  /* .shstrtab has a leading zero byte.  */
+  zero = 0;
+  if (!objfile_internal_write (descriptor, sh_offset, &zero, 1, &errmsg, err))
+    return errmsg;
+  ++sh_offset;
+
+  for (section = objfile->sections; section != NULL; section = section->next)
+    {
+      size_t len;
+
+      len = strlen (section->name) + 1;
+      if (!objfile_internal_write (descriptor, sh_offset,
+				   (const unsigned char *) section->name,
+				   len, &errmsg, err))
+	return errmsg;
+      sh_offset += len;
+    }
+
+  if (!objfile_internal_write (descriptor, sh_offset,
+			       (const unsigned char *) ".shstrtab",
+			       strlen (".shstrtab") + 1, &errmsg, err))
+    return errmsg;
+
+  return NULL;
+}
+
+/* Release the private data for an objfile_write structure.  */
+
+static void
+objfile_elf_release_write (void *data)
+{
+  XDELETE (data);
+}
+
+/* The ELF functions.  */
+
+const struct objfile_functions objfile_elf_functions =
+{
+  objfile_elf_match,
+  objfile_elf_find_sections,
+  objfile_elf_fetch_attributes,
+  objfile_elf_release_read,
+  objfile_elf_attributes_compare,
+  objfile_elf_release_attributes,
+  objfile_elf_start_write,
+  objfile_elf_write_to_file,
+  objfile_elf_release_write
+};
Index: libiberty/objfile-coff.c
===================================================================
--- libiberty/objfile-coff.c	(revision 0)
+++ libiberty/objfile-coff.c	(revision 0)
@@ -0,0 +1,661 @@
+/* objfile-coff.c -- routines to manipulate COFF object files.
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+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, 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, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "libiberty.h"
+#include "objfile.h"
+
+#include <errno.h>
+#include <stddef.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "objfile-common.h"
+
+/* COFF structures and constants.  */
+
+/* COFF file header.  */
+
+struct external_filehdr
+{
+  unsigned char f_magic[2];	/* magic number			*/
+  unsigned char f_nscns[2];	/* number of sections		*/
+  unsigned char f_timdat[4];	/* time & date stamp		*/
+  unsigned char f_symptr[4];	/* file pointer to symtab	*/
+  unsigned char f_nsyms[4];	/* number of symtab entries	*/
+  unsigned char f_opthdr[2];	/* sizeof(optional hdr)		*/
+  unsigned char f_flags[2];	/* flags			*/
+};
+
+/* Bits for filehdr f_flags field.  */
+
+#define F_EXEC			(0x0002)
+#define IMAGE_FILE_SYSTEM	(0x1000)
+#define IMAGE_FILE_DLL		(0x2000)
+
+/* COFF section header.  */
+
+struct external_scnhdr
+{
+  unsigned char s_name[8];	/* section name				*/
+  unsigned char s_paddr[4];	/* physical address, aliased s_nlib 	*/
+  unsigned char s_vaddr[4];	/* virtual address			*/
+  unsigned char s_size[4];	/* section size				*/
+  unsigned char s_scnptr[4];	/* file ptr to raw data for section 	*/
+  unsigned char s_relptr[4];	/* file ptr to relocation		*/
+  unsigned char s_lnnoptr[4];	/* file ptr to line numbers		*/
+  unsigned char s_nreloc[2];	/* number of relocation entries		*/
+  unsigned char s_nlnno[2];	/* number of line number entries	*/
+  unsigned char s_flags[4];	/* flags				*/
+};
+
+/* The length of the s_name field in struct external_scnhdr.  */
+
+#define SCNNMLEN (8)
+
+/* Bits for scnhdr s_flags field.  This includes some bits defined
+   only for PE.  This may need to be moved into coff_magic.  */
+
+#define STYP_DATA			(1 << 6)
+#define IMAGE_SCN_ALIGN_1BYTES		(1 << 20)
+#define IMAGE_SCN_MEM_DISCARDABLE	(1 << 25)
+#define IMAGE_SCN_MEM_SHARED		(1 << 28)
+#define IMAGE_SCN_MEM_READ		(1 << 30)
+
+/* COFF symbol table entry.  */
+
+#define E_SYMNMLEN	8	/* # characters in a symbol name	*/
+
+struct external_syment 
+{
+  union
+  {
+    unsigned char e_name[E_SYMNMLEN];
+
+    struct
+    {
+      unsigned char e_zeroes[4];
+      unsigned char e_offset[4];
+    } e;
+  } e;
+
+  unsigned char e_value[4];
+  unsigned char e_scnum[2];
+  unsigned char e_type[2];
+  unsigned char e_sclass[1];
+  unsigned char e_numaux[1];
+};
+
+/* Private data for an objfile_read.  */
+
+struct objfile_coff_read
+{
+  /* Magic number.  */
+  unsigned short magic;
+  /* Whether the file is big-endian.  */
+  unsigned char is_big_endian;
+  /* Number of sections.  */
+  unsigned short nscns;
+  /* File offset of symbol table.  */
+  off_t symptr;
+  /* Number of symbol table entries.  */
+  unsigned int nsyms;
+  /* Flags.  */
+  unsigned short flags;
+  /* Offset of section headers in file.  */
+  off_t scnhdr_offset;
+};
+
+/* Private data for an objfile_attributes.  */
+
+struct objfile_coff_attributes
+{
+  /* Magic number.  */
+  unsigned short magic;
+  /* Whether the file is big-endian.  */
+  unsigned char is_big_endian;
+  /* Flags.  */
+  unsigned short flags;
+};
+
+/* There is no magic number which indicates a COFF file as opposed to
+   any other sort of file.  Instead, each COFF file starts with a
+   two-byte magic number which also indicates the type of the target.
+   This struct holds a magic number as well as characteristics of that
+   COFF format.  */
+
+struct coff_magic_struct
+{
+  /* Magic number.  */
+  unsigned short magic;
+  /* Whether this magic number is for a big-endian file.  */
+  unsigned char is_big_endian;
+  /* Flag bits, in the f_flags fields, which indicates that this file
+     is not a relocatable object file.  There is no flag which
+     specifically indicates a relocatable object file, it is only
+     implied by the absence of these flags.  */
+  unsigned short non_object_flags;
+};
+
+/* This is a list of the COFF magic numbers which we recognize, namely
+   the ones used on Windows.  More can be added as needed.  */
+
+static const struct coff_magic_struct coff_magic[] =
+{
+  /* i386.  */
+  { 0x14c, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL },
+  /* x86_64.  */
+  { 0x8664, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL }
+};
+
+/* See if we have a COFF file.  */
+
+static void *
+objfile_coff_match (unsigned char header[OBJFILE_MATCH_HEADER_LEN],
+		    int descriptor, off_t offset,
+		    const char *segment_name ATTRIBUTE_UNUSED,
+		    const char **errmsg, int *err)
+{
+  size_t c;
+  unsigned short magic_big;
+  unsigned short magic_little;
+  unsigned short magic;
+  size_t i;
+  int is_big_endian;
+  unsigned short (*fetch_16) (const unsigned char *);
+  unsigned int (*fetch_32) (const unsigned char *);
+  unsigned char hdrbuf[sizeof (struct external_filehdr)];
+  unsigned char *hdr;
+  unsigned short flags;
+  struct objfile_coff_read *ocr;
+
+  c = sizeof (coff_magic) / sizeof (coff_magic[0]);
+  magic_big = objfile_fetch_big_16 (header);
+  magic_little = objfile_fetch_little_16 (header);
+  for (i = 0; i < c; ++i)
+    {
+      if (coff_magic[i].is_big_endian
+	  ? coff_magic[i].magic == magic_big
+	  : coff_magic[i].magic == magic_little)
+	break;
+    }
+  if (i >= c)
+    {
+      *errmsg = NULL;
+      *err = 0;
+      return NULL;
+    }
+  is_big_endian = coff_magic[i].is_big_endian;
+  
+  magic = is_big_endian ? magic_big : magic_little;
+  fetch_16 = (is_big_endian
+	      ? objfile_fetch_big_16
+	      : objfile_fetch_little_16);
+  fetch_32 = (is_big_endian
+	      ? objfile_fetch_big_32
+	      : objfile_fetch_little_32);
+
+  if (!objfile_internal_read (descriptor, offset, hdrbuf, sizeof hdrbuf,
+			      errmsg, err))
+    return NULL;
+
+  hdr = &hdrbuf[0];
+
+  flags = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_flags));
+  if ((flags & coff_magic[i].non_object_flags) != 0)
+    {
+      *errmsg = "not relocatable object file";
+      *err = 0;
+      return NULL;
+    }
+
+  ocr = XNEW (struct objfile_coff_read);
+  ocr->magic = magic;
+  ocr->is_big_endian = is_big_endian;
+  ocr->nscns = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_nscns));
+  ocr->symptr = fetch_32 (hdrbuf
+			  + offsetof (struct external_filehdr, f_symptr));
+  ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr, f_nsyms));
+  ocr->flags = flags;
+  ocr->scnhdr_offset = (sizeof (struct external_filehdr)
+			+ fetch_16 (hdrbuf + offsetof (struct external_filehdr,
+						       f_opthdr)));
+
+  return (void *) ocr;
+}
+
+/* Read the string table in a COFF file.  */
+
+static char *
+objfile_coff_read_strtab (objfile_read *objfile, size_t *strtab_size,
+			  const char **errmsg, int *err)
+{
+  struct objfile_coff_read *ocr = (struct objfile_coff_read *) objfile->data;
+  off_t strtab_offset;
+  unsigned char strsizebuf[4];
+  size_t strsize;
+  char *strtab;
+
+  strtab_offset = ocr->symptr + ocr->nsyms * sizeof (struct external_syment);
+  if (!objfile_internal_read (objfile->descriptor, strtab_offset,
+			      strsizebuf, 4, errmsg, err))
+    return NULL;
+  strsize = (ocr->is_big_endian
+	     ? objfile_fetch_big_32 (strsizebuf)
+	     : objfile_fetch_little_32 (strsizebuf));
+  strtab = XNEWVEC (char, strsize);
+  if (!objfile_internal_read (objfile->descriptor, strtab_offset,
+			      (unsigned char *) strtab, strsize, errmsg, err))
+    {
+      XDELETEVEC (strtab);
+      return NULL;
+    }
+  *strtab_size = strsize;
+  return strtab;
+}
+
+/* Find all sections in a COFF file.  */
+
+static const char *
+objfile_coff_find_sections (objfile_read *objfile,
+			    int (*pfn) (void *, const char *, off_t offset,
+					off_t length),
+			    void *data,
+			    int *err)
+{
+  struct objfile_coff_read *ocr = (struct objfile_coff_read *) objfile->data;
+  size_t scnhdr_size;
+  unsigned char *scnbuf;
+  const char *errmsg;
+  unsigned int (*fetch_32) (const unsigned char *);
+  unsigned int nscns;
+  char *strtab;
+  size_t strtab_size;
+  unsigned int i;
+
+  scnhdr_size = sizeof (struct external_scnhdr);
+  scnbuf = XNEWVEC (unsigned char, scnhdr_size * ocr->nscns);
+  if (!objfile_internal_read (objfile->descriptor,
+			      objfile->offset + ocr->scnhdr_offset,
+			      scnbuf, scnhdr_size * ocr->nscns, &errmsg, err))
+    {
+      XDELETEVEC (scnbuf);
+      return errmsg;
+    }
+
+  fetch_32 = (ocr->is_big_endian
+	      ? objfile_fetch_big_32
+	      : objfile_fetch_little_32);
+
+  nscns = ocr->nscns;
+  strtab = NULL;
+  strtab_size = 0;
+  for (i = 0; i < nscns; ++i)
+    {
+      unsigned char *scnhdr;
+      unsigned char *scnname;
+      char namebuf[SCNNMLEN + 1];
+      char *name;
+      off_t scnptr;
+      unsigned int size;
+
+      scnhdr = scnbuf + i * scnhdr_size;
+      scnname = scnhdr + offsetof (struct external_scnhdr, s_name);
+      memcpy (namebuf, scnname, SCNNMLEN);
+      namebuf[SCNNMLEN] = '\0';
+      name = &namebuf[0];
+      if (namebuf[0] == '/')
+	{
+	  size_t strindex;
+	  char *end;
+
+	  strindex = strtol (namebuf, &end, 10);
+	  if (*end == '\0')
+	    {
+	      /* The real section name is found in the string
+		 table.  */
+	      if (strtab == NULL)
+		{
+		  strtab = objfile_coff_read_strtab (objfile, &strtab_size,
+						     &errmsg, err);
+		  if (strtab == NULL)
+		    {
+		      XDELETEVEC (scnbuf);
+		      return errmsg;
+		    }
+		}
+
+	      if (strindex < 4 || strindex >= strtab_size)
+		{
+		  XDELETEVEC (strtab);
+		  XDELETEVEC (scnbuf);
+		  *err = 0;
+		  return "section string index out of range";
+		}
+
+	      name = strtab + strindex;
+	    }
+	}
+
+      scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr, s_scnptr));
+      size = fetch_32 (scnhdr + offsetof (struct external_scnhdr, s_size));
+
+      if (!(*pfn) (data, name, scnptr, size))
+	break;
+    }
+
+  if (strtab != NULL)
+    XDELETEVEC (strtab);
+  XDELETEVEC (scnbuf);
+
+  return NULL;
+}
+
+/* Fetch the attributes for an objfile_read.  */
+
+static void *
+objfile_coff_fetch_attributes (objfile_read *objfile,
+			       const char **errmsg ATTRIBUTE_UNUSED,
+			       int *err ATTRIBUTE_UNUSED)
+{
+  struct objfile_coff_read *ocr = (struct objfile_coff_read *) objfile->data;
+  struct objfile_coff_attributes *ret;
+
+  ret = XNEW (struct objfile_coff_attributes);
+  ret->magic = ocr->magic;
+  ret->is_big_endian = ocr->is_big_endian;
+  ret->flags = ocr->flags;
+  return ret;
+}
+
+/* Release the private data for an objfile_read.  */
+
+static void
+objfile_coff_release_read (void *data)
+{
+  XDELETE (data);
+}
+
+/* Compare two attributes structures.  */
+
+static const char *
+objfile_coff_attributes_compare (void *data1, void *data2, int *err)
+{
+  struct objfile_coff_attributes *attrs1 =
+    (struct objfile_coff_attributes *) data1;
+  struct objfile_coff_attributes *attrs2 =
+    (struct objfile_coff_attributes *) data2;
+
+  if (attrs1->magic != attrs2->magic
+      || attrs1->is_big_endian != attrs2->is_big_endian)
+    {
+      *err = 0;
+      return "COFF object format mismatch";
+    }
+  return NULL;
+}
+
+/* Release the private data for an attributes structure.  */
+
+static void
+objfile_coff_release_attributes (void *data)
+{
+  XDELETE (data);
+}
+
+/* Prepare to write out a file.  */
+
+static void *
+objfile_coff_start_write (void *attributes_data,
+			  const char **errmsg ATTRIBUTE_UNUSED,
+			  int *err ATTRIBUTE_UNUSED)
+{
+  struct objfile_coff_attributes *attrs =
+    (struct objfile_coff_attributes *) attributes_data;
+  struct objfile_coff_attributes *ret;
+
+  /* We're just going to record the attributes, but we need to make a
+     copy because the user may delete them.  */
+  ret = XNEW (struct objfile_coff_attributes);
+  *ret = *attrs;
+  return ret;
+}
+
+/* Write out a COFF filehdr.  */
+
+static int
+objfile_coff_write_filehdr (objfile_write *objfile, int descriptor,
+			    unsigned int nscns, size_t strtab_offset,
+			    const char **errmsg, int *err)
+{
+  struct objfile_coff_attributes *attrs =
+    (struct objfile_coff_attributes *) objfile->data;
+  unsigned char hdrbuf[sizeof (struct external_filehdr)];
+  unsigned char *hdr;
+  void (*set_16) (unsigned char *, unsigned short);
+  void (*set_32) (unsigned char *, unsigned int);
+
+  hdr = &hdrbuf[0];
+
+  set_16 = (attrs->is_big_endian
+	    ? objfile_set_big_16
+	    : objfile_set_little_16);
+  set_32 = (attrs->is_big_endian
+	    ? objfile_set_big_32
+	    : objfile_set_little_32);
+
+  memset (hdr, 0, sizeof (struct external_filehdr));
+
+  /* We don't write out any symbols.  We'll see if that causes any
+     problems.  */
+
+  set_16 (hdr + offsetof (struct external_filehdr, f_magic), attrs->magic);
+  set_16 (hdr + offsetof (struct external_filehdr, f_magic), nscns);
+  /* f_timdat left as zero.  */
+  set_32 (hdr + offsetof (struct external_filehdr, f_symptr), strtab_offset);
+  /* f_nsyms left as zero.  */
+  /* f_opthdr left as zero.  */
+  set_16 (hdr + offsetof (struct external_filehdr, f_flags), attrs->flags);
+
+  return objfile_internal_write (descriptor, 0, hdrbuf,
+				 sizeof (struct external_filehdr),
+				 errmsg, err);
+}
+
+/* Write out a COFF section header.  */
+
+static int
+objfile_coff_write_scnhdr (objfile_write *objfile, int descriptor,
+			   const char *name, size_t *name_offset,
+			   off_t scnhdr_offset, size_t scnsize, off_t offset,
+			   const char **errmsg, int *err)
+{
+  struct objfile_coff_attributes *attrs =
+    (struct objfile_coff_attributes *) objfile->data;
+  void (*set_32) (unsigned char *, unsigned int);
+  unsigned char hdrbuf[sizeof (struct external_scnhdr)];
+  unsigned char *hdr;
+  size_t namelen;
+
+  set_32 = (attrs->is_big_endian
+	    ? objfile_set_big_32
+	    : objfile_set_little_32);
+
+  memset (hdrbuf, 0, sizeof hdrbuf);
+  hdr = &hdrbuf[0];
+
+  namelen = strlen (name);
+  if (namelen <= SCNNMLEN)
+    strncpy ((char *) hdr + offsetof (struct external_scnhdr, s_name), name,
+	     SCNNMLEN);
+  else
+    {
+      snprintf ((char *) hdr + offsetof (struct external_scnhdr, s_name),
+		SCNNMLEN, "/%lu", (unsigned long) *name_offset);
+      *name_offset += namelen + 1;
+    }
+
+  /* s_paddr left as zero.  */
+  /* s_vaddr left as zero.  */
+  set_32 (hdr + offsetof (struct external_scnhdr, s_size), scnsize);
+  set_32 (hdr + offsetof (struct external_scnhdr, s_scnptr), offset);
+  /* s_relptr left as zero.  */
+  /* s_lnnoptr left as zero.  */
+  /* s_nreloc left as zero.  */
+  /* s_nlnno left as zero.  */
+  set_32 (hdr + offsetof (struct external_scnhdr, s_flags),
+	  (STYP_DATA | IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_DISCARDABLE
+	   | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ));
+
+  return objfile_internal_write (descriptor, scnhdr_offset, hdrbuf,
+				 sizeof (struct external_scnhdr),
+				 errmsg, err);
+}
+
+/* Write out a complete COFF file.  */
+
+static const char *
+objfile_coff_write_to_file (objfile_write *objfile, int descriptor, int *err)
+{
+  struct objfile_coff_attributes *attrs =
+    (struct objfile_coff_attributes *) objfile->data;
+  unsigned int nscns;
+  objfile_write_section *section;
+  off_t scnhdr_offset;
+  size_t offset;
+  size_t name_offset;
+  const char *errmsg;
+  unsigned char strsizebuf[4];
+
+  nscns = 0;
+  for (section = objfile->sections; section != NULL; section = section->next)
+    ++nscns;
+
+  scnhdr_offset = sizeof (struct external_filehdr);
+  offset = scnhdr_offset + nscns * sizeof (struct external_scnhdr);
+  name_offset = 4;
+  for (section = objfile->sections; section != NULL; section = section->next)
+    {
+      size_t mask;
+      size_t new_offset;
+      size_t scnsize;
+      struct objfile_write_section_buffer *buffer;
+
+      mask = (1U << section->align) - 1;
+      new_offset = offset & mask;
+      new_offset &= ~ mask;
+      while (new_offset > offset)
+	{
+	  unsigned char zeroes[16];
+	  size_t write;
+
+	  memset (zeroes, 0, sizeof zeroes);
+	  write = new_offset - offset;
+	  if (write > sizeof zeroes)
+	    write = sizeof zeroes;
+	  if (!objfile_internal_write (descriptor, offset, zeroes, write,
+				       &errmsg, err))
+	    return errmsg;
+	}
+
+      scnsize = 0;
+      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
+	{
+	  if (!objfile_internal_write (descriptor, offset + scnsize,
+				       (const unsigned char *) buffer->buffer,
+				       buffer->size, &errmsg, err))
+	    return errmsg;
+	  scnsize += buffer->size;
+	}
+
+      if (!objfile_coff_write_scnhdr (objfile, descriptor, section->name,
+				      &name_offset, scnhdr_offset,
+				      scnsize, offset, &errmsg, err))
+	return errmsg;
+
+      scnhdr_offset += sizeof (struct external_scnhdr);
+      offset += scnsize;
+    }
+
+  if (attrs->is_big_endian)
+    objfile_set_big_32 (strsizebuf, name_offset);
+  else
+    objfile_set_little_32 (strsizebuf, name_offset);
+  if (!objfile_internal_write (descriptor, offset, strsizebuf, 4, &errmsg, err))
+    return errmsg;
+
+  name_offset = 4;
+  for (section = objfile->sections; section != NULL; section = section->next)
+    {
+      size_t namelen;
+
+      namelen = strlen (section->name);
+      if (namelen > SCNNMLEN)
+	{
+	  if (!objfile_internal_write (descriptor, offset + name_offset,
+				       (const unsigned char *) section->name,
+				       namelen + 1, &errmsg, err))
+	    return errmsg;
+	  name_offset += namelen;
+	}
+    }
+
+  if (!objfile_coff_write_filehdr (objfile, descriptor, nscns, offset,
+				   &errmsg, err))
+    return errmsg;
+
+  return NULL;
+}
+
+/* Release the private data for an objfile_write structure.  */
+
+static void
+objfile_coff_release_write (void *data)
+{
+  XDELETE (data);
+}
+
+/* The COFF functions.  */
+
+const struct objfile_functions objfile_coff_functions =
+{
+  objfile_coff_match,
+  objfile_coff_find_sections,
+  objfile_coff_fetch_attributes,
+  objfile_coff_release_read,
+  objfile_coff_attributes_compare,
+  objfile_coff_release_attributes,
+  objfile_coff_start_write,
+  objfile_coff_write_to_file,
+  objfile_coff_release_write
+};
Index: gcc/lto/lto-elf.c
===================================================================
--- gcc/lto/lto-elf.c	(revision 166002)
+++ gcc/lto/lto-elf.c	(working copy)
@@ -1,817 +0,0 @@
-/* LTO routines for ELF object files.
-   Copyright 2009, 2010 Free Software Foundation, Inc.
-   Contributed by CodeSourcery, Inc.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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 GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "diagnostic-core.h"
-#include "toplev.h"
-#include <gelf.h>
-#include "lto.h"
-#include "tm.h"
-#include "libiberty.h"
-#include "ggc.h"
-#include "lto-streamer.h"
-
-/* Cater to hosts with half-backed <elf.h> file like HP-UX.  */
-#ifndef EM_SPARC
-# define EM_SPARC 2
-#endif
-
-#ifndef EM_SPARC32PLUS
-# define EM_SPARC32PLUS 18
-#endif
-
-#ifndef ELFOSABI_NONE
-# define ELFOSABI_NONE 0
-#endif
-
-#ifndef ELFOSABI_LINUX
-# define ELFOSABI_LINUX 3
-#endif
-
-#ifndef SHN_XINDEX
-# define SHN_XINDEX 0xffff
-#endif
-
-
-/* Handle opening elf files on hosts, such as Windows, that may use 
-   text file handling that will break binary access.  */
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-
-/* Initialize FILE, an LTO file object for FILENAME.  */
-static void
-lto_file_init (lto_file *file, const char *filename, off_t offset)
-{
-  file->filename = filename;
-  file->offset = offset;
-}
-
-/* An ELF file.  */
-struct lto_elf_file 
-{
-  /* The base information.  */
-  lto_file base;
-
-  /* The system file descriptor for the file.  */
-  int fd;
-
-  /* The libelf descriptor for the file.  */
-  Elf *elf;
-
-  /* Section number of string table used for section names.  */
-  size_t sec_strtab;
-
-  /* Writable file members.  */
-
-  /* The currently active section.  */
-  Elf_Scn *scn;
-
-  /* The output stream for section header names.  */
-  struct lto_output_stream *shstrtab_stream;
-
-  /* Linked list of data which must be freed *after* the file has been
-     closed.  This is an annoying limitation of libelf.  */
-  struct lto_char_ptr_base *data;
-};
-typedef struct lto_elf_file lto_elf_file;
-
-/* Stores executable header attributes which must be shared by all ELF files.
-   This is used for validating input files and populating output files.  */
-static struct {
-  bool initialized;
-  /* 32 or 64 bits?  */
-  size_t bits;
-  unsigned char elf_ident[EI_NIDENT];
-  Elf64_Half elf_machine;
-} cached_file_attrs;
-
-
-/* Return the section header for SECTION.  The return value is never
-   NULL.  Call lto_elf_free_shdr to release the memory allocated.  */
-
-static Elf64_Shdr *
-lto_elf_get_shdr (Elf_Scn *section)
-{
-  Elf64_Shdr *shdr;
-
-  switch (cached_file_attrs.bits)
-    {
-    case 32:
-      {
-	Elf32_Shdr *shdr32;
-
-	/* Read the 32-bit section header.  */
-	shdr32 = elf32_getshdr (section);
-	if (!shdr32)
-	  fatal_error ("could not read section header: %s", elf_errmsg (0));
-
-	/* Transform it into a 64-bit section header.  */
-	shdr = XNEW (Elf64_Shdr);
-	shdr->sh_name = shdr32->sh_name;
-	shdr->sh_type = shdr32->sh_type;
-	shdr->sh_flags = shdr32->sh_flags;
-	shdr->sh_addr = shdr32->sh_addr;
-	shdr->sh_offset = shdr32->sh_offset;
-	shdr->sh_size = shdr32->sh_size;
-	shdr->sh_link = shdr32->sh_link;
-	shdr->sh_info = shdr32->sh_info;
-	shdr->sh_addralign = shdr32->sh_addralign;
-	shdr->sh_entsize  = shdr32->sh_entsize;
-	break;
-      }
-      break;
-
-    case 64:
-      shdr = elf64_getshdr (section);
-      if (!shdr)
-	fatal_error ("could not read section header: %s", elf_errmsg (0));
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  return shdr;
-}
-
-/* Free SHDR, previously allocated by lto_elf_get_shdr.  */
-static void
-lto_elf_free_shdr (Elf64_Shdr *shdr)
-{
-  if (cached_file_attrs.bits != 64)
-    free (shdr);
-}
-
-/* Build a hash table whose key is the section names and whose data is
-   the start and size of each section in the .o file.  */
-
-htab_t
-lto_obj_build_section_table (lto_file *lto_file) 
-{
-  lto_elf_file *elf_file = (lto_elf_file *)lto_file;
-  htab_t section_hash_table;
-  Elf_Scn *section;
-  size_t base_offset;
-
-  section_hash_table = lto_obj_create_section_hash_table ();
-
-  base_offset = elf_getbase (elf_file->elf);
-  /* We are reasonably sure that elf_getbase does not fail at this
-     point.  So assume that we run into the incompatibility with
-     the FreeBSD libelf implementation that has a non-working
-     elf_getbase for non-archive members in which case the offset
-     should be zero.  */
-  if (base_offset == (size_t)-1)
-    base_offset = 0;
-  for (section = elf_getscn (elf_file->elf, 0);
-       section;
-       section = elf_nextscn (elf_file->elf, section)) 
-    {
-      Elf64_Shdr *shdr;
-      const char *name;
-      size_t offset;
-      char *new_name;
-      void **slot;
-      struct lto_section_slot s_slot;
-
-      /* Get the name of this section.  */
-      shdr = lto_elf_get_shdr (section);
-      offset = shdr->sh_name;
-      name = elf_strptr (elf_file->elf, 
-			 elf_file->sec_strtab,
-			 offset);
-
-      /* Only put lto stuff into the symtab.  */
-      if (strncmp (name, LTO_SECTION_NAME_PREFIX, 
-		   strlen (LTO_SECTION_NAME_PREFIX)) != 0)
-	{
-	  lto_elf_free_shdr (shdr);
-	  continue;
-	}
-
-      new_name = XNEWVEC (char, strlen (name) + 1);
-      strcpy (new_name, name);
-      s_slot.name = new_name;
-      slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
-      if (*slot == NULL)
-	{
-	  struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
-
-	  new_slot->name = new_name;
-	  /* The offset into the file for this section.  */
-	  new_slot->start = base_offset + shdr->sh_offset;
-	  new_slot->len = shdr->sh_size;
-	  *slot = new_slot;
-	}
-      else
-	{
-	  error ("two or more sections for %s:", new_name);
-	  return NULL;
-	}
-
-      lto_elf_free_shdr (shdr);
-    }
-
-  return section_hash_table;
-}
-
-
-/* Initialize the section header of section SCN.  SH_NAME is the section name
-   as an index into the section header string table.  SH_TYPE is the section
-   type, an SHT_* macro from libelf headers.  */
-
-#define DEFINE_INIT_SHDR(BITS)					      \
-static void							      \
-init_shdr##BITS (Elf_Scn *scn, size_t sh_name, size_t sh_type)	      \
-{								      \
-  Elf##BITS##_Shdr *shdr;					      \
-								      \
-  shdr = elf##BITS##_getshdr (scn);				      \
-  if (!shdr)							      \
-    {								      \
-      if (BITS == 32)						      \
-	fatal_error ("elf32_getshdr() failed: %s", elf_errmsg (-1));  \
-      else							      \
-	fatal_error ("elf64_getshdr() failed: %s", elf_errmsg (-1));  \
-    }								      \
-								      \
-  shdr->sh_name = sh_name;					      \
-  shdr->sh_type = sh_type;					      \
-  shdr->sh_addralign = POINTER_SIZE / BITS_PER_UNIT;		      \
-  shdr->sh_flags = 0;						      \
-  shdr->sh_entsize = 0;						      \
-}
-
-DEFINE_INIT_SHDR (32)
-DEFINE_INIT_SHDR (64)
-
-static bool first_data_block;
-
-/* Begin a new ELF section named NAME with type TYPE in the current output
-   file.  TYPE is an SHT_* macro from the libelf headers.  */
-
-static void
-lto_elf_begin_section_with_type (const char *name, size_t type)
-{
-  lto_elf_file *file;
-  Elf_Scn *scn;
-  size_t sh_name;
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_elf_file *) lto_get_current_out_file (),
-  gcc_assert (file);
-  gcc_assert (file->elf);
-  gcc_assert (!file->scn);
-
-  /* Create a new section.  */
-  scn = elf_newscn (file->elf);
-  if (!scn)
-    fatal_error ("could not create a new ELF section: %s", elf_errmsg (-1));
-  file->scn = scn;
-
-  /* Add a string table entry and record the offset.  */
-  gcc_assert (file->shstrtab_stream);
-  sh_name = file->shstrtab_stream->total_size;
-  lto_output_data_stream (file->shstrtab_stream, name, strlen (name) + 1);
-
-  /* Initialize the section header.  */
-  switch (cached_file_attrs.bits)
-    {
-    case 32:
-      init_shdr32 (scn, sh_name, type);
-      break;
-
-    case 64:
-      init_shdr64 (scn, sh_name, type);
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  first_data_block = true;
-}
-
-
-/* Begin a new ELF section named NAME in the current output file.  */
-
-void
-lto_obj_begin_section (const char *name)
-{
-  lto_elf_begin_section_with_type (name, SHT_PROGBITS);
-}
-
-
-/* Append DATA of length LEN to the current output section.  BASE is a pointer
-   to the output page containing DATA.  It is freed once the output file has
-   been written.  */
-
-void
-lto_obj_append_data (const void *data, size_t len, void *block)
-{
-  lto_elf_file *file;
-  Elf_Data *elf_data;
-  struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block;
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_elf_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  elf_data = elf_newdata (file->scn);
-  if (!elf_data)
-    fatal_error ("could not append data to ELF section: %s", elf_errmsg (-1));
-
-  if (first_data_block)
-    {
-      elf_data->d_align = POINTER_SIZE / BITS_PER_UNIT;
-      first_data_block = false;
-    }
-  else
-    elf_data->d_align = 1;
-  elf_data->d_buf = CONST_CAST (void *, data);
-  elf_data->d_off = 0LL;
-  elf_data->d_size = len;
-  elf_data->d_type = ELF_T_BYTE;
-  elf_data->d_version = EV_CURRENT;
-
-  base->ptr = (char *)file->data;
-  file->data = base;
-}
-
-
-/* End the current output section.  This just does some assertion checking
-   and sets the current output file's scn member to NULL.  */
-
-void
-lto_obj_end_section (void)
-{
-  lto_elf_file *file;
-
-  /* Grab the current output file and validate some basic assertions.  */
-  file = (lto_elf_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  file->scn = NULL;
-}
-
-
-/* Return true if ELF_MACHINE is compatible with the cached value of the
-   architecture and possibly update the latter.  Return false otherwise.
-
-   Note: if you want to add more EM_* cases, you'll need to provide the
-   corresponding definitions at the beginning of the file.  */
-
-static bool
-is_compatible_architecture (Elf64_Half elf_machine)
-{
-  if (cached_file_attrs.elf_machine == elf_machine)
-    return true;
-
-  switch (cached_file_attrs.elf_machine)
-    {
-    case EM_SPARC:
-      if (elf_machine == EM_SPARC32PLUS)
-	{
-	  cached_file_attrs.elf_machine = elf_machine;
-	  return true;
-	}
-      break;
-
-    case EM_SPARC32PLUS:
-      if (elf_machine == EM_SPARC)
-	return true;
-      break;
-
-    default:
-      break;
-    }
-
-  return false;
-}
-
-
-/* Validate's ELF_FILE's executable header and, if cached_file_attrs is
-   uninitialized, caches the architecture.  */
-
-#define DEFINE_VALIDATE_EHDR(BITS)				\
-static bool							\
-validate_ehdr##BITS (lto_elf_file *elf_file)			\
-{								\
-  Elf##BITS##_Ehdr *elf_header;					\
-								\
-  elf_header = elf##BITS##_getehdr (elf_file->elf);		\
-  if (!elf_header)						\
-    {								\
-      error ("could not read ELF header: %s", elf_errmsg (0));	\
-      return false;						\
-    }								\
-								\
-  if (elf_header->e_type != ET_REL)				\
-    {								\
-      error ("not a relocatable ELF object file");		\
-      return false;						\
-    }								\
-								\
-  if (!cached_file_attrs.initialized)				\
-    cached_file_attrs.elf_machine = elf_header->e_machine;	\
-  else if (!is_compatible_architecture (elf_header->e_machine))	\
-    {								\
-      error ("inconsistent file architecture detected");	\
-      return false;						\
-    }								\
-								\
-  return true;							\
-}
-
-DEFINE_VALIDATE_EHDR (32)
-DEFINE_VALIDATE_EHDR (64)
-
-
-#ifndef HAVE_ELF_GETSHDRSTRNDX
-/* elf_getshdrstrndx replacement for systems that lack it, but provide
-   either the gABI conformant or Solaris 2 variant of elf_getshstrndx
-   instead.  */
-
-static int
-elf_getshdrstrndx (Elf *elf, size_t *dst)
-{
-#ifdef HAVE_ELF_GETSHSTRNDX_GABI
-  return elf_getshstrndx (elf, dst);
-#else
-  return elf_getshstrndx (elf, dst) ? 0 : -1;
-#endif
-}
-#endif
-
-/* Validate's ELF_FILE's executable header and, if cached_file_attrs is
-   uninitialized, caches the results.  Also records the section header string
-   table's section index.  Returns true on success or false on failure.  */
-
-static bool
-validate_file (lto_elf_file *elf_file)
-{
-  const char *elf_ident;
-
-  /* Some aspects of the libelf API are dependent on whether the
-     object file is a 32-bit or 64-bit file.  Determine which kind of
-     file this is now.  */
-  elf_ident = elf_getident (elf_file->elf, NULL);
-  if (!elf_ident)
-    {
-      error ("could not read ELF identification information: %s",
-	      elf_errmsg (0));
-      return false;
-    }
-
-  if (!cached_file_attrs.initialized)
-    {
-      switch (elf_ident[EI_CLASS])
-	{
-	case ELFCLASS32:
-	  cached_file_attrs.bits = 32;
-	  break;
-
-	case ELFCLASS64:
-	  cached_file_attrs.bits = 64;
-	  break;
-
-	default:
-	  error ("unsupported ELF file class");
-	  return false;
-	}
-
-      memcpy (cached_file_attrs.elf_ident, elf_ident,
-	      sizeof cached_file_attrs.elf_ident);
-    }
-  else
-    {
-      char elf_ident_buf[EI_NIDENT];
-
-      memcpy (elf_ident_buf, elf_ident, sizeof elf_ident_buf);
-
-      if (elf_ident_buf[EI_OSABI] != cached_file_attrs.elf_ident[EI_OSABI])
-	{
-	  /* Allow mixing ELFOSABI_NONE with ELFOSABI_LINUX, with the result
-	     ELFOSABI_LINUX.  */
-	  if (elf_ident_buf[EI_OSABI] == ELFOSABI_NONE
-	      && cached_file_attrs.elf_ident[EI_OSABI] == ELFOSABI_LINUX)
-	    elf_ident_buf[EI_OSABI] = cached_file_attrs.elf_ident[EI_OSABI];
-	  else if (elf_ident_buf[EI_OSABI] == ELFOSABI_LINUX
-		   && cached_file_attrs.elf_ident[EI_OSABI] == ELFOSABI_NONE)
-	    cached_file_attrs.elf_ident[EI_OSABI] = elf_ident_buf[EI_OSABI];
-	}
-
-      if (memcmp (elf_ident_buf, cached_file_attrs.elf_ident,
-		  sizeof cached_file_attrs.elf_ident))
-	{
-	  error ("incompatible ELF identification");
-	  return false;
-	}
-    }
-
-  /* Check that the input file is a relocatable object file with the correct
-     architecture.  */
-  switch (cached_file_attrs.bits)
-    {
-    case 32:
-      if (!validate_ehdr32 (elf_file))
-	return false;
-      break;
-
-    case 64:
-      if (!validate_ehdr64 (elf_file))
-	return false;
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  /* Read the string table used for section header names.  */
-  if (elf_getshdrstrndx (elf_file->elf, &elf_file->sec_strtab) == -1)
-    {
-      error ("could not locate ELF string table: %s", elf_errmsg (0));
-      return false;
-    }
-
-  cached_file_attrs.initialized = true;
-  return true;
-}
-
-
-/* Helper functions used by init_ehdr.  Initialize ELF_FILE's executable
-   header using cached data from previously read files.  */
-
-#define DEFINE_INIT_EHDR(BITS)					      \
-static void							      \
-init_ehdr##BITS (lto_elf_file *elf_file)			      \
-{								      \
-  Elf##BITS##_Ehdr *ehdr;					      \
-								      \
-  gcc_assert (cached_file_attrs.bits);				      \
-								      \
-  ehdr = elf##BITS##_newehdr (elf_file->elf);			      \
-  if (!ehdr)							      \
-    {								      \
-      if (BITS == 32)						      \
-	fatal_error ("elf32_newehdr() failed: %s", elf_errmsg (-1));  \
-      else							      \
-	fatal_error ("elf64_newehdr() failed: %s", elf_errmsg (-1));  \
-    }								      \
-								      \
-  memcpy (ehdr->e_ident, cached_file_attrs.elf_ident,		      \
-	  sizeof cached_file_attrs.elf_ident);			      \
-  ehdr->e_type = ET_REL;					      \
-  ehdr->e_version = EV_CURRENT;					      \
-  ehdr->e_machine = cached_file_attrs.elf_machine;		      \
-}
-
-DEFINE_INIT_EHDR (32)
-DEFINE_INIT_EHDR (64)
-
-
-/* Initialize ELF_FILE's executable header using cached data from previously
-   read files.  */
-
-static void
-init_ehdr (lto_elf_file *elf_file)
-{
-  switch (cached_file_attrs.bits)
-    {
-    case 32:
-      init_ehdr32 (elf_file);
-      break;
-
-    case 64:
-      init_ehdr64 (elf_file);
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Open ELF file FILENAME.  If WRITABLE is true, the file is opened for write
-   and, if necessary, created.  Otherwise, the file is opened for reading.
-   Returns the opened file.  */
-
-lto_file *
-lto_obj_file_open (const char *filename, bool writable)
-{
-  lto_elf_file *elf_file;
-  lto_file *result = NULL;
-  off_t offset;
-  long loffset;
-  off_t header_offset;
-  const char *offset_p;
-  char *fname;
-  int consumed;
-
-  offset_p = strrchr (filename, '@');
-  if (offset_p
-      && offset_p != filename
-      && sscanf (offset_p, "@%li%n", &loffset, &consumed) >= 1
-      && strlen (offset_p) == (unsigned int)consumed)
-    {
-      fname = (char *) xmalloc (offset_p - filename + 1);
-      memcpy (fname, filename, offset_p - filename);
-      fname[offset_p - filename] = '\0';
-      offset = (off_t)loffset;
-      /* elf_rand expects the offset to point to the ar header, not the
-         object itself. Subtract the size of the ar header (60 bytes).
-         We don't uses sizeof (struct ar_hd) to avoid including ar.h */
-      header_offset = offset - 60;
-    }
-  else
-    {
-      fname = xstrdup (filename);
-      offset = 0;
-      header_offset = 0;
-    }
-
-  /* Set up.  */
-  elf_file = XCNEW (lto_elf_file);
-  result = (lto_file *) elf_file;
-  lto_file_init (result, fname, offset);
-  elf_file->fd = -1;
-
-  /* Open the file.  */
-  elf_file->fd = open (fname, writable ? O_WRONLY|O_CREAT|O_BINARY 
-				       : O_RDONLY|O_BINARY, 0666);
-  if (elf_file->fd == -1)
-    {
-      error ("could not open file %s", fname);
-      goto fail;
-    }
-
-  /* Initialize the ELF library.  */
-  if (elf_version (EV_CURRENT) == EV_NONE)
-    {
-      error ("ELF library is older than that used when building GCC");
-      goto fail;
-    }
-
-  /* Open the ELF file descriptor.  */
-  elf_file->elf = elf_begin (elf_file->fd, writable ? ELF_C_WRITE : ELF_C_READ,
-			     NULL);
-  if (!elf_file->elf)
-    {
-      error ("could not open %s as an ELF file: %s", fname, elf_errmsg (0));
-      goto fail;
-    }
-
-  if (offset != 0)
-    {
-      Elf *e;
-      off_t t = elf_rand (elf_file->elf, header_offset);
-      if (t != header_offset)
-        {
-          error ("could not seek in archive");
-          goto fail;
-        }
-
-      e = elf_begin (elf_file->fd, ELF_C_READ, elf_file->elf);
-      if (e == NULL)
-        {
-          error("could not find archive member");
-          goto fail;
-        }
-      elf_end (elf_file->elf);
-      elf_file->elf = e;
-    }
-
-  if (writable)
-    {
-      init_ehdr (elf_file);
-      elf_file->shstrtab_stream = XCNEW (struct lto_output_stream);
-      /* Output an empty string to the section header table.  This becomes the
-	 name of the initial NULL section.  */
-      lto_output_1_stream (elf_file->shstrtab_stream, '\0');
-    }
-  else
-    if (!validate_file (elf_file))
-      goto fail;
-
-  return result;
-
- fail:
-  if (result)
-    lto_obj_file_close (result);
-  return NULL;
-}
-
-
-/* Close ELF file FILE and clean up any associated data structures.  If FILE
-   was opened for writing, the file's ELF data is written at this time, and
-   any cached data buffers are freed.  */
-
-void
-lto_obj_file_close (lto_file *file)
-{
-  lto_elf_file *elf_file = (lto_elf_file *) file;
-  struct lto_char_ptr_base *cur, *tmp;
-
-  /* Write the ELF section header string table.  */
-  if (elf_file->shstrtab_stream)
-    {
-      size_t strtab;
-      GElf_Ehdr *ehdr_p, ehdr_buf;
-      lto_file *old_file = lto_set_current_out_file (file);
-
-      lto_elf_begin_section_with_type (".shstrtab", SHT_STRTAB);
-      ehdr_p = gelf_getehdr (elf_file->elf, &ehdr_buf);
-      if (ehdr_p == NULL)
-	fatal_error ("gelf_getehdr() failed: %s", elf_errmsg (-1));
-      strtab = elf_ndxscn (elf_file->scn);
-      if (strtab < SHN_LORESERVE)
-	ehdr_p->e_shstrndx = strtab;
-      else
-	{
-	  GElf_Shdr *shdr_p, shdr_buf;
-	  Elf_Scn *scn_p = elf_getscn (elf_file->elf, 0);
-	  if (scn_p == NULL)
-	    fatal_error ("elf_getscn() failed: %s", elf_errmsg (-1));
-	  shdr_p = gelf_getshdr (scn_p, &shdr_buf);
-	  if (shdr_p == NULL)
-	    fatal_error ("gelf_getshdr() failed: %s", elf_errmsg (-1));
-	  shdr_p->sh_link = strtab;
-	  if (gelf_update_shdr (scn_p, shdr_p) == 0)
-	    fatal_error ("gelf_update_shdr() failed: %s", elf_errmsg (-1));
-	  ehdr_p->e_shstrndx = SHN_XINDEX;
-	}
-      if (gelf_update_ehdr (elf_file->elf, ehdr_p) == 0)
-	fatal_error ("gelf_update_ehdr() failed: %s", elf_errmsg (-1));
-      lto_write_stream (elf_file->shstrtab_stream);
-      lto_obj_end_section ();
-
-      lto_set_current_out_file (old_file);
-      free (elf_file->shstrtab_stream);
-
-      if (elf_update (elf_file->elf, ELF_C_WRITE) < 0)
-	fatal_error ("elf_update() failed: %s", elf_errmsg (-1));
-    }
-
-  if (elf_file->elf)
-    elf_end (elf_file->elf);
-  if (elf_file->fd != -1)
-    close (elf_file->fd);
-
-  /* Free any ELF data buffers.  */
-  cur = elf_file->data;
-  while (cur)
-    {
-      tmp = cur;
-      cur = (struct lto_char_ptr_base *) cur->ptr;
-      free (tmp);
-    }
-
-  free (file);
-}
-
-
-/* The current output file.  */
-static lto_file *current_out_file;
-
-
-/* Sets the current output file to FILE.  Returns the old output file or
-   NULL.  */
-
-lto_file *
-lto_set_current_out_file (lto_file *file)
-{
-  lto_file *old_file = current_out_file;
-  current_out_file = file;
-  return old_file;
-}
-
-
-/* Returns the current output file.  */
-
-lto_file *
-lto_get_current_out_file (void)
-{
-  return current_out_file;
-}
Index: gcc/lto/lto-objfile.c
===================================================================
--- gcc/lto/lto-objfile.c	(revision 0)
+++ gcc/lto/lto-objfile.c	(revision 0)
@@ -0,0 +1,374 @@
+/* LTO routines to use objfiles.
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic-core.h"
+#include "toplev.h"
+#include "lto.h"
+#include "tm.h"
+#include "lto-streamer.h"
+#include "libiberty.h"
+#include "objfile.h"
+
+/* Handle opening elf files on hosts, such as Windows, that may use
+   text file handling that will break binary access.  */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+/* Segment name for LTO sections.  This is only used for Mach-O.
+   FIXME: This needs to be kept in sync with darwin.c.  */
+
+#define LTO_SEGMENT_NAME "__GNU_LTO"
+
+/* An LTO file wrapped around an objfile.  */
+
+struct lto_objfile
+{
+  /* The base information.  */
+  lto_file base;
+
+  /* The system file descriptor.  */
+  int fd;
+
+  /* The objfile if we are reading the file.  */
+  objfile_read *objfile_r;
+
+  /* The objfile if we are writing the file.  */
+  objfile_write *objfile_w;
+
+  /* The currently active section.  */
+  objfile_write_section *section;
+};
+
+/* Saved objfile attributes.  FIXME: Once set, this is never
+   cleared.  */
+
+static objfile_attributes *saved_attributes;
+
+/* Initialize FILE, an LTO file object for FILENAME.  */
+
+static void
+lto_file_init (lto_file *file, const char *filename, off_t offset)
+{
+  file->filename = filename;
+  file->offset = offset;
+}
+
+/* Open the file FILENAME.  It WRITABLE is true, the file is opened
+   for write and, if necessary, created.  Otherwise, the file is
+   opened for reading.  Returns the opened file.  */
+
+lto_file *
+lto_obj_file_open (const char *filename, bool writable)
+{
+  const char *offset_p;
+  long loffset;
+  int consumed;
+  char *fname;
+  off_t offset;
+  struct lto_objfile *lo;
+  const char *errmsg;
+  int err;
+
+  offset_p = strrchr (filename, '@');
+  if (offset_p != NULL
+      && offset_p != filename
+      && sscanf (offset_p, "@%li%n", &loffset, &consumed) >= 1
+      && strlen (offset_p) == (unsigned int) consumed)
+    {
+      fname = XNEWVEC (char, offset_p - filename + 1);
+      memcpy (fname, filename, offset_p - filename);
+      fname[offset_p - filename] = '\0';
+      offset = (off_t) loffset;
+    }
+  else
+    {
+      fname = xstrdup (filename);
+      offset = 0;
+    }
+
+  lo = XCNEW (struct lto_objfile);
+  lto_file_init ((lto_file *) lo, fname, offset);
+
+  lo->fd = open (fname,
+		 (writable
+		  ? O_WRONLY | O_CREAT | O_BINARY
+		  : O_RDONLY | O_BINARY),
+		 0666);
+  if (lo->fd == -1)
+    {
+      error ("open %s failed: %s", fname, xstrerror (errno));
+      goto fail;
+    }
+
+  if (!writable)
+    {
+      objfile_attributes *attrs;
+
+      lo->objfile_r = objfile_open_read (lo->fd, offset, LTO_SEGMENT_NAME,
+					 &errmsg, &err);
+      if (lo->objfile_r == NULL)
+	goto fail_errmsg;
+
+      attrs = objfile_fetch_attributes (lo->objfile_r, &errmsg, &err);
+      if (attrs == NULL)
+	goto fail_errmsg;
+
+      if (saved_attributes == NULL)
+	saved_attributes = attrs;
+      else
+	{
+	  errmsg = objfile_attributes_compare (saved_attributes, attrs, &err);
+	  if (errmsg != NULL)
+	    goto fail_errmsg;
+	}
+    }
+  else
+    {
+      gcc_assert (saved_attributes != NULL);
+      lo->objfile_w = objfile_start_write (saved_attributes, LTO_SEGMENT_NAME,
+					   &errmsg, &err);
+      if (lo->objfile_w == NULL)
+	goto fail_errmsg;
+    }
+
+  return &lo->base;
+
+ fail_errmsg:
+  if (err == 0)
+    error ("%s: %s", fname, errmsg);
+  else
+    error ("%s: %s: %s", fname, errmsg, xstrerror (err));
+					 
+ fail:
+  if (lo != NULL)
+    lto_obj_file_close ((lto_file *) lo);
+  return NULL;
+}
+
+/* Close FILE.  If FILE was opened for writing, it is written out
+   now.  */
+
+void
+lto_obj_file_close (lto_file *file)
+{
+  struct lto_objfile *lo = (struct lto_objfile *) file;
+
+  if (lo->objfile_r != NULL)
+    objfile_release_read (lo->objfile_r);
+  else if (lo->objfile_w != NULL)
+    {
+      const char *errmsg;
+      int err;
+
+      gcc_assert (lo->base.offset == 0);
+
+      errmsg = objfile_write_to_file (lo->objfile_w, lo->fd, &err);
+      if (errmsg != NULL)
+	{
+	  if (err == 0)
+	    fatal_error ("%s", errmsg);
+	  else
+	    fatal_error ("%s: %s", errmsg, xstrerror (err));
+	}
+
+      objfile_release_write (lo->objfile_w);
+    }
+
+  if (lo->fd != -1)
+    {
+      if (close (lo->fd) < 0)
+	fatal_error ("close: %s", xstrerror (errno));
+    }
+}
+
+/* This is passed to lto_obj_add_section.  */
+
+struct lto_obj_add_section_data
+{
+  /* The hash table of sections.  */
+  htab_t section_hash_table;
+  /* The offset of this file.  */
+  off_t base_offset;
+};
+
+/* This is called for each section in the file.  */
+
+static int
+lto_obj_add_section (void *data, const char *name, off_t offset,
+		     off_t length)
+{
+  struct lto_obj_add_section_data *loasd =
+    (struct lto_obj_add_section_data *) data;
+  htab_t section_hash_table = (htab_t) loasd->section_hash_table;
+  char *new_name;
+  struct lto_section_slot s_slot;
+  void **slot;
+
+  if (strncmp (name, LTO_SECTION_NAME_PREFIX,
+	       strlen (LTO_SECTION_NAME_PREFIX)) != 0)
+    return 1;
+
+  new_name = xstrdup (name);
+  s_slot.name = new_name;
+  slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
+  if (*slot == NULL)
+    {
+      struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
+
+      new_slot->name = new_name;
+      new_slot->start = loasd->base_offset + offset;
+      new_slot->len = length;
+      *slot = new_slot;
+    }
+  else
+    {
+      error ("two or more sections for %s", new_name);
+      return 0;
+    }
+
+  return 1;
+}
+
+/* Build a hash table whose key is the section name and whose data is
+   the start and size of each section in the .o file.  */
+
+htab_t
+lto_obj_build_section_table (lto_file *lto_file)
+{
+  struct lto_objfile *lo = (struct lto_objfile *) lto_file;
+  htab_t section_hash_table;
+  struct lto_obj_add_section_data loasd;
+  const char *errmsg;
+  int err;
+
+  section_hash_table = lto_obj_create_section_hash_table ();
+
+  gcc_assert (lo->objfile_r != NULL && lo->objfile_w == NULL);
+  loasd.section_hash_table = section_hash_table;
+  loasd.base_offset = lo->base.offset;
+  errmsg = objfile_find_sections (lo->objfile_r, lto_obj_add_section,
+				  &loasd, &err);
+  if (errmsg != NULL)
+    {
+      if (err == 0)
+	error ("%s", errmsg);
+      else
+	error ("%s: %s", errmsg, xstrerror (err));
+      htab_delete (section_hash_table);
+      return NULL;
+    }
+
+  return section_hash_table;
+}
+
+/* The current output file.  */
+
+static lto_file *current_out_file;
+
+/* Set the current output file.  Return the old one.  */
+
+lto_file *
+lto_set_current_out_file (lto_file *file)
+{
+  lto_file *old_file;
+
+  old_file = current_out_file;
+  current_out_file = file;
+  return old_file;
+}
+
+/* Return the current output file.  */
+
+lto_file *
+lto_get_current_out_file (void)
+{
+  return current_out_file;
+}
+
+/* Begin writing a new section named NAME in the current output
+   file.  */
+
+void
+lto_obj_begin_section (const char *name)
+{
+  struct lto_objfile *lo;
+  int align;
+  const char *errmsg;
+  int err;
+
+  lo = (struct lto_objfile *) current_out_file;
+  gcc_assert (lo != NULL
+	      && lo->objfile_r == NULL
+	      && lo->objfile_w != NULL
+	      && lo->section == NULL);
+
+  align = exact_log2 (POINTER_SIZE / BITS_PER_UNIT);
+  lo->section = objfile_write_create_section (lo->objfile_w, name, align,
+					      &errmsg, &err);
+  if (lo->section == NULL)
+    {
+      if (err == 0)
+	fatal_error ("%s", errmsg);
+      else
+	fatal_error ("%s: %s", errmsg, xstrerror (errno));
+    }
+}
+
+/* Add data to a section.  BLOCK is a pointer to memory containing
+   DATA.  */
+
+void
+lto_obj_append_data (const void *data, size_t len, void *block)
+{
+  struct lto_objfile *lo;
+  const char *errmsg;
+  int err;
+
+  lo = (struct lto_objfile *) current_out_file;
+  gcc_assert (lo != NULL && lo->section != NULL);
+
+  errmsg = objfile_write_add_data (lo->objfile_w, lo->section, data, len, 1,
+				   &err);
+  if (errmsg != NULL)
+    {
+      if (err == 0)
+	fatal_error ("%s", errmsg);
+      else
+	fatal_error ("%s: %s", errmsg, xstrerror (errno));
+    }
+
+  free (block);
+}
+
+/* Stop writing to the current output section.  */
+
+void
+lto_obj_end_section (void)
+{
+  struct lto_objfile *lo;
+
+  lo = (struct lto_objfile *) current_out_file;
+  gcc_assert (lo != NULL && lo->section != NULL);
+  lo->section = NULL;
+}
Index: gcc/lto/lto-coff.c
===================================================================
--- gcc/lto/lto-coff.c	(revision 166002)
+++ gcc/lto/lto-coff.c	(working copy)
@@ -1,817 +0,0 @@
-/* LTO routines for COFF object files.
-   Copyright 2009, 2010 Free Software Foundation, Inc.
-   Contributed by Dave Korn.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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 GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "diagnostic-core.h"
-#include "toplev.h"
-#include "lto.h"
-#include "tm.h"
-#include "libiberty.h"
-#include "ggc.h"
-#include "lto-streamer.h"
-#include "lto/lto-coff.h"
-
-
-/* Rather than implementing a libcoff to match libelf, or attempting to
-   integrate libbfd into GCC, this file is a self-contained (and very
-   minimal) COFF format object file reader/writer.  The generated files
-   will contain a COFF header, a number of COFF section headers, the 
-   section data itself, and a trailing string table for section names.  */
-
-/* Handle opening elf files on hosts, such as Windows, that may use 
-   text file handling that will break binary access.  */
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-/* Known header magics for validation, as an array.  */
-
-static const unsigned int coff_machine_array[] = COFF_KNOWN_MACHINES;
-
-/* Number of valid entries (no sentinel) in array.  */
-
-#define NUM_COFF_KNOWN_MACHINES	\
-	(sizeof (coff_machine_array) / sizeof (coff_machine_array[0]))
-
-/* Cached object file header.  */
-
-static Coff_header cached_coff_hdr;
-
-/* Flag to indicate if we have read and cached any header yet.  */
-
-static bool cached_coff_hdr_valid = false;
-
-/* The current output file.  */
-
-static lto_file *current_out_file;
-
-
-/* Sets the current output file to FILE.  Returns the old output file or
-   NULL.  */
-
-lto_file *
-lto_set_current_out_file (lto_file *file)
-{
-  lto_file *old_file = current_out_file;
-  current_out_file = file;
-  return old_file;
-}
-
-
-/* Returns the current output file.  */
-
-lto_file *
-lto_get_current_out_file (void)
-{
-  return current_out_file;
-}
-
-
-/* COFF section structure constructor.  */
-
-static lto_coff_section *
-coff_newsection (lto_coff_file *file, const char *name, size_t type)
-{
-  lto_coff_section *ptr, **chain_ptr_ptr;
-
-  ptr = XCNEW (lto_coff_section);
-  ptr->name = name;
-  ptr->type = type;
-
-  chain_ptr_ptr = &file->section_chain;
-  while (*chain_ptr_ptr)
-    chain_ptr_ptr = &(*chain_ptr_ptr)->next;
-  *chain_ptr_ptr = ptr;
-
-  return ptr;
-}
-
-
-/* COFF section data block structure constructor.  */
-
-static lto_coff_data *
-coff_newdata (lto_coff_section *sec)
-{
-  lto_coff_data *ptr, **chain_ptr_ptr;
-
-  ptr = XCNEW (lto_coff_data);
-
-  chain_ptr_ptr = &sec->data_chain;
-  while (*chain_ptr_ptr)
-    chain_ptr_ptr = &(*chain_ptr_ptr)->next;
-  *chain_ptr_ptr = ptr;
-
-  return ptr;
-}
-
-
-/* Initialize FILE, an LTO file object for FILENAME.  */
-
-static void
-lto_file_init (lto_file *file, const char *filename, off_t offset)
-{
-  file->filename = filename;
-  file->offset = offset;
-}
-
-/* Build a hash table whose key is the section names and whose data is
-   the start and size of each section in the .o file.  */
-
-htab_t
-lto_obj_build_section_table (lto_file *lto_file) 
-{
-  lto_coff_file *coff_file = (lto_coff_file *)lto_file;
-  lto_coff_section *sec;
-  htab_t section_hash_table;
-  ssize_t strtab_size;
-  char *strtab;
-
-  section_hash_table = lto_obj_create_section_hash_table ();
-
-  /* Seek to start of string table.  */
-  if (coff_file->strtab_offs != lseek (coff_file->fd,
-		coff_file->base.offset + coff_file->strtab_offs, SEEK_SET))
-    {
-      error ("altered or invalid COFF object file");
-      return section_hash_table;
-    }
-
-  strtab_size = coff_file->file_size - coff_file->strtab_offs;
-  strtab = XNEWVEC (char, strtab_size);
-  if (read (coff_file->fd, strtab, strtab_size) != strtab_size)
-    {
-      error ("invalid COFF object file string table");
-      return section_hash_table;
-    }
-
-  /* Scan sections looking at names.  */
-  COFF_FOR_ALL_SECTIONS(coff_file, sec)
-    {
-      struct lto_section_slot s_slot;
-      void **slot;
-      char *new_name;
-      int stringoffset;
-      char *name = (char *) &sec->coffsec.Name[0];
-
-      /* Skip dummy string section if by any chance we see it.  */
-      if (sec->type == 1)
-	continue;
-
-      if (name[0] == '/')
-	{
-	  if (1 != sscanf (&name[1], "%d", &stringoffset)
-		|| stringoffset < 0 || stringoffset >= strtab_size)
-	    {
-	      error ("invalid COFF section name string");
-	      continue;
-	    }
-	  name = strtab + stringoffset;
-	}
-      else
-	{
-	  /* If we cared about the VirtualSize field, we couldn't
-	     crudely trash it like this to guarantee nul-termination
-	     of the Name field.  But we don't, so we do.  */
-	  name[8] = 0;
-	}
-      if (strncmp (name, LTO_SECTION_NAME_PREFIX,
-			strlen (LTO_SECTION_NAME_PREFIX)) != 0)
-	  continue;
-
-      new_name = XNEWVEC (char, strlen (name) + 1);
-      strcpy (new_name, name);
-      s_slot.name = new_name;
-      slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
-      if (*slot == NULL)
-	{
-	  struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
-
-	  new_slot->name = new_name;
-	  /* The offset into the file for this section.  */
-	  new_slot->start = coff_file->base.offset
-			+ COFF_GET(&sec->coffsec,PointerToRawData);
-	  new_slot->len = COFF_GET(&sec->coffsec,SizeOfRawData);
-	  *slot = new_slot;
-	}
-      else
-	{
-	  error ("two or more sections for %s:", new_name);
-	  return NULL;
-	}
-    }
-
-  free (strtab);
-  return section_hash_table;
-}
-
-
-/* Begin a new COFF section named NAME with type TYPE in the current output
-   file.  TYPE is an SHT_* macro from the libelf headers.  */
-
-static void
-lto_coff_begin_section_with_type (const char *name, size_t type)
-{
-  lto_coff_file *file;
-  size_t sh_name;
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_coff_file *) lto_get_current_out_file (),
-  gcc_assert (file);
-  gcc_assert (!file->scn);
-
-  /* Create a new section.  */
-  file->scn = coff_newsection (file, name, type);
-  if (!file->scn)
-    fatal_error ("could not create a new COFF section: %m");
-
-  /* Add a string table entry and record the offset.  */
-  gcc_assert (file->shstrtab_stream);
-  sh_name = file->shstrtab_stream->total_size;
-  lto_output_data_stream (file->shstrtab_stream, name, strlen (name) + 1);
-
-  /* Initialize the section header.  */
-  file->scn->strtab_offs = sh_name;
-}
-
-
-/* Begin a new COFF section named NAME in the current output file.  */
-
-void
-lto_obj_begin_section (const char *name)
-{
-  lto_coff_begin_section_with_type (name, 0);
-}
-
-
-/* Append DATA of length LEN to the current output section.  BASE is a pointer
-   to the output page containing DATA.  It is freed once the output file has
-   been written.  */
-
-void
-lto_obj_append_data (const void *data, size_t len, void *block)
-{
-  lto_coff_file *file;
-  lto_coff_data *coff_data;
-  struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block;
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_coff_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  coff_data = coff_newdata (file->scn);
-  if (!coff_data)
-    fatal_error ("could not append data to COFF section: %m");
-
-  coff_data->d_buf = CONST_CAST (void *, data);
-  coff_data->d_size = len;
-
-  /* Chain all data blocks (from all sections) on one singly-linked
-     list for freeing en masse after the file is closed.  */
-  base->ptr = (char *)file->data;
-  file->data = base;
-}
-
-
-/* End the current output section.  This just does some assertion checking
-   and sets the current output file's scn member to NULL.  */
-
-void
-lto_obj_end_section (void)
-{
-  lto_coff_file *file;
-
-  /* Grab the current output file and validate some basic assertions.  */
-  file = (lto_coff_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  file->scn = NULL;
-}
-
-
-/* Validate's COFF_FILE's executable header and, if cached_coff_hdr is
-   uninitialized, caches the results.  Also records the section header string
-   table's section index.  Returns true on success or false on failure.  */
-
-static bool
-validate_file (lto_coff_file *coff_file)
-{
-  size_t n, secnum;
-  unsigned int numsections, secheaderssize, numsyms;
-  off_t sectionsstart, symbolsstart, stringsstart;
-  unsigned int mach, charact;
-
-  /* Read and sanity check the raw header.  */
-  n = read (coff_file->fd, &coff_file->coffhdr, sizeof (coff_file->coffhdr));
-  if (n != sizeof (coff_file->coffhdr))
-    {
-      error ("not a COFF object file");
-      return false;
-    }
-
-  mach = COFF_GET(&coff_file->coffhdr, Machine);
-  for (n = 0; n < NUM_COFF_KNOWN_MACHINES; n++)
-    if (mach == coff_machine_array[n])
-      break;
-  if (n == NUM_COFF_KNOWN_MACHINES)
-    {
-      error ("not a recognized COFF object file");
-      return false;
-    }
-
-  charact = COFF_GET(&coff_file->coffhdr, Characteristics);
-  if (COFF_NOT_CHARACTERISTICS & charact)
-    {
-      /* DLL, EXE or SYS file.  */
-      error ("not a relocatable COFF object file");
-      return false;
-    }
-
-  if (mach != IMAGE_FILE_MACHINE_AMD64
-      && COFF_CHARACTERISTICS != (COFF_CHARACTERISTICS & charact))
-    {
-      /* ECOFF/XCOFF support not implemented.  */
-      error ("not a 32-bit COFF object file");
-      return false;
-    }
-
-  /* It validated OK, so cached it if we don't already have one.  */
-  if (!cached_coff_hdr_valid)
-    {
-      cached_coff_hdr_valid = true;
-      memcpy (&cached_coff_hdr, &coff_file->coffhdr, sizeof (cached_coff_hdr));
-    }
-
-  if (mach != COFF_GET(&cached_coff_hdr, Machine))
-    {
-      error ("inconsistent file architecture detected");
-      return false;
-    }
-
-  /* Read section headers and string table? */
-
-  numsections = COFF_GET(&coff_file->coffhdr, NumberOfSections);
-  secheaderssize = numsections * sizeof (Coff_section);
-  sectionsstart = sizeof (Coff_header) + secheaderssize;
-  symbolsstart = COFF_GET(&coff_file->coffhdr, PointerToSymbolTable);
-  numsyms = COFF_GET(&coff_file->coffhdr, NumberOfSymbols);
-  stringsstart = (symbolsstart + COFF_SYMBOL_SIZE * numsyms);
-
-#define CVOFFSETTTED(x) (coff_file->base.offset + (x))
-
-  if (numsections <= 0 || symbolsstart <= 0 || numsyms <= 0
-	|| (CVOFFSETTTED(sectionsstart) >= coff_file->file_size)
-	|| (CVOFFSETTTED(symbolsstart) >= coff_file->file_size)
-	|| (CVOFFSETTTED(stringsstart) >= coff_file->file_size))
-    {
-      error ("not a valid COFF object file");
-      return false;
-    }
-
-#undef CVOFFSETTTED
-
-  /* Record start of string table.  */
-  coff_file->strtab_offs = stringsstart;
-
-  /* Validate section table entries.  */
-  for (secnum = 0; secnum < numsections; secnum++)
-    {
-      Coff_section coffsec;
-      lto_coff_section *ltosec;
-      off_t size_raw, offs_raw, offs_relocs, offs_lines;
-      off_t num_relocs, num_lines;
-
-      n = read (coff_file->fd, &coffsec, sizeof (coffsec));
-      if (n != sizeof (coffsec))
-	{
-	  error ("short/missing COFF section table");
-	  return false;
-	}
-
-      size_raw = COFF_GET(&coffsec, SizeOfRawData);
-      offs_raw = COFF_GET(&coffsec, PointerToRawData);
-      offs_relocs = COFF_GET(&coffsec, PointerToRelocations);
-      offs_lines = COFF_GET(&coffsec, PointerToLinenumbers);
-      num_relocs = COFF_GET(&coffsec, NumberOfRelocations);
-      num_lines = COFF_GET(&coffsec, NumberOfLinenumbers);
-
-      if (size_raw < 0 || num_relocs < 0 || num_lines < 0
-	|| (size_raw
-	  && ((COFF_GET(&coffsec, Characteristics)
-	      & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
-	    ? (offs_raw != 0)
-	    : (offs_raw < sectionsstart || offs_raw >= coff_file->file_size)))
-	|| (num_relocs
-	  && (offs_relocs < sectionsstart
-	    || offs_relocs >= coff_file->file_size))
-	|| (num_lines
-	  && (offs_lines < sectionsstart
-	    || offs_lines >= coff_file->file_size)))
-	{
-	  error ("invalid COFF section table");
-	  return false;
-	}
-
-      /* Looks ok, so record its details.  We don't read the 
-         string table or set up names yet; we'll do that when
-	 we build the hash table.  */
-      ltosec = coff_newsection (coff_file, NULL, 0);
-      memcpy (&ltosec->coffsec, &coffsec, sizeof (ltosec->coffsec));
-    }
-
-  return true;
-}
-
-/* Initialize COFF_FILE's executable header using cached data from previously
-   read files.  */
-
-static void
-init_coffhdr (lto_coff_file *coff_file)
-{
-  gcc_assert (cached_coff_hdr_valid);
-  memset (&coff_file->coffhdr, 0, sizeof (coff_file->coffhdr));
-  COFF_PUT(&coff_file->coffhdr, Machine, COFF_GET(&cached_coff_hdr, Machine));
-  COFF_PUT(&coff_file->coffhdr, Characteristics, COFF_GET(&cached_coff_hdr, Characteristics));
-}
-
-/* Open COFF file FILENAME.  If WRITABLE is true, the file is opened for write
-   and, if necessary, created.  Otherwise, the file is opened for reading.
-   Returns the opened file.  */
-
-lto_file *
-lto_obj_file_open (const char *filename, bool writable)
-{
-  lto_coff_file *coff_file;
-  lto_file *result = NULL;
-  off_t offset;
-  const char *offset_p;
-  char *fname;
-  struct stat statbuf;
-
-  offset_p = strchr (filename, '@');
-  if (!offset_p)
-    {
-      fname = xstrdup (filename);
-      offset = 0;
-    }
-  else
-    {
-      /* The file started with '@' is a file containing command line
-	 options.  Stop if it doesn't exist.  */
-      if (offset_p == filename)
-	fatal_error ("command line option file '%s' does not exist",
-		     filename);
-
-      fname = (char *) xmalloc (offset_p - filename + 1);
-      memcpy (fname, filename, offset_p - filename);
-      fname[offset_p - filename] = '\0';
-      offset_p += 3; /* skip the @0x */
-      offset = lto_parse_hex (offset_p);
-    }
-
-  /* Set up.  */
-  coff_file = XCNEW (lto_coff_file);
-  result = (lto_file *) coff_file;
-  lto_file_init (result, fname, offset);
-  coff_file->fd = -1;
-
-  /* Open the file.  */
-  coff_file->fd = open (fname,
-    O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666);
-
-  if (coff_file->fd == -1)
-    {
-      error ("could not open file %s", fname);
-      goto fail;
-    }
-
-  if (stat (fname, &statbuf) < 0)
-    {
-      error ("could not stat file %s", fname);
-      goto fail;
-    }
-
-  coff_file->file_size = statbuf.st_size;
-
-  if (offset != 0)
-    {
-      char ar_tail[12];
-      int size;
-
-      /* Surely not?  */
-      gcc_assert (!writable);
-
-      /* Seek to offset, or error.  */
-      if (lseek (coff_file->fd, offset, SEEK_SET) != (ssize_t) offset)
-	{
-	  error ("could not find archive member @0x%lx", (long) offset);
-	  goto fail;
-	}
-
-      /* Now seek back 12 chars and read the tail of the AR header to
-         find the length of the member file.  */
-      if (lseek (coff_file->fd, -12, SEEK_CUR) < 0
-	  || read (coff_file->fd, ar_tail, 12) != 12
-	  || lseek (coff_file->fd, 0, SEEK_CUR) != (ssize_t) offset
-	  || ar_tail[10] != '`' || ar_tail[11] != '\n')
-	{
-	  error ("could not find archive header @0x%lx", (long) offset);
-	  goto fail;
-	}
-
-      ar_tail[11] = 0;
-      if (sscanf (ar_tail, "%d", &size) != 1)
-	{
-	  error ("invalid archive header @0x%lx", (long) offset);
-	  goto fail;
-	}
-      coff_file->file_size = size;
-    }
-
-  if (writable)
-    {
-      init_coffhdr (coff_file);
-      coff_file->shstrtab_stream = XCNEW (struct lto_output_stream);
-    }
-  else
-    if (!validate_file (coff_file))
-      goto fail;
-
-  return result;
-
- fail:
-  if (result)
-    lto_obj_file_close (result);
-  return NULL;
-}
-
-
-/* Close COFF file FILE and clean up any associated data structures.  If FILE
-   was opened for writing, the file's COFF data is written at this time, and
-   any cached data buffers are freed.  Return TRUE if there was an error.  */
-
-static bool
-coff_write_object_file (lto_coff_file *coff_file)
-{
-  lto_coff_section *cursec, *stringsec;
-  lto_coff_data *data;
-  size_t fileoffset, numsections, totalsecsize, numsyms, stringssize;
-  bool write_err = false;
-  int secnum;
-
-  /* Infer whether this file was opened for reading or writing from the
-     presence or absense of an initialised stream for the string table;
-     do nothing if it was opened for reading.  */
-  if (!coff_file->shstrtab_stream)
-    return false;
-  else
-    {
-      /* Write the COFF string table into a dummy new section that
-	 we will not write a header for.  */
-      lto_file *old_file = lto_set_current_out_file (&coff_file->base);
-      /* This recursively feeds in the data to a new section.  */
-      lto_coff_begin_section_with_type (".strtab", 1);
-      lto_write_stream (coff_file->shstrtab_stream);
-      lto_obj_end_section ();
-      lto_set_current_out_file (old_file);
-      free (coff_file->shstrtab_stream);
-    }
-
-  /* Layout the file.  Count sections (not dummy string section) and calculate
-     data size for all of them.  */
-  numsections = 0;
-  totalsecsize = 0;
-  stringssize = 0;
-  stringsec = NULL;
-  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
-    {
-      lto_coff_data *data;
-      size_t cursecsize;
-      cursecsize = 0;
-      COFF_FOR_ALL_DATA(cursec,data)
-	cursecsize += data->d_size;
-      if (cursec->type == 0)
-	{
-	  ++numsections;
-	  totalsecsize += COFF_ALIGN(cursecsize);
-#if COFF_ALIGNMENT > 1
-	  cursec->pad_needed = COFF_ALIGN(cursecsize) - cursecsize;
-#endif
-	}
-      else
-        {
-	  stringssize = cursecsize;
-	  stringsec = cursec;
-	}
-      COFF_PUT(&cursec->coffsec, SizeOfRawData, cursecsize);
-    }
-
-  /* There is a file symbol and a section symbol per section,
-     and each of these has a single auxiliary symbol following.  */
-  numsyms = 2 * (1 + numsections);
-
-  /* Great!  Now we have enough info to fill out the file header.  */
-  COFF_PUT(&coff_file->coffhdr, NumberOfSections, numsections);
-  COFF_PUT(&coff_file->coffhdr, NumberOfSymbols, numsyms);
-  COFF_PUT(&coff_file->coffhdr, PointerToSymbolTable, sizeof (Coff_header)
-		+ numsections * sizeof (Coff_section) + totalsecsize);
-  /* The remaining members were initialised to zero or copied from
-     a cached header, so we leave them alone here.  */
-
-  /* Now position all the sections, and fill out their headers.  */
-  fileoffset = sizeof (Coff_header) + numsections * sizeof (Coff_section);
-  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
-    {
-      /* Skip dummy string section.  */
-      if (cursec->type == 1)
-	continue;
-      COFF_PUT(&cursec->coffsec, PointerToRawData, fileoffset);
-      fileoffset += COFF_ALIGN (COFF_GET(&cursec->coffsec, SizeOfRawData));
-      COFF_PUT(&cursec->coffsec, Characteristics, COFF_SECTION_CHARACTERISTICS);
-      snprintf ((char *)&cursec->coffsec.Name[0], 8, "/%d", cursec->strtab_offs + 4);
-    }
-
-  /* We can write the data now.  As there's no way to indicate an error return
-     from this hook, error handling is limited to not wasting our time doing
-     any more writes in the event that any one fails.  */
-
-  /* Write the COFF header.  */
-  write_err = (write (coff_file->fd, &coff_file->coffhdr,
-		sizeof (coff_file->coffhdr)) != sizeof (coff_file->coffhdr));
-
-  /* Write the COFF section headers.  */
-  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
-    if (cursec->type == 1)	/* Skip dummy string section.  */
-	continue;
-    else if (!write_err)
-      write_err = (write (coff_file->fd, &cursec->coffsec,
-		sizeof (cursec->coffsec)) != sizeof (cursec->coffsec));
-    else
-      break;
-
-  /* Write the COFF sections.  */
-  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
-    {
-#if COFF_ALIGNMENT > 1
-      static const char padzeros[COFF_ALIGNMENT] = { 0 };
-#endif
-      /* Skip dummy string section.  */
-      if (cursec->type == 1)
-	continue;
-      COFF_FOR_ALL_DATA(cursec, data)
-	if (!write_err)
-	  write_err = (write (coff_file->fd, data->d_buf, data->d_size)
-		!= data->d_size);
-	else
-	  break;
-#if COFF_ALIGNMENT > 1
-      if (!write_err && cursec->pad_needed)
-	write_err = (write (coff_file->fd, padzeros, cursec->pad_needed)
-		!= cursec->pad_needed);
-#endif
-    }
-
-  /* Write the COFF symbol table.  */
-  if (!write_err)
-    {
-      union
-	{
-	  Coff_symbol sym;
-	  Coff_aux_sym_file file;
-	  Coff_aux_sym_section sec;
-	} symbols[2];
-      memset (&symbols[0], 0, sizeof (symbols));
-      strcpy ((char *) &symbols[0].sym.Name[0], ".file");
-      COFF_PUT(&symbols[0].sym, SectionNumber, IMAGE_SYM_DEBUG);
-      COFF_PUT(&symbols[0].sym, Type, IMAGE_SYM_TYPE);
-      symbols[0].sym.StorageClass[0] = IMAGE_SYM_CLASS_FILE;
-      symbols[0].sym.NumberOfAuxSymbols[0] = 1;
-      snprintf ((char *)symbols[1].file.FileName,
-		sizeof (symbols[1].file.FileName),
-		"%s", lbasename (coff_file->base.filename));
-      write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
-		!= (2 * COFF_SYMBOL_SIZE));
-
-      /* Set up constant parts for section sym loop.  */
-      memset (&symbols[0], 0, sizeof (symbols));
-      COFF_PUT(&symbols[0].sym, Type, IMAGE_SYM_TYPE);
-      symbols[0].sym.StorageClass[0] = IMAGE_SYM_CLASS_STATIC;
-      symbols[0].sym.NumberOfAuxSymbols[0] = 1;
-
-      secnum = 1;
-      if (!write_err)
-	COFF_FOR_ALL_SECTIONS(coff_file, cursec)
-	  {
-	    /* Skip dummy string section.  */
-	    if (cursec->type == 1)
-	      continue;
-	    /* Reuse section name string for section symbol name.  */
-	    COFF_PUT_NDXSZ(&symbols[0].sym, Name, 0, 0, 4);
-	    COFF_PUT_NDXSZ(&symbols[0].sym, Name, cursec->strtab_offs + 4, 4, 4);
-	    COFF_PUT(&symbols[0].sym, SectionNumber, secnum++);
-	    COFF_PUT(&symbols[1].sec, Length,
-			COFF_GET(&cursec->coffsec, SizeOfRawData));
-	    if (!write_err)
-	      write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
-			!= (2 * COFF_SYMBOL_SIZE));
-	    else
-	      break;
-	  }
-    }
-
-  /* Write the COFF string table.  */
-  if (!write_err)
-    {
-      unsigned char outlen[4];
-      COFF_PUT4(outlen, stringssize + 4);
-      if (!write_err)
-	write_err = (write (coff_file->fd, outlen, 4) != 4);
-      if (stringsec)
-	{
-	  COFF_FOR_ALL_DATA(stringsec, data)
-	    if (!write_err)
-	      write_err = (write (coff_file->fd, data->d_buf, data->d_size)
-			   != data->d_size);
-	    else
-	      break;
-	}
-    }
-
-  return write_err;
-}
-
-/* Close COFF file FILE and clean up any associated data structures.  If FILE
-   was opened for writing, the file's COFF data is written at this time, and
-   any cached data buffers are freed.  */
-
-void
-lto_obj_file_close (lto_file *file)
-{
-  lto_coff_file *coff_file = (lto_coff_file *) file;
-  struct lto_char_ptr_base *cur, *tmp;
-  lto_coff_section *cursec, *nextsec;
-  bool write_err = false;
-
-  /* Write the COFF string table into a dummy new section that
-     we will not write a header for.  */
-  if (coff_file->shstrtab_stream)
-    coff_write_object_file (coff_file);
-
-  /* Close the file, we're done.  */
-  if (coff_file->fd != -1)
-    close (coff_file->fd);
-
-  /* Free any data buffers.  */
-  cur = coff_file->data;
-  while (cur)
-    {
-      tmp = cur;
-      cur = (struct lto_char_ptr_base *) cur->ptr;
-      free (tmp);
-    }
-
-  /* Free any sections and their data chains.  */
-  cursec = coff_file->section_chain;
-  while (cursec)
-    {
-      lto_coff_data *curdata, *nextdata;
-      nextsec = cursec->next;
-      curdata = cursec->data_chain;
-      while (curdata)
-	{
-	  nextdata = curdata->next;
-	  free (curdata);
-	  curdata = nextdata;
-	}
-      free (cursec);
-      cursec = nextsec;
-    }
-
-  free (file);
-
-  /* If there was an error, mention it.  */
-  if (write_err)
-    error ("I/O error writing COFF output file");
-}
-
Index: gcc/lto/lto-coff.h
===================================================================
--- gcc/lto/lto-coff.h	(revision 166002)
+++ gcc/lto/lto-coff.h	(working copy)
@@ -1,408 +0,0 @@
-/* LTO routines for COFF object files.
-   Copyright 2009 Free Software Foundation, Inc.
-   Contributed by Dave Korn.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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 GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#ifndef LTO_COFF_H
-#define LTO_COFF_H
-
-/* Rather than implementing a libcoff to match libelf, or attempting to
-   integrate libbfd into GCC, this file is a self-contained (and very
-   minimal) COFF format object file reader/writer.  The generated files
-   will contain a COFF header, a number of COFF section headers, the 
-   section data itself, and a trailing string table for section names.  */
-
-/* Alignment of sections in a COFF object file.
-
-   The LTO writer uses zlib compression on the data that it streams into
-   LTO sections in the output object file.  Because these streams don't
-   have any embedded size information, the section in the object file must
-   be exactly sized to the data emitted; any trailing padding bytes will
-   be interpreted as partial and/or corrupt compressed data.
-
-   This is easy enough to do on COFF targets (with binutils 2.20.1 or
-   above) because we can specify 1-byte alignment for the LTO sections.
-   They are then emitted precisely-sized and byte-packed into the object
-   and the reader is happy when it parses them later.  This is currently
-   implemented in the x86/windows backed in i386_pe_asm_named_section()
-   in config/i386/winnt.c by detecting the LTO section name prefix, 
-
-   That would be sufficient, but for one thing.  At the start of the LTO
-   data is a header struct with (currently) a couple of version numbers and
-   some type info; see struct lto_header in lto-streamer.h.  If the sections
-   are byte-packed, this header will not necessarily be correctly-aligned
-   when it is read back into memory.
-
-   On x86 targets, which are currently the only LTO-COFF targets, misaligned
-   memory accesses aren't problematic (okay, inefficient, but not worth
-   worrying about two half-word memory reads per section in the context of
-   everything else the compiler has to do at the time!), but RISC targets may
-   fail on trying to access the header struct.  In this case, it will be
-   necessary to enable (preferably in a target-dependent fashion, but a few
-   bytes of padding are hardly an important issue if it comes down to it) the
-   COFF_ALIGNMENT macros below.
-
-   As currently implemented, this will emit padding to the necessary number
-   of bytes after each LTO section.  These bytes will constitute 'gaps' in
-   the object file structure, as they won't be covered by any section header.
-   This hasn't yet been tested, because no such RISC LTO-COFF target yet
-   exists.  If it causes problems further down the toolchain, it will be
-   necessary to adapt the code to emit additional section headers for these
-   padding bytes, but the odds are that it will "just work".
-
-  */
-
-#if 0
-#define COFF_ALIGNMENT	 (4)
-#define COFF_ALIGNMENTM1 (COFF_ALIGNMENT - 1)
-#define COFF_ALIGN(x)	 (((x) + COFF_ALIGNMENTM1) & ~COFF_ALIGNMENTM1)
-#else
-#define COFF_ALIGNMENT	 (1)
-#define COFF_ALIGN(x)	 (x)
-#endif
-
-/* COFF header machine codes.  */
-
-#define IMAGE_FILE_MACHINE_I386	(0x014c)
-#define IMAGE_FILE_MACHINE_AMD64 (0x8664)
-
-/* Known header magics for validation, as an array initialiser.  */
-
-#define COFF_KNOWN_MACHINES \
-  { IMAGE_FILE_MACHINE_I386, \
-    IMAGE_FILE_MACHINE_AMD64/*, ... add more here when working.  */ }
-
-/* COFF object file header, section and symbol flags and types.  These are
-   currently specific to PE-COFF, which is the only LTO-COFF format at the
-   time of writing.  Maintainers adding support for new COFF formats will
-   need to make these into target macros of some kind.  */
-
-/* COFF header characteristics.  */
-
-#define IMAGE_FILE_EXECUTABLE_IMAGE	(1 << 1)
-#define IMAGE_FILE_32BIT_MACHINE	(1 << 8)
-#define IMAGE_FILE_SYSTEM		(1 << 12)
-#define IMAGE_FILE_DLL			(1 << 13)
-
-/* Desired characteristics (for validation).  */
-
-#define COFF_CHARACTERISTICS \
-  (IMAGE_FILE_32BIT_MACHINE)
-
-/* Unwanted characteristics (for validation).  */
-
-#define COFF_NOT_CHARACTERISTICS \
-  (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL)
-
-/* Section flags.  LTO emits byte-aligned read-only loadable data sections.  */
-
-#define IMAGE_SCN_CNT_INITIALIZED_DATA	 (1 << 6)
-#define IMAGE_SCN_CNT_UNINITIALIZED_DATA (1 << 7)
-#define IMAGE_SCN_ALIGN_1BYTES		 (0x1 << 20)
-#define IMAGE_SCN_MEM_DISCARDABLE	 (1 << 25)
-#define	IMAGE_SCN_MEM_SHARED		 (1 << 28)
-#define IMAGE_SCN_MEM_READ		 (1 << 30)
-
-#define COFF_SECTION_CHARACTERISTICS \
-  (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_1BYTES | \
-  IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ)
-
-/* Symbol-related constants.  */
-
-#define IMAGE_SYM_DEBUG		(-2)
-#define IMAGE_SYM_TYPE_NULL	(0)
-#define IMAGE_SYM_DTYPE_NULL	(0)
-#define IMAGE_SYM_CLASS_STATIC	(3)
-#define IMAGE_SYM_CLASS_FILE	(103)
-
-#define IMAGE_SYM_TYPE \
-  ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL)
-
-/* Size of a COFF symbol in bytes.  */
-
-#define COFF_SYMBOL_SIZE	(18)
-
-/* On-disk file structures.  */
-
-struct Coff_header
-{
-  unsigned char Machine[2];
-  unsigned char NumberOfSections[2];
-  unsigned char TimeDateStamp[4];
-  unsigned char PointerToSymbolTable[4];
-  unsigned char NumberOfSymbols[4];
-  unsigned char SizeOfOptionalHeader[2];
-  unsigned char Characteristics[2];
-};
-typedef struct Coff_header Coff_header;
-
-struct Coff_section
-{
-  unsigned char Name[8];
-  unsigned char VirtualSize[4];
-  unsigned char VirtualAddress[4];
-  unsigned char SizeOfRawData[4];
-  unsigned char PointerToRawData[4];
-  unsigned char PointerToRelocations[4];
-  unsigned char PointerToLinenumbers[4];
-  unsigned char NumberOfRelocations[2];
-  unsigned char NumberOfLinenumbers[2];
-  unsigned char Characteristics[4];
-};
-typedef struct Coff_section Coff_section;
-
-struct Coff_symbol
-{
-  unsigned char Name[8];
-  unsigned char Value[4];
-  unsigned char SectionNumber[2];
-  unsigned char Type[2];
-  unsigned char StorageClass[1];
-  unsigned char NumberOfAuxSymbols[1];
-};
-typedef struct Coff_symbol Coff_symbol;
-
-struct Coff_aux_sym_file
-{
-  unsigned char FileName[18];
-};
-typedef struct Coff_aux_sym_file Coff_aux_sym_file;
-
-struct Coff_aux_sym_section
-{
-  unsigned char Length[4];
-  unsigned char NumberOfRelocations[2];
-  unsigned char NumberOfLineNumbers[2];
-  unsigned char Checksum[4];
-  unsigned char Number[2];
-  unsigned char Selection[1];
-  unsigned char Unused[3];
-};
-typedef struct Coff_aux_sym_section Coff_aux_sym_section;
-
-/* Accessor macros for the above structures.  */
-
-#define COFF_GET(struc,memb) \
-  ((COFFENDIAN ? get_be : get_le) (&(struc)->memb[0], sizeof ((struc)->memb)))
-
-#define COFF_PUT(struc,memb,val) \
-  ((COFFENDIAN ? put_be : put_le) (&(struc)->memb[0], sizeof ((struc)->memb), val))
-
-#define COFF_PUT_NDXSZ(struc,memb,val,ndx,sz) \
-  ((COFFENDIAN ? put_be : put_le) (&(struc)->memb[ndx], sz, val))
-
-/* In-memory file structures.  */
-
-/* Forward declared structs.  */
-
-struct lto_coff_data;
-struct lto_coff_section;
-struct lto_coff_file;
-
-/* Section data in output files is made of these.  */
-
-struct lto_coff_data
-{
-  /* Pointer to data block.  */
-  void *d_buf;
-
-  /* Size of data block.  */
-  ssize_t d_size;
-
-  /* Next data block for this section.  */
-  struct lto_coff_data *next;
-};
-typedef struct lto_coff_data lto_coff_data;
-
-/* This struct tracks the data for a section.  */
-
-struct lto_coff_section
-{
-  /* Singly-linked list of section's data blocks.  */
-  lto_coff_data *data_chain;
-
-  /* Offset in string table of name.  */
-  size_t strtab_offs;
-
-  /* Section type: 0 = real, 1 = dummy.  */
-  size_t type;
-
-  /* Section name.  */
-  const char *name;
-
-#if COFF_ALIGNMENT > 1
-  /* Number of trailing padding bytes needed.  */
-  ssize_t pad_needed;
-#endif
-
-  /* Raw section header data.  */
-  Coff_section coffsec;
-
-  /* Next section for this file.  */
-  struct lto_coff_section *next;
-};
-typedef struct lto_coff_section lto_coff_section;
-
-/* A COFF file.  */
-
-struct lto_coff_file 
-{
-  /* The base information.  */
-  lto_file base;
-
-  /* Common file members:  */
-
-  /* The system file descriptor for the file.  */
-  int fd;
-
-  /* The file's overall header.  */
-  Coff_header coffhdr;
-
-  /* All sections in a singly-linked list.  */
-  lto_coff_section *section_chain;
-
-  /* Readable file members:  */
-
-  /* File total size.  */
-  off_t file_size;
-
-  /* String table file offset, relative to base.offset.  */
-  off_t strtab_offs;
-
-  /* Writable file members:  */
-
-  /* The currently active section.  */
-  lto_coff_section *scn;
-
-  /* The output stream for section header names.  */
-  struct lto_output_stream *shstrtab_stream;
-
-  /* Linked list of data which must be freed *after* the file has been
-     closed.  This is an annoying limitation of libelf.  Which has been
-     faithfully reproduced here.  */
-  struct lto_char_ptr_base *data;
-};
-typedef struct lto_coff_file lto_coff_file;
-
-/* Data hunk iterator.  */
-
-#define COFF_FOR_ALL_DATA(sec,var) \
-  for (var = sec->data_chain; var; var = var->next)
-
-/* Section list iterator.  */
-
-#define COFF_FOR_ALL_SECTIONS(file,var) \
-  for (var = file->section_chain; var; var = var->next)
-
-/* Very simple endian-ness layer.  */
-
-#ifndef COFFENDIAN
-#define COFFENDIAN (BYTES_BIG_ENDIAN)
-#endif
-
-static inline unsigned int
-get_2_le (const unsigned char *ptr)
-{
-  return ptr[0] | (ptr[1] << 8);
-}
-
-static inline unsigned int
-get_4_le (const unsigned char *ptr)
-{
-  return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
-}
-
-static inline unsigned int
-get_2_be (const unsigned char *ptr)
-{
-  return ptr[1] | (ptr[0] << 8);
-}
-
-static inline unsigned int
-get_4_be (const unsigned char *ptr)
-{
-  return ptr[3] | (ptr[2] << 8) | (ptr[1] << 16) | (ptr[0] << 24);
-}
-
-static inline unsigned int
-get_be (const unsigned char *ptr, size_t size)
-{
-  gcc_assert (size == 4 || size == 2);
-  return (size == 2) ? get_2_be (ptr) : get_4_be (ptr);
-}
-
-static inline unsigned int
-get_le (const unsigned char *ptr, size_t size)
-{
-  gcc_assert (size == 4 || size == 2);
-  return (size == 2) ? get_2_le (ptr) : get_4_le (ptr);
-}
-
-static inline void
-put_2_le (unsigned char *ptr, unsigned int data)
-{
-  ptr[0] = data & 0xff;
-  ptr[1] = (data >> 8) & 0xff;
-}
-
-static inline void
-put_4_le (unsigned char *ptr, unsigned int data)
-{
-  ptr[0] = data & 0xff;
-  ptr[1] = (data >> 8) & 0xff;
-  ptr[2] = (data >> 16) & 0xff;
-  ptr[3] = (data >> 24) & 0xff;
-}
-
-static inline void
-put_2_be (unsigned char *ptr, unsigned int data)
-{
-  ptr[1] = data & 0xff;
-  ptr[0] = (data >> 8) & 0xff;
-}
-
-static inline void
-put_4_be (unsigned char *ptr, unsigned int data)
-{
-  ptr[3] = data & 0xff;
-  ptr[2] = (data >> 8) & 0xff;
-  ptr[1] = (data >> 16) & 0xff;
-  ptr[0] = (data >> 24) & 0xff;
-}
-
-static inline void
-put_le (unsigned char *ptr, size_t size, unsigned int data)
-{
-  gcc_assert (size == 4 || size == 2);
-  (void) (size == 2 ? put_2_le : put_4_le) (ptr, data);
-}
-
-static inline void
-put_be (unsigned char *ptr, size_t size, unsigned int data)
-{
-  gcc_assert (size == 4 || size == 2);
-  (void) (size == 2 ? put_2_be : put_4_be) (ptr, data);
-}
-
-/* We use this for putting the string table size.  */
-
-#define COFF_PUT4(ptr, data) \
-  ((COFFENDIAN ? put_4_be : put_4_le) (ptr, data))
-
-
-#endif /* LTO_COFF_H */
Index: gcc/lto/Make-lang.in
===================================================================
--- gcc/lto/Make-lang.in	(revision 166002)
+++ gcc/lto/Make-lang.in	(working copy)
@@ -23,7 +23,7 @@
 # The name of the LTO compiler.
 LTO_EXE = lto1$(exeext)
 # The LTO-specific object files inclued in $(LTO_EXE).
-LTO_OBJS = lto/lto-lang.o lto/lto.o lto/$(LTO_BINARY_READER).o attribs.o
+LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-objfile.o attribs.o
 LTO_H = lto/lto.h $(HASHTAB_H)
 LINKER_PLUGIN_API_H = $(srcdir)/../include/plugin-api.h
 LTO_TREE_H = lto/lto-tree.h $(LINKER_PLUGIN_API_H)
@@ -73,7 +73,7 @@ lto-warn = $(STRICT_WARN)
 
 $(LTO_EXE): $(LTO_OBJS) $(BACKEND) $(LIBDEPS)
 	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
-		$(LTO_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS) $(LTO_USE_LIBELF)
+		$(LTO_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS)
 
 # Dependencies
 lto/lto-lang.o: lto/lto-lang.c $(CONFIG_H) coretypes.h debug.h \
@@ -86,14 +86,9 @@ lto/lto.o: lto/lto.c $(CONFIG_H) $(SYSTE
 	langhooks.h $(VEC_H) $(BITMAP_H) pointer-set.h $(IPA_PROP_H) \
 	$(COMMON_H) debug.h $(TIMEVAR_H) $(GIMPLE_H) $(LTO_H) $(LTO_TREE_H) \
 	$(LTO_TAGS_H) $(LTO_STREAMER_H) $(SPLAY_TREE_H) gt-lto-lto.h $(PARAMS_H)
-lto/lto-elf.o: lto/lto-elf.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
-	toplev.h $(LTO_H) $(TM_H) $(LIBIBERTY_H) $(GGC_H) $(LTO_STREAMER_H)
-lto/lto-coff.o: lto/lto-coff.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
-	toplev.h $(LTO_H) $(TM_H) $(LIBIBERTY_H) $(GGC_H) $(LTO_STREAMER_H) \
-	lto/lto-coff.h
-lto/lto-macho.o: lto/lto-macho.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
-	toplev.h $(LTO_H) $(TM_H) $(LIBIBERTY_H) $(GGC_H) $(LTO_STREAMER_H) \
-	lto/lto-macho.h lto/lto-endian.h
+lto/lto-objfile.o: lto/lto-objfile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+	$(DIAGNOSTIC_CORE_H) $(TOPLEV_H) $(LTO_H) $(TM_H) $(LTO_STREAMER_H) \
+	$(LIBIBERTY_H) $(OBJFILE_H)
 
 # LTO testing is done as part of C/C++/Fortran etc. testing.
 check-lto:
Index: gcc/lto/lto-macho.c
===================================================================
--- gcc/lto/lto-macho.c	(revision 166002)
+++ gcc/lto/lto-macho.c	(working copy)
@@ -1,948 +0,0 @@
-/* LTO routines for Mach-O object files.
-   Copyright 2010 Free Software Foundation, Inc.
-   Contributed by Steven Bosscher.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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 GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "diagnostic-core.h"
-#include "toplev.h"
-#include "lto.h"
-#include "tm.h"
-#include "libiberty.h"
-#include "lto-streamer.h"
-#include "lto/lto-endian.h"
-#include "lto/lto-macho.h"
-
-/* Rather than implementing a libmacho to match libelf, or attempting to
-   integrate libbfd into GCC, this file is a self-contained (and very
-   minimal) Mach-O format object file reader/writer.  The generated files
-   will contain a Mach-O header, a number of Mach-O load commands an
-   section headers, the  section data itself, and a trailing string table
-   for section names.  */
-
-/* This needs to be kept in sync with darwin.c.  Better yet, lto-macho.c
-   and lto-macho.h should be moved to config/, and likewise for lto-coff.*
-   and lto-elf.*.  */
-
-/* Segment name for LTO sections.  */
-#define LTO_SEGMENT_NAME "__GNU_LTO"
-
-/* Section name for LTO section names section.  */
-#define LTO_NAMES_SECTION "__section_names"
-
-/* Handle opening elf files on hosts, such as Windows, that may use 
-   text file handling that will break binary access.  */
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-/* Cached object file header.  We use a header_64 for this, since all
-   the fields we need are in there, in the same position as header_32.  */
-mach_o_header_64 cached_mach_o_header;
-uint32_t cached_mach_o_magic;
-
-/* The current output file.  */
-static lto_file *current_out_file;
-
-
-/* Is this a 32-bits or 64-bits Mach-O object file?  */
-static int
-mach_o_word_size (void)
-{
-  gcc_assert (cached_mach_o_magic != 0);
-  return (cached_mach_o_magic == MACH_O_MH_MAGIC_64
-	  || cached_mach_o_magic == MACH_O_MH_CIGAM_64) ? 64 : 32;
-}
-
-/* Sets the current output file to FILE.  Returns the old output file or
-   NULL.  */
-
-lto_file *
-lto_set_current_out_file (lto_file *file)
-{
-  lto_file *old_file = current_out_file;
-  current_out_file = file;
-  return old_file;
-}
-
-
-/* Returns the current output file.  */
-
-lto_file *
-lto_get_current_out_file (void)
-{
-  return current_out_file;
-}
-
-/* Mach-O section structure constructor.  */
-
-static lto_mach_o_section
-mach_o_new_section (lto_mach_o_file *mach_o_file, const char *name)
-{
-  lto_mach_o_section ptr;
-
-  /* FIXME We could allocate these things on an obstack.  */
-  ptr = XCNEW (struct lto_mach_o_section_d);
-  if (name)
-    {
-      if (strncmp (name, LTO_SECTION_NAME_PREFIX,
-		   strlen(LTO_SECTION_NAME_PREFIX)) != 0)
-	sorry ("not implemented: Mach-O writer for non-LTO sections");
-      ptr->name = xstrdup (name);
-    }
-
-  VEC_safe_push (lto_mach_o_section, heap, mach_o_file->section_vec, ptr);
-
-  return ptr;
-}
-
-/* Mach-O section data block structure constructor.  */
-
-static lto_mach_o_data
-mach_o_new_data (lto_mach_o_section sec)
-{
-  lto_mach_o_data ptr, *chain_ptr_ptr;
-
-  /* FIXME We could allocate these things on an obstack.  */
-  ptr = XCNEW (struct lto_mach_o_data_d);
-
-  chain_ptr_ptr = &sec->data_chain;
-  while (*chain_ptr_ptr)
-    chain_ptr_ptr = &(*chain_ptr_ptr)->next;
-  *chain_ptr_ptr = ptr;
-
-  return ptr;
-}
-
-/* Initialize FILE, an LTO file object for FILENAME.  Offset is the
-   offset into FILE where the object is located (e.g. in an archive).  */
-
-static void
-lto_file_init (lto_file *file, const char *filename, off_t offset)
-{
-  file->filename = filename;
-  file->offset = offset;
-}
-
-/* Build a hash table whose key is the section names and whose data is
-   the start and size of each section in the .o file.  */
-
-htab_t
-lto_obj_build_section_table (lto_file *lto_file) 
-{
-  lto_mach_o_file *mach_o_file = (lto_mach_o_file *)lto_file;
-  lto_mach_o_section sec;
-  htab_t section_hash_table;
-  off_t strtab_offs;
-  ssize_t strtab_size;
-  char *strtab = NULL;
-  int i;
-
-  section_hash_table = lto_obj_create_section_hash_table ();
-
-  /* Seek the string table.  */
-  /* FIXME The segment name should be in darwin.h, but can we include it
-     here in this file?  */
-  for (i = 0;
-       VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    {
-      if (strncmp (sec->u.section.segname, "__GNU_LTO", 16) != 0)
-	continue;
-      if (strncmp (sec->u.section.sectname, "__section_names", 16) == 0)
-        break;
-    }
-  if (! sec)
-    {
-      error ("invalid Mach-O LTO object file: no __section_names section found");
-      goto done;
-    }
-  mach_o_file->section_names_section = sec;
-
-  if (mach_o_word_size () == 64)
-    {
-      strtab_offs = (off_t) get_uint32 (&sec->u.section_64.offset[0]);
-      strtab_size = (size_t) get_uint64 (&sec->u.section_64.size[0]);
-    }
-  else
-    {
-      strtab_offs = (off_t) get_uint32 (&sec->u.section_32.offset[0]);
-      strtab_size = (size_t) get_uint32 (&sec->u.section_32.size[0]);
-    }
-
-  /* Seek to start of string table.  */
-  if (strtab_offs != lseek (mach_o_file->fd,
-			    mach_o_file->base.offset + strtab_offs,
-			    SEEK_SET))
-    {
-      error ("altered or invalid Mach-O object file");
-      goto done;
-    }
-
-  strtab = XNEWVEC (char, strtab_size);
-  if (read (mach_o_file->fd, strtab, strtab_size) != strtab_size)
-    {
-      error ("invalid Mach-O LTO object file __section_names section");
-      goto done;
-    }
-
-  /* Scan sections looking at names.  */
-  for (i = 0;
-       VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    {
-      struct lto_section_slot s_slot;
-      void **slot;
-      char *new_name;
-      unsigned long stringoffset;
-      char name[17];
-
-      /* Ignore non-LTO sections.  Also ignore the __section_names section
-	 which does not need renaming.  */
-      if (strncmp (sec->u.section.segname, "__GNU_LTO", 16) != 0)
-	continue;
-      if (sec == mach_o_file->section_names_section)
-        continue;
-
-      /* Try to extract the offset of the real name for this section from
-	 __section_names.  */
-      memcpy (&name[0], sec->u.section.sectname, 16);
-      name[16] = '\0';
-      if (name[0] != '_' || name[1] != '_'
-	  || sscanf (&name[2], "%08lX", &stringoffset) != 1
-	  || strtab_size < (ssize_t) stringoffset)
-	{
-	  error ("invalid Mach-O LTO section name string: %s", name);
-	  continue;
-	}
-
-      new_name = XNEWVEC (char, strlen (strtab + stringoffset) + 1);
-      strcpy (new_name, strtab + stringoffset);
-      s_slot.name = new_name;
-      slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
-      if (*slot == NULL)
-	{
-	  struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
-
-	  new_slot->name = new_name;
-	  if (mach_o_word_size() == 64)
-	    {
-	      new_slot->start =
-		(intptr_t) get_uint32 (&sec->u.section_64.offset[0]);
-	      new_slot->len =
-		(size_t) get_uint64 (&sec->u.section_64.size[0]);
-	    }
-	  else
-	    {
-	      new_slot->start =
-		(intptr_t) get_uint32 (&sec->u.section_32.offset[0]);
-	      new_slot->len =
-		(size_t) get_uint32 (&sec->u.section_32.size[0]);
-	    }
-
-	  *slot = new_slot;
-	}
-      else
-	{
-	  error ("two or more sections for %s:", new_name);
-	  goto done;
-	}
-    }
-
- done:
-  if (strtab)
-    free (strtab);
-  return section_hash_table;
-}
-
-
-/* Begin a new Mach-O section named NAME in the current output file.  */
-
-void
-lto_obj_begin_section (const char *name)
-{
-  lto_mach_o_file *file;
-
-  if (strncmp (name, LTO_SECTION_NAME_PREFIX,
-	       strlen(LTO_SECTION_NAME_PREFIX)) != 0)
-    sorry ("not implemented: Mach-O writer for non-LTO sections");
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_mach_o_file *) lto_get_current_out_file (),
-  gcc_assert (file && file->writable && !file->scn);
-
-  /* Create a new section.  */
-  file->scn = mach_o_new_section (file, name);
-  if (!file->scn)
-    fatal_error ("could not create a new Mach-O section: %m");
-}
-
-
-/* Append DATA of length LEN to the current output section.  BASE is a pointer
-   to the output page containing DATA.  It is freed once the output file has
-   been written.  */
-
-void
-lto_obj_append_data (const void *data, size_t len, void *block)
-{
-  lto_mach_o_file *file;
-  lto_mach_o_data mach_o_data;
-  struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block;
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_mach_o_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  mach_o_data = mach_o_new_data (file->scn);
-  if (!mach_o_data)
-    fatal_error ("could not append data to Mach-O section: %m");
-
-  mach_o_data->d_buf = CONST_CAST (void *, data);
-  mach_o_data->d_size = len;
-
-  /* Chain all data blocks (from all sections) on one singly-linked
-     list for freeing en masse after the file is closed.  */
-  base->ptr = (char *)file->data;
-  file->data = base;
-}
-
-
-/* End the current output section.  This just does some assertion checking
-   and sets the current output file's scn member to NULL.  */
-
-void
-lto_obj_end_section (void)
-{
-  lto_mach_o_file *file;
-
-  /* Grab the current output file and validate some basic assertions.  */
-  file = (lto_mach_o_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  file->scn = NULL;
-}
-
-
-/* Read a Mach-O header from MACH_O_FILE and validate it.
-   The file descriptor in MACH_O_FILE points at the start of the file.
-   If cached_mach_o_header is uninitialized, caches the results.
-   On succes, returns true and moves file pointer to the start of the
-   load commands.  On failure, returns false.  */
-
-static bool
-validate_mach_o_header (lto_mach_o_file *mach_o_file)
-{
-  ssize_t i, n;
-  unsigned char magic[4];
-  uint32_t cputype;
-  off_t startpos;
-
-  /* Known header magics for validation, as an array.  */
-  static const unsigned int mach_o_known_formats[] = {
-    MACH_O_MH_MAGIC,
-    MACH_O_MH_CIGAM,
-    MACH_O_MH_MAGIC_64,
-    MACH_O_MH_CIGAM_64,
-  };
-#define MACH_O_NUM_KNOWN_FORMATS \
-  ((ssize_t) ARRAY_SIZE (mach_o_known_formats))
-
-  startpos = lseek (mach_o_file->fd, 0, SEEK_CUR);
-  if (read (mach_o_file->fd, &magic, sizeof (magic)) != 4
-      || lseek (mach_o_file->fd, -4, SEEK_CUR) != startpos)
-    {
-      error ("cannot read file %s", mach_o_file->base.filename);
-      return false;
-    }
-
-  for (i = 0; i < MACH_O_NUM_KNOWN_FORMATS; ++i)
-    if (get_uint32 (&magic[0]) == mach_o_known_formats[i])
-      break;
-  if (i == MACH_O_NUM_KNOWN_FORMATS)
-    goto not_for_target;
-
-  /* Check the endian-ness.  */
-  if (BYTES_BIG_ENDIAN && magic[0] != 0xfe)
-    goto not_for_target;
-
-  /* Set or check cached magic number.  */
-  if (cached_mach_o_magic == 0)
-    cached_mach_o_magic = get_uint32 (&magic[0]);
-  else if (cached_mach_o_magic != get_uint32 (&magic[0]))
-    goto not_for_target;
- 
-  n = mach_o_word_size () == 64
-      ? sizeof (mach_o_header_64) : sizeof (mach_o_header_32);
-  if (read (mach_o_file->fd, &mach_o_file->u.header, n) != n)
-    goto not_for_target;
-
-  /* Is this a supported CPU?  */
-  /* ??? Would be nice to validate the exact target architecture.  */
-  cputype = get_uint32 (&mach_o_file->u.header.cputype[0]);
-  if (cputype == MACH_O_CPU_TYPE_I386
-      || cputype == MACH_O_CPU_TYPE_POWERPC)
-    {
-      if (mach_o_word_size () != 32)
-        goto not_for_target;
-    }
-  else if (cputype == MACH_O_CPU_TYPE_X86_64
-	   || cputype == MACH_O_CPU_TYPE_POWERPC_64)
-    {
-      if (mach_o_word_size () != 64)
-        goto not_for_target;
-    }
-
-  /* Is this an MH_OBJECT file?  */
-  if (get_uint32 (&mach_o_file->u.header.filetype[0]) != MACH_O_MH_OBJECT)
-    error ("Mach-O file %s is not an MH_OBJECT file",
-	   mach_o_file->base.filename);
-
-  /* Save the header for future use.  */
-  memcpy (&cached_mach_o_header, &mach_o_file->u.header,
-	  sizeof (cached_mach_o_header));
-
-  return true;
-
- not_for_target:
-  error ("file %s is not a Mach-O object file for target",
-	 mach_o_file->base.filename);
-  return false;
-}
-
-
-/* Read a Mach-O LC_SEGMENT command (32 bits) from MACH_O_FILE and
-   validate it.
-   The file descriptor in MACH_O_FILE points at the start of the load
-   command.  On sucess, returns true and advances the file pointer
-   past the end of the load command.  On failure, returns false.  */
-
-static bool
-validate_mach_o_segment_command_32 (lto_mach_o_file *mach_o_file)
-{
-  mach_o_segment_command_32 seg_cmd_32;
-  unsigned int i;
-  ssize_t n;
-  off_t startpos;
-
-  /* Fields we're interested in.  */
-  uint32_t cmd;
-  uint32_t cmdsize;
-  uint32_t nsects;
-
-  startpos = lseek (mach_o_file->fd, 0, SEEK_CUR);
-
-  n = sizeof (mach_o_segment_command_32);
-  if (read (mach_o_file->fd, (void *) &seg_cmd_32, n) != n)
-    goto fail;
-
-  cmd = get_uint32 (&seg_cmd_32.cmd[0]);
-  cmdsize = get_uint32 (&seg_cmd_32.cmdsize[0]);
-  nsects = get_uint32 (&seg_cmd_32.nsects[0]);
-  gcc_assert (cmd == MACH_O_LC_SEGMENT);
-
-  /* Validate section table entries.  */
-  for (i = 0; i < nsects; i++)
-    {
-      mach_o_section_32 sec_32;
-      lto_mach_o_section ltosec;
-
-      n = sizeof (mach_o_section_32);
-      if (read (mach_o_file->fd, &sec_32, n) != n)
-	goto fail;
-
-      /* ??? Perform some checks.  */
-
-      /* Looks ok, so record its details.  We don't read the 
-         string table or set up names yet; we'll do that when
-	 we build the hash table.  */
-      ltosec = mach_o_new_section (mach_o_file, NULL);
-      memcpy (&ltosec->u.section_32, &sec_32, sizeof (sec_32));
-    }
-
-  if (lseek (mach_o_file->fd, 0, SEEK_CUR) != startpos + cmdsize)
-    goto fail;
-
-  return true;
-
- fail:
-  error ("could not read LC_SEGMENT command in Mach-O file %s",
-	 mach_o_file->base.filename);
-  return false;
-}
-
-
-/* Read a Mach-O LC_SEGMENT_64 command from MACH_O_FILE and validate it.
-   The file descriptor in MACH_O_FILE points at the start of the load
-   command.  On sucess, returns true and advances the file pointer
-   past the end of the load command.  On failure, returns false.  */
-
-static bool
-validate_mach_o_segment_command_64 (lto_mach_o_file *mach_o_file)
-{
-  mach_o_segment_command_64 seg_cmd_64;
-  unsigned int i;
-  ssize_t n;
-  off_t startpos;
-
-  /* Fields we're interested in.  */
-  uint32_t cmd;
-  uint32_t cmdsize;
-  uint32_t nsects;
-
-  startpos = lseek (mach_o_file->fd, 0, SEEK_CUR);
-
-  n = sizeof (mach_o_segment_command_64);
-  if (read (mach_o_file->fd, (void *) &seg_cmd_64, n) != n)
-    goto fail;
-
-  cmd = get_uint32 (&seg_cmd_64.cmd[0]);
-  cmdsize = get_uint32 (&seg_cmd_64.cmdsize[0]);
-  nsects = get_uint32 (&seg_cmd_64.nsects[0]);
-  gcc_assert (cmd == MACH_O_LC_SEGMENT_64);
-
-  /* Validate section table entries.  */
-  for (i = 0; i < nsects; i++)
-    {
-      mach_o_section_64 sec_64;
-      lto_mach_o_section ltosec;
-
-      n = sizeof (mach_o_section_64);
-      if (read (mach_o_file->fd, &sec_64, n) != n)
-	goto fail;
-
-      /* ??? Perform some checks.  */
-
-      /* Looks ok, so record its details.  We don't read the 
-         string table or set up names yet; we'll do that when
-	 we build the hash table.  */
-      ltosec = mach_o_new_section (mach_o_file, NULL);
-      memcpy (&ltosec->u.section_64, &sec_64, sizeof (sec_64));
-    }
-
-  if (lseek (mach_o_file->fd, 0, SEEK_CUR) != startpos + cmdsize)
-    goto fail;
-
-  return true;
-
- fail:
-  error ("could not read LC_SEGMENT_64 command in Mach-O file %s",
-	 mach_o_file->base.filename);
-  return false;
-}
-
-/* Read a Mach-O load commands from MACH_O_FILE and validate it.
-   The file descriptor in MACH_O_FILE points at the start of the load
-   command.  On sucess, returns true and advances the file pointer
-   past the end of the load command.  On failure, returns false.  */
-
-static bool
-validate_mach_o_load_command (lto_mach_o_file *mach_o_file)
-{
-  mach_o_load_command load_command;
-  uint32_t cmd;
-  uint32_t cmdsize;
-  ssize_t n;
-
-  n = sizeof (load_command);
-  if (read (mach_o_file->fd, &load_command, n) != n)
-    {
-      error ("could not read load commands in Mach-O file %s",
-	     mach_o_file->base.filename);
-      return false;
-    }
-  lseek (mach_o_file->fd, -1 * (off_t) sizeof (load_command), SEEK_CUR);
-
-  cmd = get_uint32 (&load_command.cmd[0]);
-  cmdsize = get_uint32 (&load_command.cmdsize[0]);
-  switch (cmd)
-    {
-    case MACH_O_LC_SEGMENT:
-      return validate_mach_o_segment_command_32 (mach_o_file);
-    case MACH_O_LC_SEGMENT_64:
-      return validate_mach_o_segment_command_64 (mach_o_file);
-
-    default:
-      /* Just skip over it.  */
-      lseek (mach_o_file->fd, cmdsize, SEEK_CUR);
-      return true;
-    }
-}
-
-/* Validate's MACH_O_FILE's executable header and, if cached_mach_o_header is
-   uninitialized, caches the results.  Also records the section header string
-   table's section index.  Returns true on success, false on failure.  */
-
-static bool
-validate_file (lto_mach_o_file *mach_o_file)
-{
-  uint32_t i, ncmds;
-
-  /* Read and sanity check the raw header.  */
-  if (! validate_mach_o_header (mach_o_file))
-    return false;
-
-  ncmds = get_uint32 (&mach_o_file->u.header.ncmds[0]);
-  for (i = 0; i < ncmds; ++i)
-    if (! validate_mach_o_load_command (mach_o_file))
-      return false;
-
-  return true;
-}
-
-/* Initialize MACH_O_FILE's executable header using cached data from previously
-   read files.  */
-
-static void
-init_mach_o_header (lto_mach_o_file *mach_o_file)
-{
-  gcc_assert (cached_mach_o_magic != 0);
-  memcpy (&mach_o_file->u.header,
-	  &cached_mach_o_header,
-	  sizeof (mach_o_file->u.header));
-  put_uint32 (&mach_o_file->u.header.ncmds[0], 0);
-  put_uint32 (&mach_o_file->u.header.sizeofcmds[0], 0);
-}
-
-/* Open Mach-O file FILENAME.  If WRITABLE is true, the file is opened for write
-   and, if necessary, created.  Otherwise, the file is opened for reading.
-   Returns the opened file.  */
-
-lto_file *
-lto_obj_file_open (const char *filename, bool writable)
-{
-  lto_mach_o_file *mach_o_file;
-  lto_file *result = NULL;
-  off_t offset;
-  const char *offset_p;
-  char *fname;
-  struct stat statbuf;
-
-  offset_p = strchr (filename, '@');
-  if (!offset_p)
-    {
-      fname = xstrdup (filename);
-      offset = 0;
-    }
-  else
-    {
-      /* The file started with '@' is a file containing command line
-	 options.  Stop if it doesn't exist.  */
-      if (offset_p == filename)
-	fatal_error ("command line option file '%s' does not exist",
-		     filename);
-
-      fname = (char *) xmalloc (offset_p - filename + 1);
-      memcpy (fname, filename, offset_p - filename);
-      fname[offset_p - filename] = '\0';
-      offset_p += 3; /* skip the @0x */
-      offset = lto_parse_hex (offset_p);
-    }
-
-  /* Set up.  */
-  mach_o_file = XCNEW (lto_mach_o_file);
-  result = (lto_file *) mach_o_file;
-  lto_file_init (result, fname, offset);
-  mach_o_file->fd = -1;
-  mach_o_file->writable = writable;
-
-  /* Open the file.  */
-  mach_o_file->fd = open (fname,
-    O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666);
-
-  if (mach_o_file->fd == -1)
-    {
-      error ("could not open file %s", fname);
-      goto fail;
-    }
-
-  if (stat (fname, &statbuf) < 0)
-    {
-      error ("could not stat file %s", fname);
-      goto fail;
-    }
-
-  mach_o_file->file_size = statbuf.st_size;
-
-  /* If the object is in an archive, get it out.  */
-  if (offset != 0)
-    {
-      char ar_tail[12];
-      int size;
-
-      /* Surely not?  */
-      gcc_assert (!writable);
-
-      /* Seek to offset, or error.  */
-      if (lseek (mach_o_file->fd, offset, SEEK_SET) != (ssize_t) offset)
-	{
-	  error ("could not find archive member @0x%lx", (long) offset);
-	  goto fail;
-	}
-
-      /* Now seek back 12 chars and read the tail of the AR header to
-         find the length of the member file.  */
-      if (lseek (mach_o_file->fd, -12, SEEK_CUR) < 0
-	  || read (mach_o_file->fd, ar_tail, 12) != 12
-	  || lseek (mach_o_file->fd, 0, SEEK_CUR) != (ssize_t) offset
-	  || ar_tail[10] != '`' || ar_tail[11] != '\n')
-	{
-	  error ("could not find archive header @0x%lx", (long) offset);
-	  goto fail;
-	}
-
-      ar_tail[11] = 0;
-      if (sscanf (ar_tail, "%d", &size) != 1)
-	{
-	  error ("invalid archive header @0x%lx", (long) offset);
-	  goto fail;
-	}
-      mach_o_file->file_size = size;
-    }
-
-  if (writable)
-    {
-      init_mach_o_header (mach_o_file);
-    }
-  else
-    if (! validate_file (mach_o_file))
-      goto fail;
-
-  return result;
-
- fail:
-  if (result)
-    lto_obj_file_close (result);
-  return NULL;
-}
-
-
-/* Write the data in MACH_O_FILE to a real Mach-O binary object.
-   We write a header, a segment load command, and section data.  */
-
-static bool
-mach_o_write_object_file (lto_mach_o_file *mach_o_file)
-{
-  lto_mach_o_section sec, snsec;
-  lto_mach_o_data snsec_data;
-  ssize_t hdrsize, cmdsize, secsize;
-  size_t num_sections, snsec_size, total_sec_size;
-  unsigned int sec_offs, strtab_offs;
-  int i;
-  bool write_err = false;
-
-  /* The number of sections we will write is the number of sections added by
-     the streamer, plus 1 for the section names section.  */
-  num_sections = VEC_length (lto_mach_o_section, mach_o_file->section_vec) + 1;
-
-  /* Calculate the size of the basic data structures on disk.  */
-  if (mach_o_word_size () == 64)
-    {
-      hdrsize = sizeof (mach_o_header_64);
-      secsize = sizeof (mach_o_section_64);
-      cmdsize = sizeof (mach_o_segment_command_64) + num_sections * secsize;
-    }
-  else
-    {
-      hdrsize = sizeof (mach_o_header_32);
-      secsize = sizeof (mach_o_section_32);
-      cmdsize = sizeof (mach_o_segment_command_32) + num_sections * secsize;
-    }
- 
-  /* Allocate the section names section.  */
-  snsec_size = 0;
-  for (i = 0;
-       VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    snsec_size += strlen (sec->name) + 1;
-  snsec = mach_o_new_section (mach_o_file, NULL);
-  snsec->name = LTO_NAMES_SECTION;
-  snsec_data = mach_o_new_data (snsec);
-  snsec_data->d_buf = XCNEWVEC (char, snsec_size);
-  snsec_data->d_size = snsec_size;
-
-  /* Position all the sections, and fill out their headers.  */
-  sec_offs = hdrsize + cmdsize;
-  strtab_offs = 0;
-  total_sec_size = 0;
-  for (i = 0;
-       VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    {
-      lto_mach_o_data data;
-      size_t data_size;
-      /* Put the section and segment names.  Add the section name to the
-         section names section (unless, of course, this *is* the section
-	 names section).  */
-      if (sec == snsec)
-	snprintf (sec->u.section.sectname, 16, "%s", LTO_NAMES_SECTION);
-      else
-	{
-	  sprintf (sec->u.section.sectname, "__%08X", strtab_offs);
-	  memcpy ((char *) snsec_data->d_buf + strtab_offs, sec->name, strlen (sec->name));
-	}
-      memcpy (&sec->u.section.segname[0],
-	      LTO_SEGMENT_NAME, strlen (LTO_SEGMENT_NAME));
-
-      /* Add layout and attributes.  */
-      for (data = sec->data_chain, data_size = 0; data; data = data->next)
-	data_size += data->d_size;
-      if (mach_o_word_size () == 64)
-	{
-	  put_uint64 (&sec->u.section_64.addr[0], total_sec_size); 
-	  put_uint64 (&sec->u.section_64.size[0], data_size); 
-	  put_uint32 (&sec->u.section_64.offset[0], sec_offs); 
-	  put_uint32 (&sec->u.section_64.flags[0], MACH_O_S_ATTR_DEBUG);
-	}
-      else
-	{
-	  put_uint32 (&sec->u.section_64.addr[0], total_sec_size); 
-	  put_uint32 (&sec->u.section_32.size[0], data_size); 
-	  put_uint32 (&sec->u.section_32.offset[0], sec_offs); 
-	  put_uint32 (&sec->u.section_32.flags[0], MACH_O_S_ATTR_DEBUG);
-	}
-
-      sec_offs += data_size;
-      total_sec_size += data_size;
-      strtab_offs += strlen (sec->name) + 1;
-    }
-
-  /* We can write the data now.  As there's no way to indicate an error return
-     from this hook, error handling is limited to not wasting our time doing
-     any more writes in the event that any one fails.  */
-
-  /* Write the header.  */
-  put_uint32 (&mach_o_file->u.header.ncmds[0], 1);
-  put_uint32 (&mach_o_file->u.header.sizeofcmds[0], cmdsize);
-  write_err = (write (mach_o_file->fd,
-		      &mach_o_file->u.header, hdrsize) != hdrsize);
-  /* Write the segment load command.  */
-  if (mach_o_word_size () == 64)
-    {
-      mach_o_segment_command_64 lc;
-      ssize_t lc_size = sizeof (lc);
-      memset (&lc, 0, lc_size);
-      put_uint32 (&lc.cmd[0], MACH_O_LC_SEGMENT_64);
-      put_uint32 (&lc.cmdsize[0], cmdsize);
-      put_uint64 (&lc.fileoff[0], hdrsize + cmdsize);
-      put_uint64 (&lc.filesize[0], total_sec_size);
-      put_uint32 (&lc.nsects[0], num_sections);
-      write_err = (write (mach_o_file->fd, &lc, lc_size) != lc_size);
-    }
-  else
-    {
-      mach_o_segment_command_32 lc;
-      ssize_t lc_size = sizeof (lc);
-      memset (&lc, 0, lc_size);
-      put_uint32 (&lc.cmd[0], MACH_O_LC_SEGMENT);
-      put_uint32 (&lc.cmdsize[0], cmdsize);
-      put_uint32 (&lc.fileoff[0], hdrsize + cmdsize);
-      put_uint32 (&lc.filesize[0], total_sec_size);
-      put_uint32 (&lc.nsects[0], num_sections);
-      write_err = (write (mach_o_file->fd, &lc, lc_size) != lc_size);
-    }
-  for (i = 0;
-       !write_err
-       && VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    write_err = (write (mach_o_file->fd,
-			&sec->u.section, secsize) != secsize);
-
-  gcc_assert (lseek (mach_o_file->fd, 0, SEEK_CUR) == hdrsize + cmdsize);
-
-  /* Write the section data.  */
-  for (i = 0;
-       !write_err
-       && VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    {
-      lto_mach_o_data data;
-
-      for (data = sec->data_chain; data; data = data->next)
-	{
-	  if (!write_err)
-	    write_err = (write (mach_o_file->fd, data->d_buf, data->d_size)
-			 != data->d_size);
-	  else
-	    break;
-	}
-    }
-
-  return !write_err;
-}
-
-/* Close Mach-O file FILE and clean up any associated data structures.  If FILE
-   was opened for writing, the file's Mach-O data is written at this time.  Any
-   cached data buffers are freed.  */
-
-void
-lto_obj_file_close (lto_file *file)
-{
-  lto_mach_o_file *mach_o_file = (lto_mach_o_file *) file;
-  struct lto_char_ptr_base *cur, *tmp;
-  lto_mach_o_section sec;
-  bool write_err = false;
-  int i;
-
-  /* If this file is open for writing, write a Mach-O object file.  */
-  if (mach_o_file->writable)
-    {
-      if (! mach_o_write_object_file (mach_o_file))
-        fatal_error ("cannot write Mach-O object file");
-    }
-
-  /* Close the file, we're done.  */
-  if (mach_o_file->fd != -1)
-    close (mach_o_file->fd);
-
-  /* Free any data buffers.  */
-  cur = mach_o_file->data;
-  while (cur)
-    {
-      tmp = cur;
-      cur = (struct lto_char_ptr_base *) cur->ptr;
-      free (tmp);
-    }
-
-  /* Free any sections and their data chains.  */
-  for (i = 0;
-       VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    {
-      lto_mach_o_data curdata, nextdata;
-      curdata = sec->data_chain;
-      while (curdata)
-	{
-	  nextdata = curdata->next;
-	  free (curdata);
-	  curdata = nextdata;
-	}
-      free (sec);
-    }
-  VEC_free (lto_mach_o_section, heap, mach_o_file->section_vec);
-
-  free (file);
-
-  /* If there was an error, mention it.  */
-  if (write_err)
-    error ("I/O error writing Mach-O output file");
-}
-
Index: gcc/lto/lto-macho.h
===================================================================
--- gcc/lto/lto-macho.h	(revision 166002)
+++ gcc/lto/lto-macho.h	(working copy)
@@ -1,251 +0,0 @@
-/* LTO routines for Mach-O object files.
-   Copyright 2010 Free Software Foundation, Inc.
-   Contributed by Steven Bosscher.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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 GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#ifndef LTO_MACH_O_H
-#define LTO_MACH_O_H
-
-/* On-disk file structures.  */
-
-/* Mach-O header (32 bits version).  */
-struct mach_o_header_32
-{
-  unsigned char magic[4];	/* Magic number.  */
-  unsigned char cputype[4];	/* CPU that this object is for.  */
-  unsigned char cpusubtype[4];	/* CPU subtype.  */
-  unsigned char filetype[4];	/* Type of file.  */
-  unsigned char ncmds[4];	/* Number of load commands.  */
-  unsigned char sizeofcmds[4];	/* Total size of load commands.  */
-  unsigned char flags[4];	/* Flags for special featues.  */
-};
-typedef struct mach_o_header_32 mach_o_header_32;
-
-/* Mach-O header (64 bits version).  */
-struct mach_o_header_64
-{
-  unsigned char magic[4];	/* Magic number.  */
-  unsigned char cputype[4];	/* CPU that this object is for.  */
-  unsigned char cpusubtype[4];	/* CPU subtype.  */
-  unsigned char filetype[4];	/* Type of file.  */
-  unsigned char ncmds[4];	/* Number of load commands.  */
-  unsigned char sizeofcmds[4];	/* Total size of load commands.  */
-  unsigned char flags[4];	/* Flags for special featues.  */
-  unsigned char reserved[4];	/* Reserved.  Duh.  */
-};
-typedef struct mach_o_header_64 mach_o_header_64;
-
-/* Magic number.  */
-#define MACH_O_MH_MAGIC			0xfeedface
-#define MACH_O_MH_CIGAM			0xcefaedfe
-#define MACH_O_MH_MAGIC_64		0xfeedfacf
-#define MACH_O_MH_CIGAM_64		0xcffaedfe
-
-/* Supported CPU types.  */
-#define MACH_O_CPU_TYPE_I386		7
-#define MACH_O_CPU_TYPE_X86_64		7 + 0x1000000
-#define MACH_O_CPU_TYPE_POWERPC		18
-#define MACH_O_CPU_TYPE_POWERPC_64	18 + 0x1000000
-
-/* Supported file types.  */
-#define MACH_O_MH_OBJECT		0x01
-
-/* Mach-O load command data structure.  */
-struct mach_o_load_command
-{
-  unsigned char cmd[4];		/* The type of load command.  */
-  unsigned char cmdsize[4];	/* Size in bytes of load command data structure.  */
-};
-typedef struct mach_o_load_command mach_o_load_command;
-
-/* Supported load commands.  We support only the segment load commands.  */
-#define MACH_O_LC_SEGMENT		0x01
-#define MACH_O_LC_SEGMENT_64		0x19
-
-/* LC_SEGMENT load command.  */
-struct mach_o_segment_command_32
-{
-  unsigned char cmd[4];		/* The type of load command (LC_SEGMENT).  */
-  unsigned char cmdsize[4];	/* Size in bytes of load command data structure.  */
-  unsigned char segname[16];	/* Name of this segment.  */
-  unsigned char vmaddr[4];	/* Virtual memory address of this segment.  */
-  unsigned char vmsize[4];	/* Size there, in bytes.  */
-  unsigned char fileoff[4];	/* Offset in bytes of the data to be mapped.  */
-  unsigned char filesize[4];	/* Size in bytes on disk.  */
-  unsigned char maxprot[4];	/* Maximum permitted vmem protection.  */
-  unsigned char initprot[4];	/* Initial vmem protection.  */
-  unsigned char nsects[4];	/* Number of sections in this segment.  */
-  unsigned char flags[4];	/* Flags that affect the loading.  */
-};
-typedef struct mach_o_segment_command_32 mach_o_segment_command_32;
-
-/* LC_SEGMENT_64 load command.  Only nsects matters for us, really.  */
-struct mach_o_segment_command_64
-{
-  unsigned char cmd[4];		/* The type of load command (LC_SEGMENT_64).  */
-  unsigned char cmdsize[4];	/* Size in bytes of load command data structure.  */
-  unsigned char segname[16];	/* Name of this segment.  */
-  unsigned char vmaddr[8];	/* Virtual memory address of this segment.  */
-  unsigned char vmsize[8];	/* Size there, in bytes.  */
-  unsigned char fileoff[8];	/* Offset in bytes of the data to be mapped.  */
-  unsigned char filesize[8];	/* Size in bytes on disk.  */
-  unsigned char maxprot[4];	/* Maximum permitted vmem protection.  */
-  unsigned char initprot[4];	/* Initial vmem protection.  */
-  unsigned char nsects[4];	/* Number of sections in this segment.  */
-  unsigned char flags[4];	/* Flags that affect the loading.  */
-};
-typedef struct mach_o_segment_command_64 mach_o_segment_command_64;
-
-/* A Mach-O 32-bits section.  */
-struct mach_o_section_32
-{
-  unsigned char sectname[16];	/* Section name.  */
-  unsigned char segname[16];	/* Segment that the section belongs to.  */
-  unsigned char addr[4];	/* Address of this section in memory.  */
-  unsigned char size[4];	/* Size in bytes of this section.  */
-  unsigned char offset[4];	/* File offset of this section.  */
-  unsigned char align[4];	/* log2 of this section's alignment.  */
-  unsigned char reloff[4];	/* File offset of this section's relocs.  */
-  unsigned char nreloc[4];	/* Number of relocs for this section.  */
-  unsigned char flags[4];	/* Section flags/attributes.  */
-  unsigned char reserved1[4];
-  unsigned char reserved2[4];
-};
-typedef struct mach_o_section_32 mach_o_section_32;
-
-/* A Mach-O 64-bits section.  */
-struct mach_o_section_64
-{
-  unsigned char sectname[16];	/* Section name.  */
-  unsigned char segname[16];	/* Segment that the section belongs to.  */
-  unsigned char addr[8];	/* Address of this section in memory.  */
-  unsigned char size[8];	/* Size in bytes of this section.  */
-  unsigned char offset[4];	/* File offset of this section.  */
-  unsigned char align[4];	/* log2 of this section's alignment.  */
-  unsigned char reloff[4];	/* File offset of this section's relocs.  */
-  unsigned char nreloc[4];	/* Number of relocs for this section.  */
-  unsigned char flags[4];	/* Section flags/attributes.  */
-  unsigned char reserved1[4];
-  unsigned char reserved2[4];
-  unsigned char reserved3[4];
-};
-typedef struct mach_o_section_64 mach_o_section_64;
-
-/* Flags for Mach-O sections.  LTO sections are marked with S_ATTR_DEBUG
-   to instruct the linker to ignore the sections.  */
-#define MACH_O_S_ATTR_DEBUG			0x02000000
-
-/* In-memory file structures.  */
-
-/* Section data in output files is made of these.  */
-struct lto_mach_o_data_d
-{
-  /* Pointer to data block.  */
-  void *d_buf;
-
-  /* Size of data block.  */
-  ssize_t d_size;
-
-  /* Next data block for this section.  */
-  struct lto_mach_o_data_d *next;
-};
-typedef struct lto_mach_o_data_d *lto_mach_o_data;
-
-/* This struct tracks the data for a section.  */
-struct lto_mach_o_section_d
-{
-  /* Singly-linked list of section's data blocks.  */
-  lto_mach_o_data data_chain;
-
-  /* Offset in string table of the section name.  */
-  size_t strtab_offs;
-
-  /* Section name.  */
-  const char *name;
-
-  /* Number of trailing padding bytes needed.  */
-  ssize_t pad_needed;
-
-  /* Raw section header data.  */
-  size_t section_size;
-  union {
-    struct {
-      char sectname[16];
-      char segname[16];
-    } section;
-    mach_o_section_32 section_32;
-    mach_o_section_64 section_64;
-  } u;
-
-  /* Next section for this file.  */
-  struct lto_mach_o_section_d *next;
-};
-typedef struct lto_mach_o_section_d *lto_mach_o_section;
-DEF_VEC_P (lto_mach_o_section);
-DEF_VEC_ALLOC_P (lto_mach_o_section, heap);
-
-/* A Mach-O file.  */
-struct lto_mach_o_file_d
-{
-  /* The base information.  */
-  lto_file base;
-
-  /* Common file members:  */
-
-  /* The system file descriptor for the file.  */
-  int fd;
-
-  /* The file's overall header.  */
-  union {
-    /* We make use here of the fact that section_32 and section_64
-       have the same layout (except for section_64.reserved3).  We
-       read the struct of proper size, but only address the first
-       member of this union.  */
-    mach_o_header_64 header;
-    mach_o_header_32 header_32;
-    mach_o_header_64 header_64;
-  } u;
-
-  /* All sections in a varray.  */
-  VEC(lto_mach_o_section, heap) *section_vec;
-
-  /* Readable file members:  */
-
-  /* File total size.  */
-  off_t file_size;
-
-  /* True if this file is open for writing.  */
-  bool writable;
-
-  /* Section containing the __section_names section.  */
-  lto_mach_o_section section_names_section;
-
-  /* Writable file members:  */
-
-  /* The currently active section.  */
-  lto_mach_o_section scn;
-
-  /* Linked list of data which must be freed *after* the file has been
-     closed.  This is an annoying limitation of libelf.  Which has been
-     faithfully reproduced here.  */
-  struct lto_char_ptr_base *data;
-};
-typedef struct lto_mach_o_file_d lto_mach_o_file;
-
-#endif /* LTO_MACH_O_H */
-
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(revision 166002)
+++ gcc/configure.ac	(working copy)
@@ -975,22 +975,6 @@ AC_CHECK_FUNCS(times clock kill getrlimi
 	gettimeofday mbstowcs wcswidth mmap mincore setlocale \
 	gcc_UNLOCKED_FUNCS)
 
-save_CPPFLAGS="$CPPFLAGS"
-save_LIBS="$LIBS"
-LIBS="$LIBS $LIBELFLIBS"
-AC_CHECK_FUNCS(elf_getshdrstrndx,,
-  [AC_CHECK_FUNCS(elf_getshstrndx,
-    [AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdlib.h>
-#include <libelf.h>
-int main()
-{
-  return elf_getshstrndx (NULL, 0) == 0;
-}]])], AC_DEFINE(HAVE_ELF_GETSHSTRNDX_GABI, 1,
-        [Define if elf_getshstrndx has gABI conformant return values.]))])]
-  )
-LIBS="$save_LIBS"
-CPPFLAGS="$save_CPPFLAGS"
-
 if test x$ac_cv_func_mbstowcs = xyes; then
   AC_CACHE_CHECK(whether mbstowcs works, gcc_cv_func_mbstowcs_works,
 [    AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdlib.h>
@@ -4461,17 +4445,6 @@ changequote([,])dnl
 		    AC_DEFINE(ENABLE_LTO, 1, [Define to enable LTO support.])
 		    enable_lto=yes
 		    AC_SUBST(enable_lto)
-		    # LTO needs to speak the platform's object file format, and has a
-		    # number of implementations of the required binary file access APIs.
-		    # ELF is the most common, and default.  We only link libelf if ELF
-		    # is indeed the selected format.
-		    LTO_BINARY_READER=${lto_binary_reader}
-		    LTO_USE_LIBELF=-lelf
-		    if test "x$lto_binary_reader" != "xlto-elf" ; then
-		      LTO_USE_LIBELF=
-		    fi
-		    AC_SUBST(LTO_BINARY_READER)
-		    AC_SUBST(LTO_USE_LIBELF)
 		    ;;
 		*) ;;
 	esac
@@ -4644,12 +4617,6 @@ if test "x${CLOOGLIBS}" != "x" ; then 
    AC_DEFINE(HAVE_cloog, 1, [Define if cloog is in use.])
 fi
 
-AC_ARG_VAR(LIBELFLIBS,[How to link libelf])
-AC_ARG_VAR(LIBELFINC,[How to find libelf include files])
-if test "x${LIBELFLIBS}" != "x" ; then 
-   AC_DEFINE(HAVE_libelf, 1, [Define if libelf is in use.])
-fi
-
 # Check for plugin support
 AC_ARG_ENABLE(plugin,
 [  --enable-plugin         enable plugin support],
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 166002)
+++ gcc/config.gcc	(working copy)
@@ -219,8 +219,6 @@ default_gnu_indirect_function=no
 target_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
-# Selects the object file format reader/writer used by LTO.
-lto_binary_reader=lto-elf
 
 # Don't carry these over build->host->target.  Please.
 xm_file=
@@ -1159,14 +1157,12 @@ i[34567]86-*-darwin*)
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
 	extra_options="${extra_options} i386/darwin.opt"
-	lto_binary_reader=lto-macho
 	;;
 x86_64-*-darwin*)
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
 	tm_file="${tm_file} ${cpu_type}/darwin64.h"
 	extra_options="${extra_options} i386/darwin.opt"
-	lto_binary_reader=lto-macho
 	;;
 i[34567]86-*-elf*)
 	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
@@ -1421,7 +1417,6 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
 		thread_file='posix'
 	fi
 	use_gcc_stdint=wrap
-	lto_binary_reader=lto-coff
 	;;
 i[34567]86-*-mingw* | x86_64-*-mingw*)
 	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h"
@@ -1494,7 +1489,6 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
 	cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
 	default_use_cxa_atexit=yes
 	use_gcc_stdint=wrap
-	lto_binary_reader=lto-coff
 	case ${enable_threads} in
 	  "" | yes | win32)	  thread_file='win32'
 	  tmake_file="${tmake_file} i386/t-gthr-win32"
@@ -2004,7 +1998,6 @@ powerpc-*-darwin*)
 	    ;;
 	esac
 	tmake_file="${tmake_file} t-slibgcc-darwin"
-	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc64-*-darwin*)
@@ -2012,7 +2005,6 @@ powerpc64-*-darwin*)
 	extra_parts="crt2.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin"
 	tm_file="${tm_file} ${cpu_type}/darwin8.h ${cpu_type}/darwin64.h"
-	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc*-*-freebsd*)
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 166002)
+++ gcc/Makefile.in	(working copy)
@@ -319,17 +319,9 @@ PPLINC = @PPLINC@
 CLOOGLIBS = @CLOOGLIBS@
 CLOOGINC = @CLOOGINC@
 
-# How to find libelf
-LIBELFLIBS = @LIBELFLIBS@
-LIBELFINC = @LIBELFINC@
-
 # Set to 'yes' if the LTO front end is enabled.
 enable_lto = @enable_lto@
 
-# Set according to LTO object file format.
-LTO_BINARY_READER = @LTO_BINARY_READER@
-LTO_USE_LIBELF = @LTO_USE_LIBELF@
-
 # Compiler and flags needed for plugin support
 ifneq ($(ENABLE_BUILD_WITH_CXX),yes)
 PLUGINCC = @CC@
@@ -1032,7 +1024,7 @@ BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
 LIBS = @LIBS@ $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBIBERTY) $(LIBDECNUMBER) \
 	$(HOST_LIBS)
 BACKENDLIBS = $(CLOOGLIBS) $(PPLLIBS) $(GMPLIBS) $(PLUGINLIBS) $(HOST_LIBS) \
-	$(ZLIB) $(LIBELFLIBS)
+	$(ZLIB)
 # Any system libraries needed just for GNAT.
 SYSLIBS = @GNAT_LIBEXC@
 
@@ -1063,7 +1055,7 @@ BUILD_ERRORS = build/errors.o
 INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
 	   -I$(srcdir)/../include @INCINTL@ \
 	   $(CPPINC) $(GMPINC) $(DECNUMINC) \
-	   $(PPLINC) $(CLOOGINC) $(LIBELFINC)
+	   $(PPLINC) $(CLOOGINC)
 
 .c.o:
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
Index: configure.ac
===================================================================
--- configure.ac	(revision 166002)
+++ configure.ac	(working copy)
@@ -1647,174 +1647,7 @@ AC_SUBST(clooginc)
 AC_ARG_ENABLE(lto,
 [  --enable-lto            enable link time optimization support],
 enable_lto=$enableval,
-enable_lto=yes; default_enable_lto=yes)
-
-
-ACX_ELF_TARGET_IFELSE([if test x"$enable_lto" = x"yes" ; then
-  # Make sure that libelf.h and gelf.h are available.
-  AC_ARG_WITH(libelf, [  --with-libelf=PATH       Specify prefix directory for the installed libelf package
-                          Equivalent to --with-libelf-include=PATH/include
-                          plus --with-libelf-lib=PATH/lib])
-
-  AC_ARG_WITH(libelf_include, [  --with-libelf-include=PATH Specify directory for installed libelf include files])
-
-  AC_ARG_WITH(libelf_lib, [  --with-libelf-lib=PATH   Specify the directory for the installed libelf library])
-
-  saved_CFLAGS="$CFLAGS"
-  saved_CPPFLAGS="$CPPFLAGS"
-  saved_LIBS="$LIBS"
-
-  case $with_libelf in 
-    "")
-      libelflibs="-lelf"
-      libelfinc="-I/usr/include/libelf"
-      ;;
-    *)
-      libelflibs="-L$with_libelf/lib -lelf"
-      libelfinc="-I$with_libelf/include -I$with_libelf/include/libelf"
-      LIBS="$libelflibs $LIBS"
-      ;;
-  esac
-
-  if test "x$with_libelf_include" != x; then
-    libelfinc="-I$with_libelf_include"
-  fi
-
-  if test "x$with_libelf_lib" != x; then
-    libelflibs="-L$with_libelf_lib -lelf"
-    LIBS="$libelflibs $LIBS"
-  fi
-
-  if test "x$with_libelf$with_libelf_include$with_libelf_lib" = x \
-     && test -d ${srcdir}/libelf; then
-    libelflibs='-L$$r/$(HOST_SUBDIR)/libelf/lib -lelf '
-    libelfinc='-D__LIBELF_INTERNAL__ -I$$r/$(HOST_SUBDIR)/libelf/lib -I$$s/libelf/lib'
-    LIBS="$libelflibs $LIBS"
-
- else
-
-  CFLAGS="$CFLAGS $libelfinc"
-  CPPFLAGS="$CPPFLAGS $libelfinc"
-  LIBS="$LIBS $libelflibs"
-
-  AC_CHECK_HEADERS(libelf.h, [have_libelf_h=yes])
-  AC_CHECK_HEADERS(gelf.h, [have_gelf_h=yes])
-
-  AC_CHECK_HEADERS(libelf/libelf.h, [have_libelf_libelf_h=yes])
-  AC_CHECK_HEADERS(libelf/gelf.h, [have_libelf_gelf_h=yes])
-
-  # If we couldn't find libelf.h and the user forced it, emit an error.
-  if test x"$have_libelf_h" != x"yes" \
-     && test x"$have_libelf_libelf_h" != x"yes" ; then
-    if test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([LTO support requires libelf.h or libelf/libelf.h.])
-    else
-      enable_lto=no
-      libelflibs=
-      libelfinc=
-    fi
-  fi
-
-  # If we couldn't find gelf.h and the user forced it, emit an error.
-  if test x"$have_gelf_h" != x"yes" \
-     && test x"$have_libelf_gelf_h" != x"yes" ; then
-    if test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([LTO support requires gelf.h or libelf/gelf.h.])
-    else
-      enable_lto=no
-      libelflibs=
-      libelfinc=
-    fi
-  fi
-
-  # Check that the detected libelf has the functions we need.  We cannot
-  # rely on just detecting the headers since they do not include 
-  # versioning information.  Add functions, if needed.
-  if test x"$enable_lto" = x"yes" ; then
-    AC_MSG_CHECKING([for the correct version of libelf])
-    AC_TRY_LINK(
-      [#include <libelf.h>],[
-      elf_errmsg (0);
-      elf_getscn (0, 0);
-      elf_nextscn (0, 0);
-      elf_strptr (0, 0, 0);
-      elf_getident (0, 0);
-      elf_begin (0, 0, 0);
-      elf_ndxscn (0);
-      elf_end (0);
-      ],
-      [AC_MSG_RESULT([yes]);],
-      [AC_MSG_RESULT([no]); enable_lto=no; libelflibs= ; libelfinc= ]
-    )
-
-    # Check for elf_getshdrstrndx or elf_getshstrndx.  The latter's flavor
-    # is determined in gcc/configure.ac.
-    if test x"$enable_lto" = x"yes" ; then
-      AC_MSG_CHECKING([for elf_getshdrstrndx])
-      AC_TRY_LINK(
-        [#include <libelf.h>],[
-	elf_getshdrstrndx (0, 0);
-        ],
-        [AC_MSG_RESULT([yes]);],
-        [AC_MSG_RESULT([no]);
-	 AC_MSG_CHECKING([for elf_getshstrndx])
-         AC_TRY_LINK(
-           [#include <libelf.h>],[
-	   elf_getshstrndx (0, 0);
-           ],
-           [AC_MSG_RESULT([yes]);],
-           [AC_MSG_RESULT([no]); enable_lto=no; libelflibs= ; libelfinc= ]
-         )]
-      )
-    fi
-
-    # If we couldn't enable LTO and the user forced it, emit an error.
-    if test x"$enable_lto" = x"no" \
-       && test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([To enable LTO, GCC requires libelf v0.8.12+.
-Try the --with-libelf, --with-libelf-include and --with-libelf-lib options
-to specify its location.])
-    fi
-  fi
-
-  CFLAGS="$saved_CFLAGS"
-  CPPFLAGS="$saved_CPPFLAGS"
-  LIBS="$saved_LIBS"
-
- fi
-
-  # Flags needed for libelf.
-  AC_SUBST(libelflibs)
-  AC_SUBST(libelfinc)
-  # ELF platforms build the lto-plugin when GOLD is in use.
-  build_lto_plugin=${ENABLE_GOLD}
-fi],[if test x"$default_enable_lto" = x"yes" ; then
-    case $target in
-      *-apple-darwin* | *-cygwin* | *-mingw*) ;;
-      # On other non-ELF platforms, LTO must be explicitly enabled.
-      *) enable_lto=no ;;
-    esac
-  else
-  # Apart from ELF platforms, only Windows and Darwin support LTO so far.
-  # It would also be nice to check the binutils support, but we don't
-  # have gcc_GAS_CHECK_FEATURE available here.  For now, we'll just
-  # warn during gcc/ subconfigure; unless you're bootstrapping with
-  # -flto it won't be needed until after installation anyway.
-    case $target in
-      *-cygwin* | *-mingw* | *-apple-darwin*) ;;
-      *) if test x"$enable_lto" = x"yes"; then
-	AC_MSG_ERROR([LTO support is not enabled for this target.])
-        fi
-      ;;
-    esac
-  fi
-  # Among non-ELF, only Windows platforms support the lto-plugin so far.
-  case $target in
-    *-cygwin* | *-mingw*) build_lto_plugin=yes ;;
-    *) ;;
-  esac
-  default_enable_lto=no])
-
+enable_lto=yes)
 
 # By default, C is the only stage 1 language.
 stage1_languages=,c,
Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 166002)
+++ gcc/doc/install.texi	(working copy)
@@ -355,17 +355,6 @@ not installed in your default library se
 
 Necessary to build libgcj, the GCJ runtime.
 
-@item libelf version 0.8.12 (or later)
-
-Necessary to build link-time optimization (LTO) support.  It can be
-downloaded from @uref{http://www.mr511.de/software/libelf-0.8.12.tar.gz},
-though it is commonly available in several systems.  The version in
-IRIX 6.5 doesn't work since it lacks @file{gelf.h}.  The version in
-Solaris 2 does work.
-
-The @option{--with-libelf} configure option should be used if libelf is
-not installed in your default library search patch.
-
 @end table
 
 @heading Tools/packages necessary for modifying GCC
@@ -1650,20 +1639,9 @@ default for a native toolchain with an a
 GLIBC 2.11 or above, otherwise disabled.
 
 @item --enable-lto
+@itemx --disable-lto
 Enable support for link-time optimization (LTO).  This is enabled by
-default if a working libelf implementation is found (see
-@option{--with-libelf}).
-
-@item --with-libelf=@var{pathname}
-@itemx --with-libelf-include=@var{pathname}
-@itemx --with-libelf-lib=@var{pathname}
-If you do not have libelf installed in a standard location and you
-want to enable support for link-time optimization (LTO), you can
-explicitly specify the directory where libelf is installed
-(@samp{--with-libelf=@var{libelfinstalldir}}).  The
-@option{--with-libelf=@var{libelfinstalldir}} option is shorthand for
-@option{--with-libelf-include=@var{libelfinstalldir}/include}
-@option{--with-libelf-lib=@var{libelfinstalldir}/lib}.
+default, and may be disabled using @option{--disable-lto}.
 
 @item --enable-gold
 Enable support for using @command{gold} as the linker.  If gold support is

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

* Re: Discussion about merging Go frontend
  2010-10-29  6:56               ` Discussion about merging Go frontend Ian Lance Taylor
@ 2010-10-29 13:19                 ` Dave Korn
  2010-10-29 13:31                   ` IainS
  2010-10-29 13:45                   ` Jack Howarth
  2010-10-29 13:51                 ` Richard Guenther
                                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 68+ messages in thread
From: Dave Korn @ 2010-10-29 13:19 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

On 29/10/2010 02:31, Ian Lance Taylor wrote:
> Dave Korn <dave.korn.cygwin@  writes:
> 
>>   What would be even nicer would be if we could share the same code-reader
>> interface between lto and go (and the lto-plugin), thereby getting object
>> format independence equally everywhere for no extra cost.
> 
> How about this?

  That looks excellent, thank you!

> This implements an object file reader/writer which does everything
> required by LTO and gccgo.  The ELF code works.  I have not tested the
> Mach-O and COFF code at all beyond compiling it; I hope that somebody
> else can test those targets and fix them.

  I'm right here :) Can't help with Darwin but hopefully Jack/Iain will be
available.

> With this patch, libelf is no longer needed.
> 
> I've bootstrapped this on x86_64-unknown-linux-gnu, and I've run the LTO
> testsuite.
> 
> This patch puts the code in libiberty, but it could equally well go in
> gcc.  Anybody want to make an argument one way or another?

  Libiberty is better for sharing with lto-plugin, I think.  I sent a patch
that commoned out some of the COFF-reader code into gcc/, but I only put it
there because it was a single header file with no associated object file.  Now
there's actual code to be linked in, I think libiberty is a better choice than
lto-plugin trying to share .o files from the ../gcc/ objdir.

> Does the general interface look OK?
> 
> This patch requires approval from the LTO maintainers.

  Also, I have a patch outstanding to COFF-ize the lto-plugin(*), so if we can
get an early "OK in principle" I'll get cracking on respinning it to use this
new interface.

    cheers,
      DaveK
-- 
(*) - http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02176.html

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

* Re: Discussion about merging Go frontend
  2010-10-29 13:19                 ` Dave Korn
@ 2010-10-29 13:31                   ` IainS
  2010-10-29 14:50                     ` Ian Lance Taylor
  2010-10-29 13:45                   ` Jack Howarth
  1 sibling, 1 reply; 68+ messages in thread
From: IainS @ 2010-10-29 13:31 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Dave Korn, Andi Kleen, Andrew Pinski, Mark Mitchell,
	GCC Mailing List, GCC Patches, Jack Howarth


On 29 Oct 2010, at 09:56, Dave Korn wrote:
>> This implements an object file reader/writer which does everything
>> required by LTO and gccgo.  The ELF code works.  I have not tested  
>> the
>> Mach-O and COFF code at all beyond compiling it; I hope that somebody
>> else can test those targets and fix them.
>
>  I'm right here :) Can't help with Darwin but hopefully Jack/Iain  
> will be
> available.


I tried with 166058 on ppc-darwin9 (my other machines are tied up  
right now)

-flto fails on link with missing _main.
e.g:
Executing on host: /Volumes/ScratchCS/gcc-4-6-trunk-build/gcc/xgcc -B/ 
Volumes/ScratchCS/gcc-4-6-trunk-build/gcc/ c_lto_20081024_0.o  -
O0 -flto       -m32 -o gcc-dg-lto-20081024-21    (timeout = 60)
Undefined symbols:
   "_main", referenced from:
       start in crt1.10.5.o

-whopr ices with:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000000
0x007f8e18 in objfile_mach_o_find_sections (objfile=0x40e078b0,  
pfn=0x1d7ec <lto_obj_add_section>, data=0xbffff19c, err=0xbffff198)  
at /GCC/gcc-live-trunk/libiberty/objfile-mach-o.c:469
469           memcpy (name, sechdr + sectname_offset, MACH_O_NAME_LEN);
(gdb) bt
#0  0x007f8e18 in objfile_mach_o_find_sections (objfile=0x40e078b0,  
pfn=0x1d7ec <lto_obj_add_section>, data=0xbffff19c, err=0xbffff198)  
at /GCC/gcc-live-trunk/libiberty/objfile-mach-o.c:469
#1  0x007f5dbc in objfile_find_sections (objfile=<value temporarily  
unavailable, due to optimizations>, pfn=<value temporarily  
unavailable, due to optimizations>, data=<value temporarily  
unavailable, due to optimizations>, err=<value temporarily  
unavailable, due to optimizations>) at /GCC/gcc-live-trunk/libiberty/ 
objfile.c:173
#2  0x0001dc60 in lto_obj_build_section_table (lto_file=<value  
temporarily unavailable, due to optimizations>) at /GCC/gcc-live-trunk/ 
gcc/lto/lto-objfile.c:270
#3  0x0001af80 in lto_read_all_file_options () at /GCC/gcc-live-trunk/ 
gcc/lto/lto.c:2052
#4  0x00003960 in lto_post_options (pfilename=<value temporarily  
unavailable, due to optimizations>) at /GCC/gcc-live-trunk/gcc/lto/lto- 
lang.c:709
#5  0x004f0eec in toplev_main (argc=15, argv=Cannot access memory at  
address 0x1c
) at /GCC/gcc-live-trunk/gcc/toplev.c:1778
#6  0x00001944 in start ()

if you need more analysis - ping me with what and I'll try and do sth  
-- or maybe Jack can help with a user on his machine.

cheers,
Iain


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

* Re: Discussion about merging Go frontend
  2010-10-29 13:19                 ` Dave Korn
  2010-10-29 13:31                   ` IainS
@ 2010-10-29 13:45                   ` Jack Howarth
  2010-10-29 14:34                     ` Dave Korn
  2010-10-29 14:35                     ` Ian Lance Taylor
  1 sibling, 2 replies; 68+ messages in thread
From: Jack Howarth @ 2010-10-29 13:45 UTC (permalink / raw)
  To: Dave Korn
  Cc: Ian Lance Taylor, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc,
	gcc-patches

On Fri, Oct 29, 2010 at 09:56:02AM +0100, Dave Korn wrote:
> On 29/10/2010 02:31, Ian Lance Taylor wrote:
> > Dave Korn <dave.korn.cygwin@  writes:
> > 
> >>   What would be even nicer would be if we could share the same code-reader
> >> interface between lto and go (and the lto-plugin), thereby getting object
> >> format independence equally everywhere for no extra cost.
> > 
> > How about this?
> 
>   That looks excellent, thank you!
> 
> > This implements an object file reader/writer which does everything
> > required by LTO and gccgo.  The ELF code works.  I have not tested the
> > Mach-O and COFF code at all beyond compiling it; I hope that somebody
> > else can test those targets and fix them.
> 
>   I'm right here :) Can't help with Darwin but hopefully Jack/Iain will be
> available.
> 

Dave,
   Doesn't the go compiler require functional split stack support? Mike Stump
left me with the impression that split stack support would require additional
linker support on darwin.
               Jack

> > With this patch, libelf is no longer needed.
> > 
> > I've bootstrapped this on x86_64-unknown-linux-gnu, and I've run the LTO
> > testsuite.
> > 
> > This patch puts the code in libiberty, but it could equally well go in
> > gcc.  Anybody want to make an argument one way or another?
> 
>   Libiberty is better for sharing with lto-plugin, I think.  I sent a patch
> that commoned out some of the COFF-reader code into gcc/, but I only put it
> there because it was a single header file with no associated object file.  Now
> there's actual code to be linked in, I think libiberty is a better choice than
> lto-plugin trying to share .o files from the ../gcc/ objdir.
> 
> > Does the general interface look OK?
> > 
> > This patch requires approval from the LTO maintainers.
> 
>   Also, I have a patch outstanding to COFF-ize the lto-plugin(*), so if we can
> get an early "OK in principle" I'll get cracking on respinning it to use this
> new interface.
> 
>     cheers,
>       DaveK
> -- 
> (*) - http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02176.html

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

* Re: Discussion about merging Go frontend
  2010-10-29  6:56               ` Discussion about merging Go frontend Ian Lance Taylor
  2010-10-29 13:19                 ` Dave Korn
@ 2010-10-29 13:51                 ` Richard Guenther
  2010-10-29 14:31                   ` Dave Korn
  2010-10-29 15:30                 ` Mark Mitchell
                                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 68+ messages in thread
From: Richard Guenther @ 2010-10-29 13:51 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Dave Korn, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

On Fri, Oct 29, 2010 at 3:31 AM, Ian Lance Taylor <iant@google.com> wrote:
> Dave Korn <dave.korn.cygwin@gmail.com> writes:
>
>>   What would be even nicer would be if we could share the same code-reader
>> interface between lto and go (and the lto-plugin), thereby getting object
>> format independence equally everywhere for no extra cost.
>
> How about this?
>
> This implements an object file reader/writer which does everything
> required by LTO and gccgo.  The ELF code works.  I have not tested the
> Mach-O and COFF code at all beyond compiling it; I hope that somebody
> else can test those targets and fix them.
>
> With this patch, libelf is no longer needed.
>
> I've bootstrapped this on x86_64-unknown-linux-gnu, and I've run the LTO
> testsuite.
>
> This patch puts the code in libiberty, but it could equally well go in
> gcc.  Anybody want to make an argument one way or another?
>
> Does the general interface look OK?
>
> This patch requires approval from the LTO maintainers.  I don't need
> approval for the libiberty changes (if the code stays in libiberty) but
> of course I would appreciate it if somebody could look it over.  I think
> the configure and Makefile changes are sufficiently obvious given the
> other changes as to not require approval.
>
> If this patch is accepted, then gccgo will not require elfcpp.

Nice!

The LTO changes are ok (I suppose you'll be around in helping people
debug eventual problems).

Richard.

> Ian
>
>
> include/ChangeLog:
>
> 2010-10-28  Ian Lance Taylor  <iant@google.com>
>
>        * objfile.h: New file.
>
> libiberty/ChangeLog:
>
> 2010-10-28  Ian Lance Taylor  <iant@google.com>
>
>        * objfile.c: New file.
>        * objfile-common.h: New file.
>        * objfile-elf.c: New file.
>        * objfile-mach-o.c: New file.
>        * objfile-coff.c: New file.
>        * configure.ac: Add AC_TYPE_SSIZE_T.
>        * Makefile.in: Rebuild dependencies.
>        (CFILES): Add objfile.c, objfile-coff, objfile-elf.c,
>        objfile-mach-o.c.
>        (REQUIRED_OFILES): Add corresponding object files.
>        * configure: Rebuild.
>        * config.in: Rebuild.
>
> gcc/ChangeLog:
>
> 2010-10-28  Ian Lance Taylor  <iant@google.com>
>
>        * configure.ac: Remove elf_getshdrstrndx test.  Don't substitute
>        LTO_BINARY_READER or LTO_USE_LIBELF.  Remove LIBELFLIBS and
>        LIBELFINC.  Remove HAVE_libelf.
>        * gcc/config.gcc: Don't set lto_binary_reader.
>        * gcc/Makefile.in (LIBELFLIBS, LIBELFINC): Remove variables.
>        (LTO_BINARY_READER, LTO_USE_LIBELF): Remove variables.
>        (LIBS): Remove $(LIBELFLIBS).
>        (INCLUDES): Remove $(LIBELFINC).
>        * doc/install.texi (Prerequisites): Remove libelf paragraphs.
>        (Configuration): Mention --disable-lto.  Remove --with-libelf
>        paragraph.
>        * configure: Rebuild.
>        * config.in: Rebuild.
>
> gcc/lto/ChangeLog:
>
> 2010-10-28  Ian Lance Taylor  <iant@google.com>
>
>        * lto-objfile.c: New file.
>        * lto-elf.c: Remove file.
>        * lto-macho.c: Remove file.
>        * lto-macho.h: Remove file.
>        * lto-coff.c: Remove file.
>        * lto-coff.h: Remove file.
>        * Make-lang.in (LTO_OBJS): Change lto/$(LTO_BINARY_READER).o to
>        lto/lto-objfile.o.
>        ($(LTO_EXE)): Remove $(LTO_USE_LIBELF)
>        (lto/lto-objfile.o): New target.
>        (lto/lto-elf.o, lto/lto-coff.o, lto/lto-macho.o): Remove targets.
>
> ./ChangeLog:
>
> 2010-10-28  Ian Lance Taylor  <iant@google.com>
>
>        * configure.ac: Don't set default_enable_lto.  Remove libelf tests.
>        * configure: Rebuild.
>
>
>

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

* Re: Discussion about merging Go frontend
  2010-10-29 13:51                 ` Richard Guenther
@ 2010-10-29 14:31                   ` Dave Korn
  0 siblings, 0 replies; 68+ messages in thread
From: Dave Korn @ 2010-10-29 14:31 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Ian Lance Taylor, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc,
	gcc-patches

On 29/10/2010 14:31, Richard Guenther wrote:
> On Fri, Oct 29, 2010 at 3:31 AM, Ian Lance Taylor <iant@google.com> wrote:

>> This patch requires approval from the LTO maintainers.  I don't need
>> approval for the libiberty changes (if the code stays in libiberty) but
>> of course I would appreciate it if somebody could look it over.  I think
>> the configure and Makefile changes are sufficiently obvious given the
>> other changes as to not require approval.
>>
>> If this patch is accepted, then gccgo will not require elfcpp.
> 
> Nice!
> 
> The LTO changes are ok (I suppose you'll be around in helping people
> debug eventual problems).

  I'll start work on porting the lto-plugin to use the new interface.  It'll
subsume my plugin-for-coff patch.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-10-29 13:45                   ` Jack Howarth
@ 2010-10-29 14:34                     ` Dave Korn
  2010-10-29 14:35                     ` Ian Lance Taylor
  1 sibling, 0 replies; 68+ messages in thread
From: Dave Korn @ 2010-10-29 14:34 UTC (permalink / raw)
  To: Jack Howarth
  Cc: Ian Lance Taylor, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc,
	gcc-patches

On 29/10/2010 14:18, Jack Howarth wrote:
> On Fri, Oct 29, 2010 at 09:56:02AM +0100, Dave Korn wrote:
>> On 29/10/2010 02:31, Ian Lance Taylor wrote:
>>> Dave Korn <dave.korn.cygwin@  writes:
>>>
>>>>   What would be even nicer would be if we could share the same code-reader
>>>> interface between lto and go (and the lto-plugin), thereby getting object
>>>> format independence equally everywhere for no extra cost.
>>> How about this?
>>   That looks excellent, thank you!
>>
>>> This implements an object file reader/writer which does everything
>>> required by LTO and gccgo.  The ELF code works.  I have not tested the
>>> Mach-O and COFF code at all beyond compiling it; I hope that somebody
>>> else can test those targets and fix them.
>>   I'm right here :) Can't help with Darwin but hopefully Jack/Iain will be
>> available.
>>
> 
> Dave,
>    Doesn't the go compiler require functional split stack support? 

  Ian will have to answer that, I don't know.

> Mike Stump
> left me with the impression that split stack support would require additional
> linker support on darwin.

  Well, this also affects LTO, since it refactors the object file support
underlying that.  As Iain has discovered...

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-10-29 13:45                   ` Jack Howarth
  2010-10-29 14:34                     ` Dave Korn
@ 2010-10-29 14:35                     ` Ian Lance Taylor
  2010-10-29 15:10                       ` Jack Howarth
  1 sibling, 1 reply; 68+ messages in thread
From: Ian Lance Taylor @ 2010-10-29 14:35 UTC (permalink / raw)
  To: Jack Howarth
  Cc: Dave Korn, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

Jack Howarth <howarth@bromo.med.uc.edu> writes:

>    Doesn't the go compiler require functional split stack support? Mike Stump
> left me with the impression that split stack support would require additional
> linker support on darwin.

The Go compiler can work without split stack support.  The effect is
that you are limited in the number of goroutines you can create,
particularly on a 32-bit system.  And you are also limited in the depth
of recursion and size of local variables you can create.  But you can
write working Go programs.

The objfile patch, however, is not really about Go, although gccgo will
use it.  It's really about LTO.  If it works for LTO, it will work for
gccgo.

Ian

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

* Re: Discussion about merging Go frontend
  2010-10-29 13:31                   ` IainS
@ 2010-10-29 14:50                     ` Ian Lance Taylor
  0 siblings, 0 replies; 68+ messages in thread
From: Ian Lance Taylor @ 2010-10-29 14:50 UTC (permalink / raw)
  To: IainS; +Cc: Dave Korn, GCC Patches, Jack Howarth

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

IainS <developer@sandoe-acoustics.co.uk> writes:

> -whopr ices with:
>
> Program received signal EXC_BAD_ACCESS, Could not access memory.
> Reason: KERN_PROTECTION_FAILURE at address: 0x00000000
> 0x007f8e18 in objfile_mach_o_find_sections (objfile=0x40e078b0,
> pfn=0x1d7ec <lto_obj_add_section>, data=0xbffff19c, err=0xbffff198)
> at /GCC/gcc-live-trunk/libiberty/objfile-mach-o.c:469
> 469           memcpy (name, sechdr + sectname_offset, MACH_O_NAME_LEN);
> (gdb) bt
> #0  0x007f8e18 in objfile_mach_o_find_sections (objfile=0x40e078b0,
> pfn=0x1d7ec <lto_obj_add_section>, data=0xbffff19c, err=0xbffff198)
> at /GCC/gcc-live-trunk/libiberty/objfile-mach-o.c:469
> #1  0x007f5dbc in objfile_find_sections (objfile=<value temporarily
> unavailable, due to optimizations>, pfn=<value temporarily
> unavailable, due to optimizations>, data=<value temporarily
> unavailable, due to optimizations>, err=<value temporarily
> unavailable, due to optimizations>) at /GCC/gcc-live-trunk/libiberty/
> objfile.c:173
> #2  0x0001dc60 in lto_obj_build_section_table (lto_file=<value
> temporarily unavailable, due to optimizations>) at
> /GCC/gcc-live-trunk/ gcc/lto/lto-objfile.c:270
> #3  0x0001af80 in lto_read_all_file_options () at /GCC/gcc-live-trunk/
> gcc/lto/lto.c:2052
> #4  0x00003960 in lto_post_options (pfilename=<value temporarily
> unavailable, due to optimizations>) at
> /GCC/gcc-live-trunk/gcc/lto/lto- 
> lang.c:709
> #5  0x004f0eec in toplev_main (argc=15, argv=Cannot access memory at
> address 0x1c
> ) at /GCC/gcc-live-trunk/gcc/toplev.c:1778
> #6  0x00001944 in start ()
>
> if you need more analysis - ping me with what and I'll try and do sth
> -- or maybe Jack can help with a user on his machine.

Thanks for looking at it.  For this problem, I've attached a new version
of libiberty/objfile-mach-o.c.

In general I'm going to need somebody who can debug the code running on
Darwin.

Ian


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: objfile-mach-o.c --]
[-- Type: text/x-csrc, Size: 29522 bytes --]

/* objfile-mach-o.c -- routines to manipulate Mach-O object files.
   Copyright 2010 Free Software Foundation, Inc.
   Written by Ian Lance Taylor, Google.

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, 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, 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA.  */

#include "config.h"
#include "libiberty.h"
#include "objfile.h"

#include <stddef.h>

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif

#ifdef HAVE_STRING_H
#include <string.h>
#endif

#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif

#include "objfile-common.h"

/* Mach-O structures and constants.  */

/* Mach-O header (32-bit version).  */

struct mach_o_header_32
{
  unsigned char magic[4];	/* Magic number.  */
  unsigned char cputype[4];	/* CPU that this object is for.  */
  unsigned char cpusubtype[4];	/* CPU subtype.  */
  unsigned char filetype[4];	/* Type of file.  */
  unsigned char ncmds[4];	/* Number of load commands.  */
  unsigned char sizeofcmds[4];	/* Total size of load commands.  */
  unsigned char flags[4];	/* Flags for special featues.  */
};

/* Mach-O header (64-bit version).  */

struct mach_o_header_64
{
  unsigned char magic[4];	/* Magic number.  */
  unsigned char cputype[4];	/* CPU that this object is for.  */
  unsigned char cpusubtype[4];	/* CPU subtype.  */
  unsigned char filetype[4];	/* Type of file.  */
  unsigned char ncmds[4];	/* Number of load commands.  */
  unsigned char sizeofcmds[4];	/* Total size of load commands.  */
  unsigned char flags[4];	/* Flags for special featues.  */
  unsigned char reserved[4];	/* Reserved.  Duh.  */
};

/* For magic field in header.  */

#define MACH_O_MH_MAGIC			0xfeedface
#define MACH_O_MH_MAGIC_64		0xfeedfacf

/* For filetype field in header.  */

#define MACH_O_MH_OBJECT		0x01

/* A Mach-O file is a list of load commands.  This is the header of a
   load command.  */

struct mach_o_load_command
{
  unsigned char cmd[4];		/* The type of load command.  */
  unsigned char cmdsize[4];	/* Size in bytes of entire command.  */
};

/* For cmd field in load command.   */

#define MACH_O_LC_SEGMENT		0x01
#define MACH_O_LC_SEGMENT_64		0x19

/* LC_SEGMENT load command.  */

struct mach_o_segment_command_32
{
  unsigned char cmd[4];		/* The type of load command (LC_SEGMENT).  */
  unsigned char cmdsize[4];	/* Size in bytes of entire command.  */
  unsigned char segname[16];	/* Name of this segment.  */
  unsigned char vmaddr[4];	/* Virtual memory address of this segment.  */
  unsigned char vmsize[4];	/* Size there, in bytes.  */
  unsigned char fileoff[4];	/* Offset in bytes of the data to be mapped.  */
  unsigned char filesize[4];	/* Size in bytes on disk.  */
  unsigned char maxprot[4];	/* Maximum permitted vmem protection.  */
  unsigned char initprot[4];	/* Initial vmem protection.  */
  unsigned char nsects[4];	/* Number of sections in this segment.  */
  unsigned char flags[4];	/* Flags that affect the loading.  */
};

/* LC_SEGMENT_64 load command.  */

struct mach_o_segment_command_64
{
  unsigned char cmd[4];		/* The type of load command (LC_SEGMENT_64).  */
  unsigned char cmdsize[4];	/* Size in bytes of entire command.  */
  unsigned char segname[16];	/* Name of this segment.  */
  unsigned char vmaddr[8];	/* Virtual memory address of this segment.  */
  unsigned char vmsize[8];	/* Size there, in bytes.  */
  unsigned char fileoff[8];	/* Offset in bytes of the data to be mapped.  */
  unsigned char filesize[8];	/* Size in bytes on disk.  */
  unsigned char maxprot[4];	/* Maximum permitted vmem protection.  */
  unsigned char initprot[4];	/* Initial vmem protection.  */
  unsigned char nsects[4];	/* Number of sections in this segment.  */
  unsigned char flags[4];	/* Flags that affect the loading.  */
};

/* 32-bit section header.  */

struct mach_o_section_32
{
  unsigned char sectname[16];	/* Section name.  */
  unsigned char segname[16];	/* Segment that the section belongs to.  */
  unsigned char addr[4];	/* Address of this section in memory.  */
  unsigned char size[4];	/* Size in bytes of this section.  */
  unsigned char offset[4];	/* File offset of this section.  */
  unsigned char align[4];	/* log2 of this section's alignment.  */
  unsigned char reloff[4];	/* File offset of this section's relocs.  */
  unsigned char nreloc[4];	/* Number of relocs for this section.  */
  unsigned char flags[4];	/* Section flags/attributes.  */
  unsigned char reserved1[4];
  unsigned char reserved2[4];
};

/* 64-bit section header.  */

struct mach_o_section_64
{
  unsigned char sectname[16];	/* Section name.  */
  unsigned char segname[16];	/* Segment that the section belongs to.  */
  unsigned char addr[8];	/* Address of this section in memory.  */
  unsigned char size[8];	/* Size in bytes of this section.  */
  unsigned char offset[4];	/* File offset of this section.  */
  unsigned char align[4];	/* log2 of this section's alignment.  */
  unsigned char reloff[4];	/* File offset of this section's relocs.  */
  unsigned char nreloc[4];	/* Number of relocs for this section.  */
  unsigned char flags[4];	/* Section flags/attributes.  */
  unsigned char reserved1[4];
  unsigned char reserved2[4];
  unsigned char reserved3[4];
};

/* Flags for Mach-O sections.  */

#define MACH_O_S_ATTR_DEBUG			0x02000000

/* The length of a segment or section name.  */

#define MACH_O_NAME_LEN (16)

/* A GNU specific extension for long section names.  */

#define GNU_SECTION_NAMES "__section_names"

/* Private data for an objfile_read.  */

struct objfile_mach_o_read
{
  /* User specified segment name.  */
  char *segment_name;
  /* Magic number.  */
  unsigned int magic;
  /* Whether this file is big-endian.  */
  int is_big_endian;
  /* CPU type from header.  */
  unsigned int cputype;
  /* CPU subtype from header.  */
  unsigned int cpusubtype;
  /* Number of commands, from header.  */
  unsigned int ncmds;
  /* Flags from header.  */
  unsigned int flags;
  /* Reserved field from header, only used on 64-bit.  */
  unsigned int reserved;
};

/* Private data for an objfile_attributes.  */

struct objfile_mach_o_attributes
{
  /* Magic number.  */
  unsigned int magic;
  /* Whether this file is big-endian.  */
  int is_big_endian;
  /* CPU type from header.  */
  unsigned int cputype;
  /* CPU subtype from header.  */
  unsigned int cpusubtype;
  /* Flags from header.  */
  unsigned int flags;
  /* Reserved field from header, only used on 64-bit.  */
  unsigned int reserved;
};

/* See if we have a Mach-O file.  */

static void *
objfile_mach_o_match (unsigned char header[OBJFILE_MATCH_HEADER_LEN],
		      int descriptor, off_t offset, const char *segment_name,
		      const char **errmsg, int *err)
{
  unsigned int magic;
  int is_big_endian;
  unsigned int (*fetch_32) (const unsigned char *);
  unsigned int filetype;
  struct objfile_mach_o_read *omr;
  unsigned char buf[sizeof (struct mach_o_header_64)];
  unsigned char *b;

  magic = objfile_fetch_big_32 (header);
  if (magic == MACH_O_MH_MAGIC || magic == MACH_O_MH_MAGIC_64)
    is_big_endian = 1;
  else
    {
      magic = objfile_fetch_little_32 (header);
      if (magic == MACH_O_MH_MAGIC || magic == MACH_O_MH_MAGIC_64)
	is_big_endian = 0;
      else
	{
	  *errmsg = NULL;
	  *err = 0;
	  return NULL;
	}
    }

#ifndef UNSIGNED_64BIT_TYPE
  if (magic == MACH_O_MH_MAGIC_64)
    {
      *errmsg = "64-bit Mach-O objects not supported";
      *err = 0;
      return NULL;
    }
#endif

  /* We require the user to provide a segment name.  This is
     unfortunate but I don't see any good choices here.  */

  if (segment_name == NULL)
    {
      *errmsg = "Mach-O file found but no segment name specified";
      *err = 0;
      return NULL;
    }

  if (strlen (segment_name) > MACH_O_NAME_LEN)
    {
      *errmsg = "Mach-O segment name too long";
      *err = 0;
      return NULL;
    }

  /* The 32-bit and 64-bit headers are similar enough that we can use
     the same code.  */

  fetch_32 = is_big_endian ? objfile_fetch_big_32 : objfile_fetch_little_32;

  if (!objfile_internal_read (descriptor, offset, buf,
			      (magic == MACH_O_MH_MAGIC
			       ? sizeof (struct mach_o_header_32)
			       : sizeof (struct mach_o_header_64)),
			      errmsg, err))
    return NULL;

  b = &buf[0];

  filetype = (*fetch_32) (b + offsetof (struct mach_o_header_32, filetype));
  if (filetype != MACH_O_MH_OBJECT)
    {
      *errmsg = "Mach-O file is not object file";
      *err = 0;
      return NULL;
    }

  omr = XNEW (struct objfile_mach_o_read);
  omr->segment_name = xstrdup (segment_name);
  omr->magic = magic;
  omr->is_big_endian = is_big_endian;
  omr->cputype = (*fetch_32) (b + offsetof (struct mach_o_header_32, cputype));
  omr->cpusubtype = (*fetch_32) (b
				 + offsetof (struct mach_o_header_32,
					     cpusubtype));
  omr->ncmds = (*fetch_32) (b + offsetof (struct mach_o_header_32, ncmds));
  omr->flags = (*fetch_32) (b + offsetof (struct mach_o_header_32, flags));
  if (magic == MACH_O_MH_MAGIC)
    omr->reserved = 0;
  else
    omr->reserved = (*fetch_32) (b
				 + offsetof (struct mach_o_header_64,
					     reserved));

  return (void *) omr;
}

/* Get the file offset and size from a section header.  */

static void
objfile_mach_o_section_info (int is_big_endian, int is_32,
			     const unsigned char *sechdr, off_t *offset,
			     size_t *size)
{
  unsigned int (*fetch_32) (const unsigned char *);
  ulong_type (*fetch_64) (const unsigned char *);

  fetch_32 = (is_big_endian
	      ? objfile_fetch_big_32
	      : objfile_fetch_little_32);

  fetch_64 = NULL;
#ifdef UNSIGNED_64BIT_TYPE
  fetch_64 = (is_big_endian
	      ? objfile_fetch_big_64
	      : objfile_fetch_little_64);
#endif

  if (is_32)
    {
      *offset = fetch_32 (sechdr
			  + offsetof (struct mach_o_section_32, offset));
      *size = fetch_32 (sechdr
			+ offsetof (struct mach_o_section_32, size));
    }
  else
    {
      *offset = fetch_32 (sechdr
			  + offsetof (struct mach_o_section_64, offset));
      *size = fetch_64 (sechdr
			+ offsetof (struct mach_o_section_64, size));
    }
}

/* Handle a segment in a Mach-O file.  Return 1 if we should continue,
   0 if the caller should return.  */

static int
objfile_mach_o_segment (objfile_read *objfile, off_t offset,
			const unsigned char *segbuf,
			int (*pfn) (void *, const char *, off_t offset,
				    off_t length),
			void *data,
			const char **errmsg, int *err)
{
  struct objfile_mach_o_read *omr =
    (struct objfile_mach_o_read *) objfile->data;
  unsigned int (*fetch_32) (const unsigned char *);
  int is_32;
  size_t seghdrsize;
  size_t sechdrsize;
  size_t sectname_offset;
  unsigned int nsects;
  unsigned char *secdata;
  unsigned int i;
  unsigned int strtab_index;
  char *strtab;
  size_t strtab_size;

  fetch_32 = (omr->is_big_endian
	      ? objfile_fetch_big_32
	      : objfile_fetch_little_32);

  is_32 = omr->magic == MACH_O_MH_MAGIC;

  if (is_32)
    {
      seghdrsize = sizeof (struct mach_o_segment_command_32);
      sechdrsize = sizeof (struct mach_o_section_32);
      sectname_offset = offsetof (struct mach_o_section_32, sectname);
      nsects = (*fetch_32) (segbuf
			    + offsetof (struct mach_o_segment_command_32,
					nsects));
    }
  else
    {
      seghdrsize = sizeof (struct mach_o_segment_command_64);
      sechdrsize = sizeof (struct mach_o_section_64);
      sectname_offset = offsetof (struct mach_o_section_64, sectname);
      nsects = (*fetch_32) (segbuf
			    + offsetof (struct mach_o_segment_command_64,
					nsects));
    }

  secdata = XNEWVEC (unsigned char, nsects * sechdrsize);
  if (!objfile_internal_read (objfile->descriptor, offset + seghdrsize,
			      secdata, nsects * sechdrsize, errmsg, err))
    {
      XDELETEVEC (secdata);
      return 0;
    }

  /* Scan for a __section_names section.  This is in effect a GNU
     extension that permits section names longer than 16 chars.  */

  for (i = 0; i < nsects; ++i)
    {
      size_t nameoff;

      nameoff = i * sechdrsize + sectname_offset;
      if (strcmp ((char *) secdata + nameoff, GNU_SECTION_NAMES) == 0)
	break;
    }

  strtab_index = i;
  if (strtab_index >= nsects)
    {
      strtab = NULL;
      strtab_size = 0;
    }
  else
    {
      off_t strtab_offset;

      objfile_mach_o_section_info (omr->is_big_endian, is_32,
				   secdata + strtab_index * sechdrsize,
				   &strtab_offset, &strtab_size);
      strtab = XNEWVEC (char, strtab_size);
      if (!objfile_internal_read (objfile->descriptor, strtab_offset,
				  (unsigned char *) strtab, strtab_size,
				  errmsg, err))
	{
	  XDELETEVEC (strtab);
	  XDELETEVEC (secdata);
	  return 0;
	}
    }

  /* Process the sections.  */

  for (i = 0; i < nsects; ++i)
    {
      const unsigned char *sechdr;
      char namebuf[MACH_O_NAME_LEN + 1];
      char *name;
      off_t secoffset;
      size_t secsize;

      if (i == strtab_index)
	continue;

      sechdr = secdata + i * sechdrsize;
      memcpy (namebuf, sechdr + sectname_offset, MACH_O_NAME_LEN);
      namebuf[MACH_O_NAME_LEN] = '\0';

      name = &namebuf[0];
      if (strtab != NULL && name[0] == '_' && name[1] == '_')
	{
	  unsigned long stringoffset;

	  if (sscanf (name + 2, "%08lX", &stringoffset) == 1)
	    {
	      if (stringoffset >= strtab_size)
		{
		  *errmsg = "section name offset out of range";
		  *err = 0;
		  XDELETEVEC (strtab);
		  XDELETEVEC (secdata);
		  return 0;
		}

	      name = strtab + stringoffset;
	    }
	}

      objfile_mach_o_section_info (omr->is_big_endian, is_32, sechdr,
				   &secoffset, &secsize);

      if (!(*pfn) (data, name, secoffset, secsize))
	{
	  *errmsg = NULL;
	  *err = 0;
	  XDELETEVEC (strtab);
	  XDELETEVEC (secdata);
	  return 0;
	}
    }

  XDELETEVEC (strtab);
  XDELETEVEC (secdata);

  return 1;
}

/* Find all sections in a Mach-O file.  */

static const char *
objfile_mach_o_find_sections (objfile_read *objfile,
			      int (*pfn) (void *, const char *, off_t offset,
					  off_t length),
			      void *data,
			      int *err)
{
  struct objfile_mach_o_read *omr =
    (struct objfile_mach_o_read *) objfile->data;
  off_t offset;
  size_t seghdrsize;
  unsigned int (*fetch_32) (const unsigned char *);
  const char *errmsg;
  unsigned int i;

  if (omr->magic == MACH_O_MH_MAGIC)
    {
      offset = sizeof (struct mach_o_header_32);
      seghdrsize = sizeof (struct mach_o_segment_command_32);
    }
  else
    {
      offset = sizeof (struct mach_o_header_64);
      seghdrsize = sizeof (struct mach_o_segment_command_64);
    }

  fetch_32 = (omr->is_big_endian
	      ? objfile_fetch_big_32
	      : objfile_fetch_little_32);

  for (i = 0; i < omr->ncmds; ++i)
    {
      unsigned char loadbuf[sizeof (struct mach_o_load_command)];
      unsigned int cmd;
      unsigned int cmdsize;

      if (!objfile_internal_read (objfile->descriptor,
				  objfile->offset + offset,
				  loadbuf, sizeof (struct mach_o_load_command),
				  &errmsg, err))
	return errmsg;

      cmd = (*fetch_32) (loadbuf + offsetof (struct mach_o_load_command, cmd));
      cmdsize = (*fetch_32) (loadbuf
			     + offsetof (struct mach_o_load_command, cmdsize));

      if (cmd == MACH_O_LC_SEGMENT || cmd == MACH_O_LC_SEGMENT_64)
	{
	  unsigned char segbuf[sizeof (struct mach_o_segment_command_64)];
	  char *segname;

	  if (!objfile_internal_read (objfile->descriptor, offset, segbuf,
				      seghdrsize, &errmsg, err))
	    return errmsg;

	  /* The segment name is in the same position for both 32-bit
	     and 64-bit.  */
	  segname = (char *) (&segbuf[0]
			      + offsetof (struct mach_o_segment_command_32,
					  segname));
	  if (strncmp (omr->segment_name, segname, MACH_O_NAME_LEN) == 0)
	    {
	      int r;

	      r = objfile_mach_o_segment (objfile, offset, segbuf, pfn,
					  data, &errmsg, err);
	      if (!r)
		return errmsg;

	      /* We can probably just return NULL here.  There
		 probably won't be another function with the same
		 name.  */
	    }
	}

      offset += cmdsize;
    }

  return NULL;
}

/* Fetch the attributes for an objfile_read.  */

static void *
objfile_mach_o_fetch_attributes (objfile_read *objfile,
				 const char **errmsg ATTRIBUTE_UNUSED,
				 int *err ATTRIBUTE_UNUSED)
{
  struct objfile_mach_o_read *omr =
    (struct objfile_mach_o_read *) objfile->data;
  struct objfile_mach_o_attributes *ret;

  ret = XNEW (struct objfile_mach_o_attributes);
  ret->magic = omr->magic;
  ret->is_big_endian = omr->is_big_endian;
  ret->cputype = omr->cputype;
  ret->cpusubtype = omr->cpusubtype;
  ret->flags = omr->flags;
  ret->reserved = omr->reserved;
  return ret;
}

/* Release the private data for an objfile_read.  */

static void
objfile_mach_o_release_read (void *data)
{
  struct objfile_mach_o_read *omr =
    (struct objfile_mach_o_read *) data;

  free (omr->segment_name);
  XDELETE (omr);
}

/* Compare two attributes structures.  */

static const char *
objfile_mach_o_attributes_compare (void *data1, void *data2, int *err)
{
  struct objfile_mach_o_attributes *attrs1 =
    (struct objfile_mach_o_attributes *) data1;
  struct objfile_mach_o_attributes *attrs2 =
    (struct objfile_mach_o_attributes *) data2;

  if (attrs1->magic != attrs2->magic
      || attrs1->is_big_endian != attrs2->is_big_endian
      || attrs1->cputype != attrs2->cputype)
    {
      *err = 0;
      return "Mach-O object format mismatch";
    }
  return NULL;
}

/* Release the private data for an attributes structure.  */

static void
objfile_mach_o_release_attributes (void *data)
{
  XDELETE (data);
}

/* Prepare to write out a file.  */

static void *
objfile_mach_o_start_write (void *attributes_data,
			    const char **errmsg ATTRIBUTE_UNUSED,
			    int *err ATTRIBUTE_UNUSED)
{
  struct objfile_mach_o_attributes *attrs =
    (struct objfile_mach_o_attributes *) attributes_data;
  struct objfile_mach_o_attributes *ret;

  /* We're just going to record the attributes, but we need to make a
     copy because the user may delete them.  */
  ret = XNEW (struct objfile_mach_o_attributes);
  *ret = *attrs;
  return ret;
}

/* Write out the header of a Mach-O file.  */

static int
objfile_mach_o_write_header (objfile_write *objfile, int descriptor,
			     size_t nsects, const char **errmsg, int *err)
{
  struct objfile_mach_o_attributes *attrs =
    (struct objfile_mach_o_attributes *) objfile->data;
  void (*set_32) (unsigned char *, unsigned int);
  unsigned char hdrbuf[sizeof (struct mach_o_header_64)];
  unsigned char *hdr;
  size_t wrsize;

  set_32 = (attrs->is_big_endian
	    ? objfile_set_big_32
	    : objfile_set_little_32);

  memset (hdrbuf, 0, sizeof hdrbuf);

  /* The 32-bit and 64-bit headers start out the same.  */

  hdr = &hdrbuf[0];
  set_32 (hdr + offsetof (struct mach_o_header_32, magic), attrs->magic);
  set_32 (hdr + offsetof (struct mach_o_header_32, cputype), attrs->cputype);
  set_32 (hdr + offsetof (struct mach_o_header_32, cpusubtype),
	  attrs->cpusubtype);
  set_32 (hdr + offsetof (struct mach_o_header_32, filetype), MACH_O_MH_OBJECT);
  set_32 (hdr + offsetof (struct mach_o_header_32, ncmds), 1);
  set_32 (hdr + offsetof (struct mach_o_header_32, flags), attrs->flags);
  if (attrs->magic == MACH_O_MH_MAGIC)
    {
      wrsize = sizeof (struct mach_o_header_32);
      set_32 (hdr + offsetof (struct mach_o_header_32, sizeofcmds),
	      (sizeof (struct mach_o_segment_command_32)
	       + nsects * sizeof (struct mach_o_section_32)));
    }
  else
    {
      set_32 (hdr + offsetof (struct mach_o_header_64, sizeofcmds),
	      (sizeof (struct mach_o_segment_command_64)
	       + nsects * sizeof (struct mach_o_section_64)));
      set_32 (hdr + offsetof (struct mach_o_header_64, reserved),
	      attrs->reserved);
      wrsize = sizeof (struct mach_o_header_64);
    }

  return objfile_internal_write (descriptor, 0, hdrbuf, wrsize, errmsg, err);
}

/* Write a Mach-O section header.  */

static int
objfile_mach_o_write_section_header (objfile_write *objfile, int descriptor,
				     size_t sechdr_offset, const char *name,
				     size_t secaddr, size_t secsize,
				     size_t offset, unsigned int align,
				     const char **errmsg, int *err)
{
  struct objfile_mach_o_attributes *attrs =
    (struct objfile_mach_o_attributes *) objfile->data;
  void (*set_32) (unsigned char *, unsigned int);
  unsigned char hdrbuf[sizeof (struct mach_o_section_64)];
  unsigned char *hdr;
  size_t sechdrsize;

  set_32 = (attrs->is_big_endian
	    ? objfile_set_big_32
	    : objfile_set_little_32);

  memset (hdrbuf, 0, sizeof hdrbuf);

  hdr = &hdrbuf[0];
  if (attrs->magic == MACH_O_MH_MAGIC)
    {
      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, sectname),
	       name, MACH_O_NAME_LEN);
      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, segname),
	       objfile->segment_name, MACH_O_NAME_LEN);
      set_32 (hdr + offsetof (struct mach_o_section_32, addr), secaddr);
      set_32 (hdr + offsetof (struct mach_o_section_32, size), secsize);
      set_32 (hdr + offsetof (struct mach_o_section_32, offset), offset);
      set_32 (hdr + offsetof (struct mach_o_section_32, align), align);
      /* reloff left as zero.  */
      /* nreloc left as zero.  */
      set_32 (hdr + offsetof (struct mach_o_section_32, flags),
	      MACH_O_S_ATTR_DEBUG);
      /* reserved1 left as zero.  */
      /* reserved2 left as zero.  */
      sechdrsize = sizeof (struct mach_o_section_32);
    }
  else
    {
#ifdef UNSIGNED_64BIT_TYPE
      void (*set_64) (unsigned char *, ulong_type);

      set_64 = (attrs->is_big_endian
		? objfile_set_big_64
		: objfile_set_little_64);

      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, sectname),
	       name, MACH_O_NAME_LEN);
      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, segname),
	       objfile->segment_name, MACH_O_NAME_LEN);
      set_64 (hdr + offsetof (struct mach_o_section_64, addr), secaddr);
      set_64 (hdr + offsetof (struct mach_o_section_64, size), secsize);
      set_32 (hdr + offsetof (struct mach_o_section_64, offset), offset);
      set_32 (hdr + offsetof (struct mach_o_section_64, align), align);
      /* reloff left as zero.  */
      /* nreloc left as zero.  */
      set_32 (hdr + offsetof (struct mach_o_section_64, flags),
	      MACH_O_S_ATTR_DEBUG);
      /* reserved1 left as zero.  */
      /* reserved2 left as zero.  */
      /* reserved3 left as zero.  */
#endif
      sechdrsize = sizeof (struct mach_o_section_64);
    }

  return objfile_internal_write (descriptor, sechdr_offset, hdr,
				 sechdrsize, errmsg, err);
}

/* Write out the single segment and the sections of a Mach-O file.  */

static int
objfile_mach_o_write_segment (objfile_write *objfile, int descriptor,
			      size_t nsects, const char **errmsg, int *err)
{
  struct objfile_mach_o_attributes *attrs =
    (struct objfile_mach_o_attributes *) objfile->data;
  void (*set_32) (unsigned char *, unsigned int);
  size_t hdrsize;
  size_t seghdrsize;
  size_t sechdrsize;
  size_t cmdsize;
  size_t offset;
  size_t sechdr_offset;
  size_t secaddr;
  unsigned int name_offset;
  objfile_write_section *section;
  unsigned char hdrbuf[sizeof (struct mach_o_segment_command_64)];
  unsigned char *hdr;

  set_32 = (attrs->is_big_endian
	    ? objfile_set_big_32
	    : objfile_set_little_32);

  /* Write out the sections first.  */

  if (attrs->magic == MACH_O_MH_MAGIC)
    {
      hdrsize = sizeof (struct mach_o_header_32);
      seghdrsize = sizeof (struct mach_o_segment_command_32);
      sechdrsize = sizeof (struct mach_o_section_32);
    }
  else
    {
      hdrsize = sizeof (struct mach_o_header_64);
      seghdrsize = sizeof (struct mach_o_segment_command_64);
      sechdrsize = sizeof (struct mach_o_section_64);
    }

  sechdr_offset = hdrsize + seghdrsize;
  cmdsize = seghdrsize + nsects * sechdrsize;
  offset = hdrsize + cmdsize;
  name_offset = 0;
  secaddr = 0;

  for (section = objfile->sections; section != NULL; section = section->next)
    {
      size_t mask;
      size_t new_offset;
      size_t secsize;
      struct objfile_write_section_buffer *buffer;
      char namebuf[MACH_O_NAME_LEN + 1];

      mask = (1U << section->align) - 1;
      new_offset = offset + mask;
      new_offset &= ~ mask;
      while (new_offset > offset)
	{
	  unsigned char zeroes[16];
	  size_t write;

	  memset (zeroes, 0, sizeof zeroes);
	  write = new_offset - offset;
	  if (write > sizeof zeroes)
	    write = sizeof zeroes;
	  if (!objfile_internal_write (descriptor, offset, zeroes, write,
				       errmsg, err))
	    return 0;
	  offset += write;
	}

      secsize = 0;
      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
	{
	  if (!objfile_internal_write (descriptor, offset + secsize,
				       (const unsigned char *) buffer->buffer,
				       buffer->size, errmsg, err))
	    return 0;
	  secsize += buffer->size;
	}

      snprintf (namebuf, sizeof namebuf, "__%08X", name_offset);
      if (!objfile_mach_o_write_section_header (objfile, descriptor,
						sechdr_offset, namebuf,
						secaddr, secsize, offset,
						section->align, errmsg, err))
	return 0;

      sechdr_offset += sechdrsize;
      offset += secsize;
      name_offset += strlen (section->name) + 1;
      secaddr += secsize;
    }

  /* Write out the section names.  */

  if (!objfile_mach_o_write_section_header (objfile, descriptor, sechdr_offset,
					    GNU_SECTION_NAMES, secaddr,
					    name_offset, offset, 0,
					    errmsg, err))
    return 0;

  for (section = objfile->sections; section != NULL; section = section->next)
    {
      size_t namelen;

      namelen = strlen (section->name) + 1;
      if (!objfile_internal_write (descriptor, offset,
				   (const unsigned char *) section->name,
				   namelen, errmsg, err))
	return 0;
      offset += namelen;
    }

  /* Write out the segment header.  */

  memset (hdrbuf, 0, sizeof hdrbuf);

  hdr = &hdrbuf[0];
  if (attrs->magic == MACH_O_MH_MAGIC)
    {
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd),
	      MACH_O_LC_SEGMENT);
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
	      cmdsize);
      strncpy (((char *) hdr
		+ offsetof (struct mach_o_segment_command_32, segname)),
	       objfile->segment_name, MACH_O_NAME_LEN);
      /* vmaddr left as zero.  */
      /* vmsize left as zero.  */
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
	      hdrsize + cmdsize);
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, filesize),
	      offset - (hdrsize + cmdsize));
      /* maxprot left as zero.  */
      /* initprot left as zero.  */
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
	      nsects);
      /* flags left as zero.  */
    }
  else
    {
#ifdef UNSIGNED_64BIT_TYPE
      void (*set_64) (unsigned char *, ulong_type);

      set_64 = (attrs->is_big_endian
		? objfile_set_big_64
		: objfile_set_little_64);

      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd),
	      MACH_O_LC_SEGMENT);
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
	      cmdsize);
      strncpy (((char *) hdr
		+ offsetof (struct mach_o_segment_command_32, segname)),
	       objfile->segment_name, MACH_O_NAME_LEN);
      /* vmaddr left as zero.  */
      /* vmsize left as zero.  */
      set_64 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
	      hdrsize + cmdsize);
      set_64 (hdr + offsetof (struct mach_o_segment_command_32, filesize),
	      offset - (hdrsize + cmdsize));
      /* maxprot left as zero.  */
      /* initprot left as zero.  */
      set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
	      nsects);
      /* flags left as zero.  */
#endif
    }

  return objfile_internal_write (descriptor, hdrsize, hdr, seghdrsize,
				 errmsg, err);
}

/* Write out a complete Mach-O file.  */

static const char *
objfile_mach_o_write_to_file (objfile_write *objfile, int descriptor, int *err)
{
  size_t nsects;
  objfile_write_section *section;
  const char *errmsg;

  /* Start at 1 for symbol_names section.  */
  nsects = 1;
  for (section = objfile->sections; section != NULL; section = section->next)
    ++nsects;

  if (!objfile_mach_o_write_header (objfile, descriptor, nsects, &errmsg, err))
    return errmsg;

  if (!objfile_mach_o_write_segment (objfile, descriptor, nsects, &errmsg, err))
    return errmsg;

  return NULL;
}

/* Release the private data for an objfile_write structure.  */

static void
objfile_mach_o_release_write (void *data)
{
  XDELETE (data);
}

/* The Mach-O functions.  */

const struct objfile_functions objfile_mach_o_functions =
{
  objfile_mach_o_match,
  objfile_mach_o_find_sections,
  objfile_mach_o_fetch_attributes,
  objfile_mach_o_release_read,
  objfile_mach_o_attributes_compare,
  objfile_mach_o_release_attributes,
  objfile_mach_o_start_write,
  objfile_mach_o_write_to_file,
  objfile_mach_o_release_write
};

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

* Re: Discussion about merging Go frontend
  2010-10-29 14:35                     ` Ian Lance Taylor
@ 2010-10-29 15:10                       ` Jack Howarth
  0 siblings, 0 replies; 68+ messages in thread
From: Jack Howarth @ 2010-10-29 15:10 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Dave Korn, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

On Fri, Oct 29, 2010 at 06:49:51AM -0700, Ian Lance Taylor wrote:
> Jack Howarth <howarth@bromo.med.uc.edu> writes:
> 
> >    Doesn't the go compiler require functional split stack support? Mike Stump
> > left me with the impression that split stack support would require additional
> > linker support on darwin.
> 
> The Go compiler can work without split stack support.  The effect is
> that you are limited in the number of goroutines you can create,
> particularly on a 32-bit system.  And you are also limited in the depth
> of recursion and size of local variables you can create.  But you can
> write working Go programs.

Ian,
   Is split stack support unique to the go compiler or might it eventually
be leveraged in the other compilers as well? We could submit a radar for
the addition of split stack support for the linker in Xcode 4.0 or later
but it would helpful if the eventual usage was greater than just the go
compiler.
             Jack

> 
> The objfile patch, however, is not really about Go, although gccgo will
> use it.  It's really about LTO.  If it works for LTO, it will work for
> gccgo.
> 
> Ian

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

* Re: Discussion about merging Go frontend
  2010-10-29  6:56               ` Discussion about merging Go frontend Ian Lance Taylor
  2010-10-29 13:19                 ` Dave Korn
  2010-10-29 13:51                 ` Richard Guenther
@ 2010-10-29 15:30                 ` Mark Mitchell
  2010-10-30  8:07                 ` Richard Henderson
                                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 68+ messages in thread
From: Mark Mitchell @ 2010-10-29 15:30 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Dave Korn, Andi Kleen, Andrew Pinski, gcc, gcc-patches

On 10/28/2010 6:31 PM, Ian Lance Taylor wrote:

> This patch requires approval from the LTO maintainers.  I don't need
> approval for the libiberty changes (if the code stays in libiberty) but
> of course I would appreciate it if somebody could look it over.  I think
> the configure and Makefile changes are sufficiently obvious given the
> other changes as to not require approval.

This all looks good to me, and seems like a reasonable solution.  I
think libiberty is as good a place as any for the routines, FWIW.

Thanks,

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

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

* Re: Discussion about merging Go frontend
  2010-10-29  6:56               ` Discussion about merging Go frontend Ian Lance Taylor
                                   ` (2 preceding siblings ...)
  2010-10-29 15:30                 ` Mark Mitchell
@ 2010-10-30  8:07                 ` Richard Henderson
  2010-10-30 13:59                   ` Dave Korn
  2010-10-31 20:00                   ` Ian Lance Taylor
  2010-10-30 16:31                 ` Dave Korn
                                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 68+ messages in thread
From: Richard Henderson @ 2010-10-30  8:07 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Dave Korn, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

> +extern objfile_read *
> +objfile_open_read (int descriptor, off_t offset, const char *segment_name,
> +		   const char **errmsg, int *err);
...
> +extern objfile_write *
> +objfile_start_write (objfile_attributes *ATTRS, const char *segment_name,
> +		     const char **errmsg, int *err);

Mismatch in naming conventions?  I like the use of "release"
to clearly indicate non-closure of the FD.

> +  shdr_size = (cl == ELFCLASS32
> +	       ? sizeof (Elf32_External_Shdr)
> +	       : sizeof (Elf64_External_Shdr));
> +  memset (buf, 0, shdr_size);

Constant size memset is easier to optimize.  You might as well
zero all of BUF, even if we're not going to use it all.  The
slop between 32 and 64 is minimal.

> +  if (!objfile_internal_read (objfile->descriptor,
> +			      objfile->offset + eor->shoff + shdr_size,
> +			      shdrs,
> +			      shdr_size * (shnum - 1),
> +			      &errmsg, err))

Do we really want to keep re-reading section data for every section
lookup we do?  Can't we do this in objfile_open_read?

> +  set_32 (hdr + offsetof (struct external_scnhdr, s_flags),
> +	  (STYP_DATA | IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_DISCARDABLE
> +	   | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ));

You're not recording alignment in the coff object file?
IMAGE_SCN_ALIGN_<N>BYTES, 1 <= N <= 8192, are all defined
with a simple function in that nibble.


r~

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

* Re: Discussion about merging Go frontend
  2010-10-30  8:07                 ` Richard Henderson
@ 2010-10-30 13:59                   ` Dave Korn
  2010-10-31  0:31                     ` Richard Henderson
  2010-10-31 20:00                   ` Ian Lance Taylor
  1 sibling, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-10-30 13:59 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Ian Lance Taylor, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc,
	gcc-patches

On 30/10/2010 01:23, Richard Henderson wrote:

>> +  if (!objfile_internal_read (objfile->descriptor,
>> +			      objfile->offset + eor->shoff + shdr_size,
>> +			      shdrs,
>> +			      shdr_size * (shnum - 1),
>> +			      &errmsg, err))
> 
> Do we really want to keep re-reading section data for every section
> lookup we do?  Can't we do this in objfile_open_read?

  It should only be necessary to do one section lookup per object file anyway.
 Keep extra data hanging around in memory in the backend just so that we can
write algorithmically inefficient code in the client?  Seems like a bad
tradeoff to me!

>> +  set_32 (hdr + offsetof (struct external_scnhdr, s_flags),
>> +	  (STYP_DATA | IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_DISCARDABLE
>> +	   | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ));
> 
> You're not recording alignment in the coff object file?

  It looks to me like he's recording an alignment of 1 byte.

> IMAGE_SCN_ALIGN_<N>BYTES, 1 <= N <= 8192, are all defined
> with a simple function in that nibble.

  The line you quoted uses IMAGE_SCN_ALIGN_1BYTES.  That's all we'll ever need
for LTO sections.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-10-29  6:56               ` Discussion about merging Go frontend Ian Lance Taylor
                                   ` (3 preceding siblings ...)
  2010-10-30  8:07                 ` Richard Henderson
@ 2010-10-30 16:31                 ` Dave Korn
  2010-10-30 20:02                   ` [PATCH] Enable linker plugin for windows [was Re: Discussion about merging Go frontend] Dave Korn
  2010-11-02 15:12                   ` Discussion about merging Go frontend Ian Lance Taylor
  2010-10-30 19:30                 ` Dave Korn
                                   ` (2 subsequent siblings)
  7 siblings, 2 replies; 68+ messages in thread
From: Dave Korn @ 2010-10-30 16:31 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

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

On 29/10/2010 02:31, Ian Lance Taylor wrote:

> This implements an object file reader/writer which does everything
> required by LTO and gccgo.  The ELF code works.  I have not tested the
> Mach-O and COFF code at all beyond compiling it; I hope that somebody
> else can test those targets and fix them.
> 
> With this patch, libelf is no longer needed.

  Almost, but not quite!  The attached patch switches the lto-plugin over to
use the new objfile reader as well.

lto-plugin/ChangeLog:

	* configure.ac: Don't use libelf, don't source config.gcc.
	(LIBELFLIBS): Delete.
	(LIBELFINC): Delete.
	(LTO_FORMAT): Delete.
	(SYM_STYLE): New AC_SUBST var set based on $target.
	* Makefile.am (LIBELFLIBS): Delete.
	(LIBELFINC): Delete.
	(LTO_FORMAT): Delete.
	(SYM_STYLE): Import.
	(AM_CPPFLAGS): Use it.  Don't use LIBELFINC.
	(liblto_plugin_la_SOURCES): Don't use LTO_FORMAT, don't include
	any object-format-specific source file in the link.
	(liblto_plugin_la_LIBADD): Don't use LIBELFLIBS.
	* configure: Regenerate.
	* Makefile.in: Regenerate.
	* lto-plugin-elf.c: Delete.
	* lto-plugin-coff.c: Delete.
	* lto-plugin.h: Delete.
	* lto-plugin.c (O_BINARY): Definition moved here from lto-plugin.h.
	(LTO_SEGMENT_NAME): New definition.
	(LTO_SECTION_PREFIX): Definition moved here from lto-plugin.h.
	(LTO_SECTION_PREFIX_LEN): New definition.
	(struct sym_aux): Struct definition moved here from lto-plugin.h.
	(struct plugin_symtab): Likewise.
	(struct plugin_objfile): Likewise.
	(struct plugin_objfile): New struct def.
	(enum symbol_style): New enum type.
	(add_symbols): Make static.
	(claimed_files): Likewise.
	(num_claimed_files): Likewise.
	(sym_style): New global.
	(check): Make static.
	(parse_table_entry): Likewise.  Respect sym_style when extracting
	symbol from symtab entry.
	(translate): Make static.
	(resolve_conflicts): Likewise.
	(process_symtab): New function, per-section callback version of
	old object-format-specific handling from deleted lto-plugin-elf.c.
	(claim_file_handler): Convert ELF-specific version from deleted
	lto-plugin-elf.c to objfile interface and move here.
	(process_options): Allow new '-sym-style=' option.
	(onload): Don't call deleted onload_format_checks hook.

  Bootstrapped and tested all languages except java and ada on
x86_64-unknown-linux-gnu, no regressions.  There are still a couple of bugs to
iron out of the COFF-specific part of the objfile reader which I'll have fixed
later today.

  OK for trunk (once the objfile changes have gone in)?

    cheers,
      DaveK


[-- Attachment #2: 2010_10_29_19_53_45_lto-objfile-plugin-part1.diff --]
[-- Type: text/x-c, Size: 19379 bytes --]

Index: lto-plugin/lto-plugin-elf.c
===================================================================
--- lto-plugin/lto-plugin-elf.c	(revision 166059)
+++ lto-plugin/lto-plugin-elf.c	(working copy)
@@ -1,157 +0,0 @@
-/* LTO plugin for gold.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
-   Contributed by Rafael Avila de Espindola (espindola@google.com).
-
-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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-#include <libiberty.h>
-#include <stdlib.h>
-#include <inttypes.h>
-
-/* The presence of gelf.h is checked by the toplevel configure script.  */
-#include <gelf.h>
-
-/* Common definitions that the object format dependent code needs.  */
-#include "lto-plugin.h"
-
-/* Process all lto symtabs of file ELF. */
-
-static int
-process_symtab (Elf *elf, struct plugin_symtab *out)
-{
-  int found = 0;
-  Elf_Scn *section = 0;
-  GElf_Ehdr header;
-  GElf_Ehdr *t = gelf_getehdr (elf, &header);
-  if (t == NULL)
-    return 0;
-  assert (t == &header);
-
-  while ((section = elf_nextscn(elf, section)) != 0)
-    {
-      GElf_Shdr shdr;
-      GElf_Shdr *tshdr = gelf_getshdr (section, &shdr);
-      Elf_Data *symtab;
-      const char *t;
-      assert (tshdr == &shdr);
-      t = elf_strptr (elf, header.e_shstrndx, shdr.sh_name);
-      assert (t != NULL);
-      if (strncmp (t, LTO_SECTION_PREFIX, strlen (LTO_SECTION_PREFIX)) == 0)
-	{
-	  char *s = strrchr (t, '.');
-	  if (s)
-	      sscanf (s, ".%x", &out->id);
-	  symtab = elf_getdata (section, NULL);
-	  translate (symtab->d_buf, symtab->d_buf + symtab->d_size, out);
-	  found++;
-	}
-    }
-  return found;
-}
-
-/* Callback used by gold to check if the plugin will claim FILE. Writes
-   the result in CLAIMED. */
-
-enum ld_plugin_status
-claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
-{
-  enum ld_plugin_status status;
-  Elf *elf;
-  struct plugin_file_info lto_file;
-  int n;
-
-  memset (&lto_file, 0, sizeof (struct plugin_file_info));
-
-  if (file->offset != 0)
-    {
-      char *objname;
-      Elf *archive;
-      off_t offset;
-      /* We pass the offset of the actual file, not the archive header. */
-      int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
-                        (int64_t) file->offset);
-      check (t >= 0, LDPL_FATAL, "asprintf failed");
-      lto_file.name = objname;
-
-      archive = elf_begin (file->fd, ELF_C_READ, NULL);
-      check (elf_kind (archive) == ELF_K_AR, LDPL_FATAL,
-             "Not an archive and offset not 0");
-
-      /* elf_rand expects the offset to point to the ar header, not the
-         object itself. Subtract the size of the ar header (60 bytes).
-         We don't uses sizeof (struct ar_hd) to avoid including ar.h */
-
-      offset = file->offset - 60;
-      check (offset == elf_rand (archive, offset), LDPL_FATAL,
-             "could not seek in archive");
-      elf = elf_begin (file->fd, ELF_C_READ, archive);
-      check (elf != NULL, LDPL_FATAL, "could not find archive member");
-      elf_end (archive);
-    }
-  else
-    {
-      lto_file.name = xstrdup (file->name);
-      elf = elf_begin (file->fd, ELF_C_READ, NULL);
-    }
-  lto_file.handle = file->handle;
-
-  *claimed = 0;
-
-  if (!elf)
-    goto err;
-
-  n = process_symtab (elf, &lto_file.symtab);
-  if (n == 0)
-    goto err;
-
-  if (n > 1)
-    resolve_conflicts (&lto_file.symtab, &lto_file.conflicts);
-
-  status = add_symbols (file->handle, lto_file.symtab.nsyms,
-			lto_file.symtab.syms);
-  check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
-
-  *claimed = 1;
-  num_claimed_files++;
-  claimed_files =
-    xrealloc (claimed_files,
-	      num_claimed_files * sizeof (struct plugin_file_info));
-  claimed_files[num_claimed_files - 1] = lto_file;
-
-  goto cleanup;
-
- err:
-  free (lto_file.name);
-
- cleanup:
-  if (elf)
-    elf_end (elf);
-
-  return LDPS_OK;
-}
-
-/* Method called first thing at onload time to perform sanity checks.  */
-
-enum ld_plugin_status
-onload_format_checks (struct ld_plugin_tv *tv)
-{
-  unsigned version = elf_version (EV_CURRENT);
-  check (version != EV_NONE, LDPL_FATAL, "invalid ELF version");
-  return LDPS_OK;
-}
-
Index: lto-plugin/lto-plugin.h
===================================================================
--- lto-plugin/lto-plugin.h	(revision 166059)
+++ lto-plugin/lto-plugin.h	(working copy)
@@ -1,84 +0,0 @@
-/* Common declarations for LTO plugin for gold and/or GNU ld.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
-   Contributed by Rafael Avila de Espindola (espindola@google.com).
-
-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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include <stdbool.h>
-#include "plugin-api.h"
-
-/* LTO magic section name.  */
-
-#define LTO_SECTION_PREFIX ".gnu.lto_.symtab"
-
-/* The part of the symbol table the plugin has to keep track of. Note that we
-   must keep SYMS until all_symbols_read is called to give the linker time to
-   copy the symbol information. */
-
-struct sym_aux
-{
-  uint32_t slot;
-  unsigned id;
-  unsigned next_conflict;
-};
-
-struct plugin_symtab
-{
-  int nsyms;
-  struct sym_aux *aux;
-  struct ld_plugin_symbol *syms;
-  unsigned id;
-};
-
-/* All that we have to remember about a file. */
-
-struct plugin_file_info
-{
-  char *name;
-  void *handle;
-  struct plugin_symtab symtab;
-  struct plugin_symtab conflicts;
-};
-
-/* These are the methods supplied by one of the object format
-   dependent files lto-plugin-elf.c or lto-plugin-coff.c  */
-
-extern enum ld_plugin_status claim_file_handler
-		(const struct ld_plugin_input_file *file, int *claimed);
-
-extern enum ld_plugin_status onload_format_checks (struct ld_plugin_tv *tv);
-
-/* These methods are made available to the object format
-   dependent files.  */
-
-extern void check (bool gate, enum ld_plugin_level level, const char *text);
-
-extern void translate (char *data, char *end, struct plugin_symtab *out);
-
-extern char *parse_table_entry (char *p, struct ld_plugin_symbol *entry,
-			struct sym_aux *aux);
-
-extern void resolve_conflicts (struct plugin_symtab *t,
-			struct plugin_symtab *conflicts);
-
-/* And this callback function is exposed.  */
-
-extern ld_plugin_add_symbols add_symbols;
-
-/* Along with these two variables.  */
-
-extern struct plugin_file_info *claimed_files;
-extern unsigned int num_claimed_files;
-
Index: lto-plugin/configure.ac
===================================================================
--- lto-plugin/configure.ac	(revision 166059)
+++ lto-plugin/configure.ac	(working copy)
@@ -6,18 +6,21 @@
 AM_MAINTAINER_MODE
 AC_PROG_CC
 AC_SYS_LARGEFILE
-AC_ARG_VAR(LIBELFLIBS,[How to link libelf])
-AC_ARG_VAR(LIBELFINC,[How to find libelf include files])
 AM_PROG_LIBTOOL
 AC_SUBST(target_noncanonical)
-. ${srcdir}/../gcc/config.gcc
-case ${lto_binary_reader} in
-  *coff*) LTO_FORMAT=coff ;;
-  *elf*)  LTO_FORMAT=elf ;;
-  *) AC_MSG_ERROR([LTO plugin is not supported on this target.]) ;;
+# Trying to get this information from gcc's config is tricky.
+case $target in
+  x86_64*-mingw*)
+    SYM_STYLE=-DSYM_STYLE=ss_none
+    ;;
+  *-cygwin* | i?86*-mingw* )
+    SYM_STYLE=-DSYM_STYLE=ss_win32
+    ;;
+  *)
+    SYM_STYLE=-DSYM_STYLE=ss_none
+    ;;
 esac
-
-AC_SUBST(LTO_FORMAT)
+AC_SUBST(SYM_STYLE)
 AC_TYPE_UINT64_T
 AC_CONFIG_FILES(Makefile)
 AC_OUTPUT
Index: lto-plugin/lto-plugin-coff.c
===================================================================
--- lto-plugin/lto-plugin-coff.c	(revision 166059)
+++ lto-plugin/lto-plugin-coff.c	(working copy)
@@ -1,38 +0,0 @@
-/* LTO plugin for gold.
-   Copyright (C) 2010 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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-/* Common definitions that the object format dependent code needs.  */
-#include "lto-plugin.h"
-
-/* Callback used by gold to check if the plugin will claim FILE. Writes
-   the result in CLAIMED. */
-
-enum ld_plugin_status
-claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
-{
-  /* To be implemented; for now, simply do nothing.  */
-  return LDPS_OK;
-}
-
-/* Method called first thing at onload time to perform sanity checks.  */
-
-enum ld_plugin_status
-onload_format_checks (struct ld_plugin_tv *tv)
-{
-  return LDPS_OK;
-}
-
Index: lto-plugin/Makefile.am
===================================================================
--- lto-plugin/Makefile.am	(revision 166059)
+++ lto-plugin/Makefile.am	(working copy)
@@ -7,20 +7,16 @@
 target_noncanonical := @target_noncanonical@
 libexecsubdir := $(libexecdir)/gcc/$(target_noncanonical)/$(gcc_version)

-# How to find libelf
-LIBELFLIBS = @LIBELFLIBS@
-LIBELFINC = @LIBELFINC@
+# Which symbol format to use.
+SYM_STYLE = @SYM_STYLE@

-# Which object format to parse.
-LTO_FORMAT = @LTO_FORMAT@
-
-AM_CPPFLAGS = -I$(top_srcdir)/../include $(LIBELFINC)
+AM_CPPFLAGS = -I$(top_srcdir)/../include $(SYM_STYLE)
 AM_CFLAGS = -Wall -Werror

 libexecsub_LTLIBRARIES = liblto_plugin.la

-liblto_plugin_la_SOURCES = lto-plugin.c lto-plugin-$(LTO_FORMAT).c
-liblto_plugin_la_LIBADD = $(LIBELFLIBS) \
+liblto_plugin_la_SOURCES = lto-plugin.c
+liblto_plugin_la_LIBADD = \
 	$(if $(wildcard ../libiberty/pic/libiberty.a),../libiberty/pic/libiberty.a,)
 liblto_plugin_la_LDFLAGS = -no-undefined -bindir $(libexecsubdir) \
 	$(if $(wildcard ../libiberty/pic/libiberty.a),,-Wc,../libiberty/libiberty.a)
Index: lto-plugin/lto-plugin.c
===================================================================
--- lto-plugin/lto-plugin.c	(revision 166059)
+++ lto-plugin/lto-plugin.c	(working copy)
@@ -46,10 +46,73 @@
 #include <libiberty.h>
 #include <hashtab.h>
 #include "../gcc/lto/common.h"
+#include "objfile.h"
+#include "plugin-api.h"

-/* Common definitions for/from the object format dependent code.  */
-#include "lto-plugin.h"
+/* Handle opening elf files on hosts, such as Windows, that may use
+   text file handling that will break binary access.  */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif

+/* Segment name for LTO sections.  This is only used for Mach-O.
+   FIXME: This needs to be kept in sync with darwin.c.  */
+
+#define LTO_SEGMENT_NAME "__GNU_LTO"
+
+/* LTO magic section name.  */
+
+#define LTO_SECTION_PREFIX	".gnu.lto_.symtab"
+#define LTO_SECTION_PREFIX_LEN	(sizeof (LTO_SECTION_PREFIX) - 1)
+
+/* The part of the symbol table the plugin has to keep track of. Note that we
+   must keep SYMS until all_symbols_read is called to give the linker time to
+   copy the symbol information. */
+
+struct sym_aux
+{
+  uint32_t slot;
+  unsigned id;
+  unsigned next_conflict;
+};
+
+struct plugin_symtab
+{
+  int nsyms;
+  struct sym_aux *aux;
+  struct ld_plugin_symbol *syms;
+  unsigned id;
+};
+
+/* Encapsulates object file data during symbol scan.  */
+struct plugin_objfile
+{
+  int found;
+  objfile_read *objfile;
+  struct plugin_symtab *out;
+  const struct ld_plugin_input_file *file;
+};
+
+/* All that we have to remember about a file. */
+
+struct plugin_file_info
+{
+  char *name;
+  void *handle;
+  struct plugin_symtab symtab;
+  struct plugin_symtab conflicts;
+};
+
+/* Until ASM_OUTPUT_LABELREF can be hookized and decoupled from
+   stdio file streams, we do simple label translation here.  */
+
+enum symbol_style
+{
+  ss_none,	/* No underscore prefix. */
+  ss_win32,	/* Underscore prefix any symbol not beginning with '@'.  */
+  ss_uscore,	/* Underscore prefix all symbols.  */
+};
+
 static char *arguments_file_name;
 static ld_plugin_register_claim_file register_claim_file;
 static ld_plugin_register_all_symbols_read register_all_symbols_read;
@@ -58,14 +121,11 @@
 static ld_plugin_add_input_file add_input_file;
 static ld_plugin_add_input_library add_input_library;
 static ld_plugin_message message;
+static ld_plugin_add_symbols add_symbols;

-/* These are not static because the object format dependent
-   claim_file hooks in lto-plugin-{coff,elf}.c need them.  */
-ld_plugin_add_symbols add_symbols;
+static struct plugin_file_info *claimed_files = NULL;
+static unsigned int num_claimed_files = 0;

-struct plugin_file_info *claimed_files = NULL;
-unsigned int num_claimed_files = 0;
-
 static char **output_files = NULL;
 static unsigned int num_output_files = 0;

@@ -79,7 +139,12 @@
 static bool nop;
 static char *resolution_file = NULL;

-void
+/* Set by default from configure.ac, but can be overridden at runtime
+   by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
+   (in fact, only first letter of style arg is checked.)  */
+static enum symbol_style sym_style = SYM_STYLE;
+
+static void
 check (bool gate, enum ld_plugin_level level, const char *text)
 {
   if (gate)
@@ -100,7 +165,7 @@
    by P and the result is written in ENTRY. The slot number is stored in SLOT.
    Returns the address of the next entry. */

-char *
+static char *
 parse_table_entry (char *p, struct ld_plugin_symbol *entry,
 		   struct sym_aux *aux)
 {
@@ -122,7 +187,24 @@
       LDPV_HIDDEN
     };

-  entry->name = xstrdup (p);
+  switch (sym_style)
+    {
+    case ss_win32:
+      if (p[0] == '@')
+	{
+    /* cf. Duff's device.  */
+    case ss_none:
+	  entry->name = xstrdup (p);
+	  break;
+	}
+    /* FALL-THROUGH.  */
+    case ss_uscore:
+      entry->name = concat ("_", p, NULL);
+      break;
+    default:
+      check (false, LDPL_FATAL, "invalid symbol style requested");
+      break;
+    }
   while (*p)
     p++;
   p++;
@@ -165,7 +247,7 @@
 /* Translate the IL symbol table located between DATA and END. Append the
    slots and symbols to OUT. */

-void
+static void
 translate (char *data, char *end, struct plugin_symtab *out)
 {
   struct sym_aux *aux;
@@ -621,7 +703,7 @@

    XXX how to handle common? */

-void
+static void
 resolve_conflicts (struct plugin_symtab *t, struct plugin_symtab *conflicts)
 {
   htab_t symtab = htab_create (t->nsyms, hash_sym, eq_sym, NULL);
@@ -689,6 +771,120 @@
   htab_delete (symtab);
 }

+/* Process one section of an object file.  */
+
+static int
+process_symtab (void *data, const char *name, off_t offset, off_t length)
+{
+  struct plugin_objfile *obj = (struct plugin_objfile *)data;
+  char *s;
+  char *secdata;
+
+  if (strncmp (name, LTO_SECTION_PREFIX, LTO_SECTION_PREFIX_LEN) != 0)
+    return 1;
+
+  s = strrchr (name, '.');
+  if (s)
+    sscanf (s, ".%x", &obj->out->id);
+  secdata = xmalloc (length);
+  offset += obj->file->offset;
+  if (offset != lseek (obj->file->fd, offset, SEEK_SET)
+	|| length != read (obj->file->fd, secdata, length))
+    {
+      if (message)
+	message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
+      /* Force claim_file_handler to abandon this file.  */
+      obj->found = 0;
+      free (data);
+      return 0;
+    }
+
+  translate (secdata, secdata + length, obj->out);
+  obj->found++;
+  free (data);
+  return 1;
+}
+
+/* Callback used by gold to check if the plugin will claim FILE. Writes
+   the result in CLAIMED. */
+
+static enum ld_plugin_status
+claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
+{
+  enum ld_plugin_status status;
+  struct plugin_objfile obj;
+  struct plugin_file_info lto_file;
+  int err;
+  const char *errmsg;
+
+  memset (&lto_file, 0, sizeof (struct plugin_file_info));
+
+  if (file->offset != 0)
+    {
+      char *objname;
+      /* We pass the offset of the actual file, not the archive header. */
+      int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
+                        (int64_t) file->offset);
+      check (t >= 0, LDPL_FATAL, "asprintf failed");
+      lto_file.name = objname;
+    }
+  else
+    {
+      lto_file.name = xstrdup (file->name);
+    }
+  lto_file.handle = file->handle;
+
+  *claimed = 0;
+  obj.file = file;
+  obj.found = 0;
+  obj.out = &lto_file.symtab;
+  errmsg = NULL;
+  obj.objfile = objfile_open_read (file->fd, file->offset, LTO_SEGMENT_NAME,
+			&errmsg, &err);
+  if (obj.objfile)
+    errmsg = objfile_find_sections (obj.objfile, process_symtab, &obj, &err);
+
+  if (!obj.objfile || errmsg)
+    {
+      if (err && message)
+	message (LDPL_FATAL, "%s: %s: %s", file->name, errmsg,
+		xstrerror (err));
+      else if (message)
+	message (LDPL_FATAL, "%s: %s", file->name, errmsg);
+      goto err;
+    }
+
+  if (obj.found == 0)
+    goto err;
+
+  if (obj.found > 1)
+    resolve_conflicts (&lto_file.symtab, &lto_file.conflicts);
+
+  status = add_symbols (file->handle, lto_file.symtab.nsyms,
+			lto_file.symtab.syms);
+  check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
+
+  *claimed = 1;
+  num_claimed_files++;
+  claimed_files =
+    xrealloc (claimed_files,
+	      num_claimed_files * sizeof (struct plugin_file_info));
+  claimed_files[num_claimed_files - 1] = lto_file;
+
+  goto cleanup;
+
+ err:
+  free (lto_file.name);
+
+ cleanup:
+  if (obj.objfile)
+    objfile_release_read (obj.objfile);
+  if (file->fd >= 0)
+    close (file->fd);
+
+  return LDPS_OK;
+}
+
 /* Parse the plugin options. */

 static void
@@ -706,6 +902,21 @@
       pass_through_items[num_pass_through_items - 1] =
           xstrdup (option + strlen ("-pass-through="));
     }
+  else if (!strncmp (option, "-sym-style=", sizeof ("-sym-style=") - 1))
+    {
+      switch (option[sizeof ("-sym-style=")])
+	{
+	case 'w':
+	  sym_style = ss_win32;
+	  break;
+	case 'u':
+	  sym_style = ss_uscore;
+	  break;
+	default:
+	  sym_style = ss_none;
+	  break;
+	}
+    }
   else
     {
       int size;
@@ -727,10 +938,6 @@
   struct ld_plugin_tv *p;
   enum ld_plugin_status status;

-  status = onload_format_checks (tv);
-  if (status != LDPS_OK)
-    return status;
-
   p = tv;
   while (p->tv_tag)
     {

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

* Re: Discussion about merging Go frontend
  2010-10-29  6:56               ` Discussion about merging Go frontend Ian Lance Taylor
                                   ` (4 preceding siblings ...)
  2010-10-30 16:31                 ` Dave Korn
@ 2010-10-30 19:30                 ` Dave Korn
  2010-10-31 20:18                   ` Ian Lance Taylor
  2010-11-01 17:36                 ` Tom Tromey
  2010-11-06 20:01                 ` Eric Botcazou
  7 siblings, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-10-30 19:30 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

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

On 29/10/2010 02:31, Ian Lance Taylor wrote:

> 	* objfile-coff.c: New file.

  A few bugs have cropped up:

> +      if (namebuf[0] == '/')
> +	{
> +	  size_t strindex;
> +	  char *end;
> +
> +	  strindex = strtol (namebuf, &end, 10);

  Needs to be strtol (namebuf + 1, ....

> +  /* We don't write out any symbols.  We'll see if that causes any
> +     problems.  */

  Not a chance of getting away with that, I'm afraid.  Everything expects
there to be file and section symbols and their auxiliaries.

> +  set_16 (hdr + offsetof (struct external_filehdr, f_magic), attrs->magic);
> +  set_16 (hdr + offsetof (struct external_filehdr, f_magic), nscns);

  Cut'n'pasto.  Second f_magic should be f_nscns.

> +	  name_offset += namelen;

  Also needs to be namelen + 1.

  Attached are the revised version of the file, and a diff to show what I
changed.  With this version, all the tests in gcc.dg/lto/lto.exp pass as
before (i.e. there are still a couple of pre-existing FAILs that aren't affected).

    cheers,
      DaveK

[-- Attachment #2: objfile-coff.c --]
[-- Type: text/plain, Size: 22509 bytes --]

/* objfile-coff.c -- routines to manipulate COFF object files.
   Copyright 2010 Free Software Foundation, Inc.
   Written by Ian Lance Taylor, Google.

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, 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, 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA.  */

#include "config.h"
#include "libiberty.h"
#include "objfile.h"

#include <errno.h>
#include <stddef.h>

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif

#ifdef HAVE_STRING_H
#include <string.h>
#endif

#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif

#include "objfile-common.h"

/* COFF structures and constants.  */

/* COFF file header.  */

struct external_filehdr
{
  unsigned char f_magic[2];	/* magic number			*/
  unsigned char f_nscns[2];	/* number of sections		*/
  unsigned char f_timdat[4];	/* time & date stamp		*/
  unsigned char f_symptr[4];	/* file pointer to symtab	*/
  unsigned char f_nsyms[4];	/* number of symtab entries	*/
  unsigned char f_opthdr[2];	/* sizeof(optional hdr)		*/
  unsigned char f_flags[2];	/* flags			*/
};

/* Bits for filehdr f_flags field.  */

#define F_EXEC			(0x0002)
#define IMAGE_FILE_SYSTEM	(0x1000)
#define IMAGE_FILE_DLL		(0x2000)

/* COFF section header.  */

struct external_scnhdr
{
  unsigned char s_name[8];	/* section name				*/
  unsigned char s_paddr[4];	/* physical address, aliased s_nlib 	*/
  unsigned char s_vaddr[4];	/* virtual address			*/
  unsigned char s_size[4];	/* section size				*/
  unsigned char s_scnptr[4];	/* file ptr to raw data for section 	*/
  unsigned char s_relptr[4];	/* file ptr to relocation		*/
  unsigned char s_lnnoptr[4];	/* file ptr to line numbers		*/
  unsigned char s_nreloc[2];	/* number of relocation entries		*/
  unsigned char s_nlnno[2];	/* number of line number entries	*/
  unsigned char s_flags[4];	/* flags				*/
};

/* The length of the s_name field in struct external_scnhdr.  */

#define SCNNMLEN (8)

/* Bits for scnhdr s_flags field.  This includes some bits defined
   only for PE.  This may need to be moved into coff_magic.  */

#define STYP_DATA			(1 << 6)
#define IMAGE_SCN_ALIGN_1BYTES		(1 << 20)
#define IMAGE_SCN_MEM_DISCARDABLE	(1 << 25)
#define IMAGE_SCN_MEM_SHARED		(1 << 28)
#define IMAGE_SCN_MEM_READ		(1 << 30)

/* COFF symbol table entry.  */

#define E_SYMNMLEN	8	/* # characters in a symbol name	*/

struct external_syment
{
  union
  {
    unsigned char e_name[E_SYMNMLEN];

    struct
    {
      unsigned char e_zeroes[4];
      unsigned char e_offset[4];
    } e;
  } e;

  unsigned char e_value[4];
  unsigned char e_scnum[2];
  unsigned char e_type[2];
  unsigned char e_sclass[1];
  unsigned char e_numaux[1];
};

/* Length allowed for filename in aux sym format 4.  */

#define E_FILNMLEN	18

/* Omits x_sym and other unused variants.  */

union external_auxent
{
  /* Aux sym format 4: file.  */
  union
  {
    char x_fname[E_FILNMLEN];
    struct
    {
      unsigned char x_zeroes[4];
      unsigned char x_offset[4];
    } x_n;
  } x_file;
  /* Aux sym format 5: section.  */
  struct
  {
    unsigned char x_scnlen[4];		/* section length		*/
    unsigned char x_nreloc[2];		/* # relocation entries		*/
    unsigned char x_nlinno[2];		/* # line numbers		*/
    unsigned char x_checksum[4];	/* section COMDAT checksum	*/
    unsigned char x_associated[2];	/* COMDAT assoc section index	*/
    unsigned char x_comdat[1];		/* COMDAT selection number	*/
  } x_scn;
};

/* Symbol-related constants.  */

#define IMAGE_SYM_DEBUG		(-2)
#define IMAGE_SYM_TYPE_NULL	(0)
#define IMAGE_SYM_DTYPE_NULL	(0)
#define IMAGE_SYM_CLASS_STATIC	(3)
#define IMAGE_SYM_CLASS_FILE	(103)

#define IMAGE_SYM_TYPE \
  ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL)

/* Private data for an objfile_read.  */

struct objfile_coff_read
{
  /* Magic number.  */
  unsigned short magic;
  /* Whether the file is big-endian.  */
  unsigned char is_big_endian;
  /* Number of sections.  */
  unsigned short nscns;
  /* File offset of symbol table.  */
  off_t symptr;
  /* Number of symbol table entries.  */
  unsigned int nsyms;
  /* Flags.  */
  unsigned short flags;
  /* Offset of section headers in file.  */
  off_t scnhdr_offset;
};

/* Private data for an objfile_attributes.  */

struct objfile_coff_attributes
{
  /* Magic number.  */
  unsigned short magic;
  /* Whether the file is big-endian.  */
  unsigned char is_big_endian;
  /* Flags.  */
  unsigned short flags;
};

/* There is no magic number which indicates a COFF file as opposed to
   any other sort of file.  Instead, each COFF file starts with a
   two-byte magic number which also indicates the type of the target.
   This struct holds a magic number as well as characteristics of that
   COFF format.  */

struct coff_magic_struct
{
  /* Magic number.  */
  unsigned short magic;
  /* Whether this magic number is for a big-endian file.  */
  unsigned char is_big_endian;
  /* Flag bits, in the f_flags fields, which indicates that this file
     is not a relocatable object file.  There is no flag which
     specifically indicates a relocatable object file, it is only
     implied by the absence of these flags.  */
  unsigned short non_object_flags;
};

/* This is a list of the COFF magic numbers which we recognize, namely
   the ones used on Windows.  More can be added as needed.  */

static const struct coff_magic_struct coff_magic[] =
{
  /* i386.  */
  { 0x14c, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL },
  /* x86_64.  */
  { 0x8664, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL }
};

/* See if we have a COFF file.  */

static void *
objfile_coff_match (unsigned char header[OBJFILE_MATCH_HEADER_LEN],
		    int descriptor, off_t offset,
		    const char *segment_name ATTRIBUTE_UNUSED,
		    const char **errmsg, int *err)
{
  size_t c;
  unsigned short magic_big;
  unsigned short magic_little;
  unsigned short magic;
  size_t i;
  int is_big_endian;
  unsigned short (*fetch_16) (const unsigned char *);
  unsigned int (*fetch_32) (const unsigned char *);
  unsigned char hdrbuf[sizeof (struct external_filehdr)];
  unsigned short flags;
  struct objfile_coff_read *ocr;

  c = sizeof (coff_magic) / sizeof (coff_magic[0]);
  magic_big = objfile_fetch_big_16 (header);
  magic_little = objfile_fetch_little_16 (header);
  for (i = 0; i < c; ++i)
    {
      if (coff_magic[i].is_big_endian
	  ? coff_magic[i].magic == magic_big
	  : coff_magic[i].magic == magic_little)
	break;
    }
  if (i >= c)
    {
      *errmsg = NULL;
      *err = 0;
      return NULL;
    }
  is_big_endian = coff_magic[i].is_big_endian;

  magic = is_big_endian ? magic_big : magic_little;
  fetch_16 = (is_big_endian
	      ? objfile_fetch_big_16
	      : objfile_fetch_little_16);
  fetch_32 = (is_big_endian
	      ? objfile_fetch_big_32
	      : objfile_fetch_little_32);

  if (!objfile_internal_read (descriptor, offset, hdrbuf, sizeof hdrbuf,
			      errmsg, err))
    return NULL;

  flags = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_flags));
  if ((flags & coff_magic[i].non_object_flags) != 0)
    {
      *errmsg = "not relocatable object file";
      *err = 0;
      return NULL;
    }

  ocr = XNEW (struct objfile_coff_read);
  ocr->magic = magic;
  ocr->is_big_endian = is_big_endian;
  ocr->nscns = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_nscns));
  ocr->symptr = fetch_32 (hdrbuf
			  + offsetof (struct external_filehdr, f_symptr));
  ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr, f_nsyms));
  ocr->flags = flags;
  ocr->scnhdr_offset = (sizeof (struct external_filehdr)
			+ fetch_16 (hdrbuf + offsetof (struct external_filehdr,
						       f_opthdr)));

  return (void *) ocr;
}

/* Read the string table in a COFF file.  */

static char *
objfile_coff_read_strtab (objfile_read *objfile, size_t *strtab_size,
			  const char **errmsg, int *err)
{
  struct objfile_coff_read *ocr = (struct objfile_coff_read *) objfile->data;
  off_t strtab_offset;
  unsigned char strsizebuf[4];
  size_t strsize;
  char *strtab;

  strtab_offset = ocr->symptr + ocr->nsyms * sizeof (struct external_syment);
  if (!objfile_internal_read (objfile->descriptor, strtab_offset,
			      strsizebuf, 4, errmsg, err))
    return NULL;
  strsize = (ocr->is_big_endian
	     ? objfile_fetch_big_32 (strsizebuf)
	     : objfile_fetch_little_32 (strsizebuf));
  strtab = XNEWVEC (char, strsize);
  if (!objfile_internal_read (objfile->descriptor, strtab_offset,
			      (unsigned char *) strtab, strsize, errmsg, err))
    {
      XDELETEVEC (strtab);
      return NULL;
    }
  *strtab_size = strsize;
  return strtab;
}

/* Find all sections in a COFF file.  */

static const char *
objfile_coff_find_sections (objfile_read *objfile,
			    int (*pfn) (void *, const char *, off_t offset,
					off_t length),
			    void *data,
			    int *err)
{
  struct objfile_coff_read *ocr = (struct objfile_coff_read *) objfile->data;
  size_t scnhdr_size;
  unsigned char *scnbuf;
  const char *errmsg;
  unsigned int (*fetch_32) (const unsigned char *);
  unsigned int nscns;
  char *strtab;
  size_t strtab_size;
  unsigned int i;

  scnhdr_size = sizeof (struct external_scnhdr);
  scnbuf = XNEWVEC (unsigned char, scnhdr_size * ocr->nscns);
  if (!objfile_internal_read (objfile->descriptor,
			      objfile->offset + ocr->scnhdr_offset,
			      scnbuf, scnhdr_size * ocr->nscns, &errmsg, err))
    {
      XDELETEVEC (scnbuf);
      return errmsg;
    }

  fetch_32 = (ocr->is_big_endian
	      ? objfile_fetch_big_32
	      : objfile_fetch_little_32);

  nscns = ocr->nscns;
  strtab = NULL;
  strtab_size = 0;
  for (i = 0; i < nscns; ++i)
    {
      unsigned char *scnhdr;
      unsigned char *scnname;
      char namebuf[SCNNMLEN + 1];
      char *name;
      off_t scnptr;
      unsigned int size;

      scnhdr = scnbuf + i * scnhdr_size;
      scnname = scnhdr + offsetof (struct external_scnhdr, s_name);
      memcpy (namebuf, scnname, SCNNMLEN);
      namebuf[SCNNMLEN] = '\0';
      name = &namebuf[0];
      if (namebuf[0] == '/')
	{
	  size_t strindex;
	  char *end;

	  strindex = strtol (namebuf + 1, &end, 10);
	  if (*end == '\0')
	    {
	      /* The real section name is found in the string
		 table.  */
	      if (strtab == NULL)
		{
		  strtab = objfile_coff_read_strtab (objfile, &strtab_size,
						     &errmsg, err);
		  if (strtab == NULL)
		    {
		      XDELETEVEC (scnbuf);
		      return errmsg;
		    }
		}

	      if (strindex < 4 || strindex >= strtab_size)
		{
		  XDELETEVEC (strtab);
		  XDELETEVEC (scnbuf);
		  *err = 0;
		  return "section string index out of range";
		}

	      name = strtab + strindex;
	    }
	}

      scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr, s_scnptr));
      size = fetch_32 (scnhdr + offsetof (struct external_scnhdr, s_size));

      if (!(*pfn) (data, name, scnptr, size))
	break;
    }

  if (strtab != NULL)
    XDELETEVEC (strtab);
  XDELETEVEC (scnbuf);

  return NULL;
}

/* Fetch the attributes for an objfile_read.  */

static void *
objfile_coff_fetch_attributes (objfile_read *objfile,
			       const char **errmsg ATTRIBUTE_UNUSED,
			       int *err ATTRIBUTE_UNUSED)
{
  struct objfile_coff_read *ocr = (struct objfile_coff_read *) objfile->data;
  struct objfile_coff_attributes *ret;

  ret = XNEW (struct objfile_coff_attributes);
  ret->magic = ocr->magic;
  ret->is_big_endian = ocr->is_big_endian;
  ret->flags = ocr->flags;
  return ret;
}

/* Release the private data for an objfile_read.  */

static void
objfile_coff_release_read (void *data)
{
  XDELETE (data);
}

/* Compare two attributes structures.  */

static const char *
objfile_coff_attributes_compare (void *data1, void *data2, int *err)
{
  struct objfile_coff_attributes *attrs1 =
    (struct objfile_coff_attributes *) data1;
  struct objfile_coff_attributes *attrs2 =
    (struct objfile_coff_attributes *) data2;

  if (attrs1->magic != attrs2->magic
      || attrs1->is_big_endian != attrs2->is_big_endian)
    {
      *err = 0;
      return "COFF object format mismatch";
    }
  return NULL;
}

/* Release the private data for an attributes structure.  */

static void
objfile_coff_release_attributes (void *data)
{
  XDELETE (data);
}

/* Prepare to write out a file.  */

static void *
objfile_coff_start_write (void *attributes_data,
			  const char **errmsg ATTRIBUTE_UNUSED,
			  int *err ATTRIBUTE_UNUSED)
{
  struct objfile_coff_attributes *attrs =
    (struct objfile_coff_attributes *) attributes_data;
  struct objfile_coff_attributes *ret;

  /* We're just going to record the attributes, but we need to make a
     copy because the user may delete them.  */
  ret = XNEW (struct objfile_coff_attributes);
  *ret = *attrs;
  return ret;
}

/* Write out a COFF filehdr.  */

static int
objfile_coff_write_filehdr (objfile_write *objfile, int descriptor,
			    unsigned int nscns, size_t symtab_offset,
			    unsigned int nsyms, const char **errmsg, int *err)
{
  struct objfile_coff_attributes *attrs =
    (struct objfile_coff_attributes *) objfile->data;
  unsigned char hdrbuf[sizeof (struct external_filehdr)];
  unsigned char *hdr;
  void (*set_16) (unsigned char *, unsigned short);
  void (*set_32) (unsigned char *, unsigned int);

  hdr = &hdrbuf[0];

  set_16 = (attrs->is_big_endian
	    ? objfile_set_big_16
	    : objfile_set_little_16);
  set_32 = (attrs->is_big_endian
	    ? objfile_set_big_32
	    : objfile_set_little_32);

  memset (hdr, 0, sizeof (struct external_filehdr));

  set_16 (hdr + offsetof (struct external_filehdr, f_magic), attrs->magic);
  set_16 (hdr + offsetof (struct external_filehdr, f_nscns), nscns);
  /* f_timdat left as zero.  */
  set_32 (hdr + offsetof (struct external_filehdr, f_symptr), symtab_offset);
  set_32 (hdr + offsetof (struct external_filehdr, f_nsyms), nsyms);
  /* f_opthdr left as zero.  */
  set_16 (hdr + offsetof (struct external_filehdr, f_flags), attrs->flags);

  return objfile_internal_write (descriptor, 0, hdrbuf,
				 sizeof (struct external_filehdr),
				 errmsg, err);
}

/* Write out a COFF section header.  */

static int
objfile_coff_write_scnhdr (objfile_write *objfile, int descriptor,
			   const char *name, size_t *name_offset,
			   off_t scnhdr_offset, size_t scnsize, off_t offset,
			   const char **errmsg, int *err)
{
  struct objfile_coff_attributes *attrs =
    (struct objfile_coff_attributes *) objfile->data;
  void (*set_32) (unsigned char *, unsigned int);
  unsigned char hdrbuf[sizeof (struct external_scnhdr)];
  unsigned char *hdr;
  size_t namelen;

  set_32 = (attrs->is_big_endian
	    ? objfile_set_big_32
	    : objfile_set_little_32);

  memset (hdrbuf, 0, sizeof hdrbuf);
  hdr = &hdrbuf[0];

  namelen = strlen (name);
  if (namelen <= SCNNMLEN)
    strncpy ((char *) hdr + offsetof (struct external_scnhdr, s_name), name,
	     SCNNMLEN);
  else
    {
      snprintf ((char *) hdr + offsetof (struct external_scnhdr, s_name),
		SCNNMLEN, "/%lu", (unsigned long) *name_offset);
      *name_offset += namelen + 1;
    }

  /* s_paddr left as zero.  */
  /* s_vaddr left as zero.  */
  set_32 (hdr + offsetof (struct external_scnhdr, s_size), scnsize);
  set_32 (hdr + offsetof (struct external_scnhdr, s_scnptr), offset);
  /* s_relptr left as zero.  */
  /* s_lnnoptr left as zero.  */
  /* s_nreloc left as zero.  */
  /* s_nlnno left as zero.  */
  set_32 (hdr + offsetof (struct external_scnhdr, s_flags),
	  (STYP_DATA | IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_DISCARDABLE
	   | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ));

  return objfile_internal_write (descriptor, scnhdr_offset, hdrbuf,
				 sizeof (struct external_scnhdr),
				 errmsg, err);
}

/* Write out a complete COFF file.  */

static const char *
objfile_coff_write_to_file (objfile_write *objfile, int descriptor, int *err)
{
  struct objfile_coff_attributes *attrs =
    (struct objfile_coff_attributes *) objfile->data;
  unsigned int nscns, secnum;
  objfile_write_section *section;
  off_t scnhdr_offset;
  size_t symtab_offset;
  off_t secsym_offset;
  unsigned int nsyms;
  size_t offset;
  size_t name_offset;
  const char *errmsg;
  unsigned char strsizebuf[4];
  /* The interface doesn't give us access to the name of the input file
     yet.  We want to use its basename for the FILE symbol.  This is
     what 'gas' uses when told to assemble from stdin.  */
  const char *source_filename = "fake";
  union
  {
    struct external_syment sym;
    union external_auxent aux;
  } syms[2];
  void (*set_16) (unsigned char *, unsigned short);
  void (*set_32) (unsigned char *, unsigned int);

  set_16 = (attrs->is_big_endian
	    ? objfile_set_big_16
	    : objfile_set_little_16);
  set_32 = (attrs->is_big_endian
	    ? objfile_set_big_32
	    : objfile_set_little_32);

  nscns = 0;
  for (section = objfile->sections; section != NULL; section = section->next)
    ++nscns;

  scnhdr_offset = sizeof (struct external_filehdr);
  offset = scnhdr_offset + nscns * sizeof (struct external_scnhdr);
  name_offset = 4;
  for (section = objfile->sections; section != NULL; section = section->next)
    {
      size_t mask;
      size_t new_offset;
      size_t scnsize;
      struct objfile_write_section_buffer *buffer;

      mask = (1U << section->align) - 1;
      new_offset = offset & mask;
      new_offset &= ~ mask;
      while (new_offset > offset)
	{
	  unsigned char zeroes[16];
	  size_t write;

	  memset (zeroes, 0, sizeof zeroes);
	  write = new_offset - offset;
	  if (write > sizeof zeroes)
	    write = sizeof zeroes;
	  if (!objfile_internal_write (descriptor, offset, zeroes, write,
				       &errmsg, err))
	    return errmsg;
	}

      scnsize = 0;
      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
	{
	  if (!objfile_internal_write (descriptor, offset + scnsize,
				       (const unsigned char *) buffer->buffer,
				       buffer->size, &errmsg, err))
	    return errmsg;
	  scnsize += buffer->size;
	}

      if (!objfile_coff_write_scnhdr (objfile, descriptor, section->name,
				      &name_offset, scnhdr_offset,
				      scnsize, offset, &errmsg, err))
	return errmsg;

      scnhdr_offset += sizeof (struct external_scnhdr);
      offset += scnsize;
    }

  /* Symbol table is always half-word aligned.  */
  offset += (offset & 1);
  /* There is a file symbol and a section symbol per section,
     and each of these has a single auxiliary symbol following.  */
  nsyms = 2 * (nscns + 1);
  symtab_offset = offset;
  /* Advance across space reserved for symbol table to locate
     start of string table.  */
  offset += nsyms * sizeof (struct external_syment);

  /* Write out file symbol.  */
  memset (&syms[0], 0, sizeof (syms));
  strcpy ((char *)&syms[0].sym.e.e_name[0], ".file");
  set_16 (&syms[0].sym.e_scnum[0], IMAGE_SYM_DEBUG);
  set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
  syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_FILE;
  syms[0].sym.e_numaux[0] = 1;
  /* The name need not be nul-terminated if it fits into the x_fname field
     directly, but must be if it has to be placed into the string table.  */
  if (strlen (source_filename) <= E_FILNMLEN)
    {
      memcpy (&syms[1].aux.x_file.x_fname[0], source_filename,
		strlen (source_filename));
    }
  else
    {
      set_32 (&syms[1].aux.x_file.x_n.x_offset[0], name_offset);
      if (!objfile_internal_write (descriptor, offset + name_offset,
		(const unsigned char *) source_filename,
		strlen (source_filename) + 1, &errmsg, err))
	return errmsg;
      name_offset += strlen (source_filename) + 1;
    }
  if (!objfile_internal_write (descriptor, symtab_offset,
	(const unsigned char *) &syms[0], sizeof (syms), &errmsg, err))
    return errmsg;

  /* Write the string table length, followed by the strings and section
     symbols in step with each other.  */
  set_32 (strsizebuf, name_offset);
  if (!objfile_internal_write (descriptor, offset, strsizebuf, 4, &errmsg, err))
    return errmsg;

  name_offset = 4;
  secsym_offset = symtab_offset + sizeof (syms);
  memset (&syms[0], 0, sizeof (syms));
  set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
  syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_STATIC;
  syms[0].sym.e_numaux[0] = 1;
  secnum = 1;

  for (section = objfile->sections; section != NULL; section = section->next)
    {
      size_t namelen;
      size_t scnsize;
      struct objfile_write_section_buffer *buffer;

      namelen = strlen (section->name);
      set_16 (&syms[0].sym.e_scnum[0], secnum++);
      scnsize = 0;
      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
	scnsize += buffer->size;
      set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize);
      if (namelen > SCNNMLEN)
	{
	  set_32 (&syms[0].sym.e.e.e_zeroes[0], 0);
	  set_32 (&syms[0].sym.e.e.e_offset[0], name_offset);
	  if (!objfile_internal_write (descriptor, offset + name_offset,
				       (const unsigned char *) section->name,
				       namelen + 1, &errmsg, err))
	    return errmsg;
	  name_offset += namelen + 1;
	}
      else
	{
	  memcpy (&syms[0].sym.e.e_name[0], section->name,
		strlen (section->name));
	  memset (&syms[0].sym.e.e_name[strlen (section->name)], 0,
		E_SYMNMLEN - strlen (section->name));
	}

      if (!objfile_internal_write (descriptor, secsym_offset,
	  (const unsigned char *) &syms[0], sizeof (syms), &errmsg, err))
	return errmsg;
      secsym_offset += sizeof (syms);
    }

  if (!objfile_coff_write_filehdr (objfile, descriptor, nscns, symtab_offset,
				   nsyms, &errmsg, err))
    return errmsg;

  return NULL;
}

/* Release the private data for an objfile_write structure.  */

static void
objfile_coff_release_write (void *data)
{
  XDELETE (data);
}

/* The COFF functions.  */

const struct objfile_functions objfile_coff_functions =
{
  objfile_coff_match,
  objfile_coff_find_sections,
  objfile_coff_fetch_attributes,
  objfile_coff_release_read,
  objfile_coff_attributes_compare,
  objfile_coff_release_attributes,
  objfile_coff_start_write,
  objfile_coff_write_to_file,
  objfile_coff_release_write
};

[-- Attachment #3: coff-fixes.diff --]
[-- Type: text/x-c, Size: 8844 bytes --]

--- gcc-unpatched/libiberty/objfile-coff.c	2010-10-30 15:36:49.609375000 +0100
+++ gcc/libiberty/objfile-coff.c	2010-10-30 15:33:12.453125000 +0100
@@ -96,7 +96,7 @@ struct external_scnhdr
 
 #define E_SYMNMLEN	8	/* # characters in a symbol name	*/
 
-struct external_syment 
+struct external_syment
 {
   union
   {
@@ -116,6 +116,47 @@ struct external_syment
   unsigned char e_numaux[1];
 };
 
+/* Length allowed for filename in aux sym format 4.  */
+
+#define E_FILNMLEN	18
+
+/* Omits x_sym and other unused variants.  */
+
+union external_auxent
+{
+  /* Aux sym format 4: file.  */
+  union
+  {
+    char x_fname[E_FILNMLEN];
+    struct
+    {
+      unsigned char x_zeroes[4];
+      unsigned char x_offset[4];
+    } x_n;
+  } x_file;
+  /* Aux sym format 5: section.  */
+  struct
+  {
+    unsigned char x_scnlen[4];		/* section length		*/
+    unsigned char x_nreloc[2];		/* # relocation entries		*/
+    unsigned char x_nlinno[2];		/* # line numbers		*/
+    unsigned char x_checksum[4];	/* section COMDAT checksum	*/
+    unsigned char x_associated[2];	/* COMDAT assoc section index	*/
+    unsigned char x_comdat[1];		/* COMDAT selection number	*/
+  } x_scn;
+};
+
+/* Symbol-related constants.  */
+
+#define IMAGE_SYM_DEBUG		(-2)
+#define IMAGE_SYM_TYPE_NULL	(0)
+#define IMAGE_SYM_DTYPE_NULL	(0)
+#define IMAGE_SYM_CLASS_STATIC	(3)
+#define IMAGE_SYM_CLASS_FILE	(103)
+
+#define IMAGE_SYM_TYPE \
+  ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL)
+
 /* Private data for an objfile_read.  */
 
 struct objfile_coff_read
@@ -195,7 +236,6 @@ objfile_coff_match (unsigned char header
   unsigned short (*fetch_16) (const unsigned char *);
   unsigned int (*fetch_32) (const unsigned char *);
   unsigned char hdrbuf[sizeof (struct external_filehdr)];
-  unsigned char *hdr;
   unsigned short flags;
   struct objfile_coff_read *ocr;
 
@@ -216,7 +256,7 @@ objfile_coff_match (unsigned char header
       return NULL;
     }
   is_big_endian = coff_magic[i].is_big_endian;
-  
+
   magic = is_big_endian ? magic_big : magic_little;
   fetch_16 = (is_big_endian
 	      ? objfile_fetch_big_16
@@ -229,8 +269,6 @@ objfile_coff_match (unsigned char header
 			      errmsg, err))
     return NULL;
 
-  hdr = &hdrbuf[0];
-
   flags = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_flags));
   if ((flags & coff_magic[i].non_object_flags) != 0)
     {
@@ -339,7 +377,7 @@ objfile_coff_find_sections (objfile_read
 	  size_t strindex;
 	  char *end;
 
-	  strindex = strtol (namebuf, &end, 10);
+	  strindex = strtol (namebuf + 1, &end, 10);
 	  if (*end == '\0')
 	    {
 	      /* The real section name is found in the string
@@ -455,8 +493,8 @@ objfile_coff_start_write (void *attribut
 
 static int
 objfile_coff_write_filehdr (objfile_write *objfile, int descriptor,
-			    unsigned int nscns, size_t strtab_offset,
-			    const char **errmsg, int *err)
+			    unsigned int nscns, size_t symtab_offset,
+			    unsigned int nsyms, const char **errmsg, int *err)
 {
   struct objfile_coff_attributes *attrs =
     (struct objfile_coff_attributes *) objfile->data;
@@ -476,14 +514,11 @@ objfile_coff_write_filehdr (objfile_writ
 
   memset (hdr, 0, sizeof (struct external_filehdr));
 
-  /* We don't write out any symbols.  We'll see if that causes any
-     problems.  */
-
   set_16 (hdr + offsetof (struct external_filehdr, f_magic), attrs->magic);
-  set_16 (hdr + offsetof (struct external_filehdr, f_magic), nscns);
+  set_16 (hdr + offsetof (struct external_filehdr, f_nscns), nscns);
   /* f_timdat left as zero.  */
-  set_32 (hdr + offsetof (struct external_filehdr, f_symptr), strtab_offset);
-  /* f_nsyms left as zero.  */
+  set_32 (hdr + offsetof (struct external_filehdr, f_symptr), symtab_offset);
+  set_32 (hdr + offsetof (struct external_filehdr, f_nsyms), nsyms);
   /* f_opthdr left as zero.  */
   set_16 (hdr + offsetof (struct external_filehdr, f_flags), attrs->flags);
 
@@ -549,13 +584,34 @@ objfile_coff_write_to_file (objfile_writ
 {
   struct objfile_coff_attributes *attrs =
     (struct objfile_coff_attributes *) objfile->data;
-  unsigned int nscns;
+  unsigned int nscns, secnum;
   objfile_write_section *section;
   off_t scnhdr_offset;
+  size_t symtab_offset;
+  off_t secsym_offset;
+  unsigned int nsyms;
   size_t offset;
   size_t name_offset;
   const char *errmsg;
   unsigned char strsizebuf[4];
+  /* The interface doesn't give us access to the name of the input file
+     yet.  We want to use its basename for the FILE symbol.  This is
+     what 'gas' uses when told to assemble from stdin.  */
+  const char *source_filename = "fake";
+  union
+  {
+    struct external_syment sym;
+    union external_auxent aux;
+  } syms[2];
+  void (*set_16) (unsigned char *, unsigned short);
+  void (*set_32) (unsigned char *, unsigned int);
+
+  set_16 = (attrs->is_big_endian
+	    ? objfile_set_big_16
+	    : objfile_set_little_16);
+  set_32 = (attrs->is_big_endian
+	    ? objfile_set_big_32
+	    : objfile_set_little_32);
 
   nscns = 0;
   for (section = objfile->sections; section != NULL; section = section->next)
@@ -607,31 +663,95 @@ objfile_coff_write_to_file (objfile_writ
       offset += scnsize;
     }
 
-  if (attrs->is_big_endian)
-    objfile_set_big_32 (strsizebuf, name_offset);
+  /* Symbol table is always half-word aligned.  */
+  offset += (offset & 1);
+  /* There is a file symbol and a section symbol per section,
+     and each of these has a single auxiliary symbol following.  */
+  nsyms = 2 * (nscns + 1);
+  symtab_offset = offset;
+  /* Advance across space reserved for symbol table to locate
+     start of string table.  */
+  offset += nsyms * sizeof (struct external_syment);
+
+  /* Write out file symbol.  */
+  memset (&syms[0], 0, sizeof (syms));
+  strcpy ((char *)&syms[0].sym.e.e_name[0], ".file");
+  set_16 (&syms[0].sym.e_scnum[0], IMAGE_SYM_DEBUG);
+  set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
+  syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_FILE;
+  syms[0].sym.e_numaux[0] = 1;
+  /* The name need not be nul-terminated if it fits into the x_fname field
+     directly, but must be if it has to be placed into the string table.  */
+  if (strlen (source_filename) <= E_FILNMLEN)
+    {
+      memcpy (&syms[1].aux.x_file.x_fname[0], source_filename,
+		strlen (source_filename));
+    }
   else
-    objfile_set_little_32 (strsizebuf, name_offset);
+    {
+      set_32 (&syms[1].aux.x_file.x_n.x_offset[0], name_offset);
+      if (!objfile_internal_write (descriptor, offset + name_offset,
+		(const unsigned char *) source_filename,
+		strlen (source_filename) + 1, &errmsg, err))
+	return errmsg;
+      name_offset += strlen (source_filename) + 1;
+    }
+  if (!objfile_internal_write (descriptor, symtab_offset,
+	(const unsigned char *) &syms[0], sizeof (syms), &errmsg, err))
+    return errmsg;
+
+  /* Write the string table length, followed by the strings and section
+     symbols in step with each other.  */
+  set_32 (strsizebuf, name_offset);
   if (!objfile_internal_write (descriptor, offset, strsizebuf, 4, &errmsg, err))
     return errmsg;
 
   name_offset = 4;
+  secsym_offset = symtab_offset + sizeof (syms);
+  memset (&syms[0], 0, sizeof (syms));
+  set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
+  syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_STATIC;
+  syms[0].sym.e_numaux[0] = 1;
+  secnum = 1;
+
   for (section = objfile->sections; section != NULL; section = section->next)
     {
       size_t namelen;
+      size_t scnsize;
+      struct objfile_write_section_buffer *buffer;
 
       namelen = strlen (section->name);
+      set_16 (&syms[0].sym.e_scnum[0], secnum++);
+      scnsize = 0;
+      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
+	scnsize += buffer->size;
+      set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize);
       if (namelen > SCNNMLEN)
 	{
+	  set_32 (&syms[0].sym.e.e.e_zeroes[0], 0);
+	  set_32 (&syms[0].sym.e.e.e_offset[0], name_offset);
 	  if (!objfile_internal_write (descriptor, offset + name_offset,
 				       (const unsigned char *) section->name,
 				       namelen + 1, &errmsg, err))
 	    return errmsg;
-	  name_offset += namelen;
+	  name_offset += namelen + 1;
+	}
+      else
+	{
+	  memcpy (&syms[0].sym.e.e_name[0], section->name,
+		strlen (section->name));
+	  memset (&syms[0].sym.e.e_name[strlen (section->name)], 0,
+		E_SYMNMLEN - strlen (section->name));
 	}
+
+      if (!objfile_internal_write (descriptor, secsym_offset,
+	  (const unsigned char *) &syms[0], sizeof (syms), &errmsg, err))
+	return errmsg;
+      secsym_offset += sizeof (syms);
     }
 
-  if (!objfile_coff_write_filehdr (objfile, descriptor, nscns, offset,
-				   &errmsg, err))
+  if (!objfile_coff_write_filehdr (objfile, descriptor, nscns, symtab_offset,
+				   nsyms, &errmsg, err))
     return errmsg;
 
   return NULL;

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

* [PATCH] Enable linker plugin for windows [was Re: Discussion about merging Go frontend]
  2010-10-30 16:31                 ` Dave Korn
@ 2010-10-30 20:02                   ` Dave Korn
  2010-11-05 22:02                     ` Ian Lance Taylor
  2010-11-02 15:12                   ` Discussion about merging Go frontend Ian Lance Taylor
  1 sibling, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-10-30 20:02 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

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

On 30/10/2010 11:44, Dave Korn wrote:
> On 29/10/2010 02:31, Ian Lance Taylor wrote:
> 
>> This implements an object file reader/writer which does everything
>> required by LTO and gccgo.  The ELF code works.  I have not tested the
>> Mach-O and COFF code at all beyond compiling it; I hope that somebody
>> else can test those targets and fix them.
>>
>> With this patch, libelf is no longer needed.
> 
>   Almost, but not quite!  The attached patch switches the lto-plugin over to
> use the new objfile reader as well.

>   Bootstrapped and tested all languages except java and ada on
> x86_64-unknown-linux-gnu, no regressions.  There are still a couple of bugs to
> iron out of the COFF-specific part of the objfile reader which I'll have fixed
> later today.
> 
>   OK for trunk (once the objfile changes have gone in)?

  As you'll see elsethread, I fixed the COFF problems.  This is the remaining
chunk of patch required to make the lto-plugin work on cygming targets.

gcc/ChangeLog:

	* gcc.c (PLUGIN_PASSTHROUGH_SPEC): New macro factored out from
	LINK_COMMAND_SPEC.
	(LINK_COMMAND_SPEC): Use it.
	(static_spec_functions[]): Add pass-through-libs entry.
	(pass_through_libs_spec_func): Add related spec function.
	* config/i386/cygming.h (PLUGIN_PASSTHROUGH_SPEC): Define.
	* doc/tm.texi.in (PLUGIN_PASSTHROUGH_SPEC): Document.
	(LINK_COMMAND_SPEC): Mention it.
	* doc/tm.texi: Regenerate.
	* doc/invoke.texi (pass-through-libs): Mention new spec function.

  Taking this for a bootstrap and test cycle now (on top of the objfile
changes).  Assuming no regressions, and one new PASS (the sole LTO test that
exercises -fuse-linker-plugin), and once all the other patches have gone in: OK?

    cheers,
      DaveK


[-- Attachment #2: 2010_10_29_19_53_45_lto-objfile-plugin-part2.diff --]
[-- Type: text/x-c, Size: 6933 bytes --]

Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 166059)
+++ gcc/doc/tm.texi	(working copy)
@@ -406,6 +406,15 @@
 By default this is @code{%G %L %G}.
 @end defmac

+@defmac PLUGIN_PASSTHROUGH_SPEC
+This macro is used as part of @code{LINK_COMMAND_SPEC} when the LTO plugin
+is in use.  It allows the system's standard libraries to be sent to the
+plugin as @option{-pass-through} plugin options, which causes them to be
+added at the end of the link when it may be necessary to resolve new
+undefined references generated as LTO expands builtins from the IR.  The
+default definition should suit ELF platforms.
+@end defmac
+
 @defmac LINK_COMMAND_SPEC
 A C string constant giving the complete command line need to execute the
 linker.  When you do this, you will need to update your port each time a
@@ -413,7 +422,7 @@
 define this macro only if you need to completely redefine the command
 line for invoking the linker and there is no other way to accomplish
 the effect you need.  Overriding this macro may be avoidable by overriding
-@code{LINK_GCC_C_SEQUENCE_SPEC} instead.
+@code{LINK_GCC_C_SEQUENCE_SPEC} and/or @code{PLUGIN_PASSTHROUGH_SPEC} instead.
 @end defmac

 @defmac LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	(revision 166059)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -406,6 +406,15 @@
 By default this is @code{%G %L %G}.
 @end defmac

+@defmac PLUGIN_PASSTHROUGH_SPEC
+This macro is used as part of @code{LINK_COMMAND_SPEC} when the LTO plugin
+is in use.  It allows the system's standard libraries to be sent to the
+plugin as @option{-pass-through} plugin options, which causes them to be
+added at the end of the link when it may be necessary to resolve new
+undefined references generated as LTO expands builtins from the IR.  The
+default definition should suit ELF platforms.
+@end defmac
+
 @defmac LINK_COMMAND_SPEC
 A C string constant giving the complete command line need to execute the
 linker.  When you do this, you will need to update your port each time a
@@ -413,7 +422,7 @@
 define this macro only if you need to completely redefine the command
 line for invoking the linker and there is no other way to accomplish
 the effect you need.  Overriding this macro may be avoidable by overriding
-@code{LINK_GCC_C_SEQUENCE_SPEC} instead.
+@code{LINK_GCC_C_SEQUENCE_SPEC} and/or @code{PLUGIN_PASSTHROUGH_SPEC} instead.
 @end defmac

 @defmac LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 166059)
+++ gcc/doc/invoke.texi	(working copy)
@@ -9683,6 +9683,17 @@
 %:remove-outfile(-lm)
 @end smallexample

+@item @code{pass-through-libs}
+The @code{pass-through-libs} spec function takes any number of arguments.  It
+finds any @option{-l} options and any non-options (which it assumes are the
+names of linker input files) and returns a result containing all the found
+arguments each prepended by @option{-plugin-opt=-pass-through=} and joined by
+spaces.  This list is intended to be passed to the LTO linker plugin.
+
+@smallexample
+%:pass-through-libs(%G %L %G)
+@end smallexample
+
 @item @code{print-asm-header}
 The @code{print-asm-header} function takes no arguments and simply
 prints a banner like:
Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c	(revision 166059)
+++ gcc/gcc.c	(working copy)
@@ -287,6 +287,7 @@
 static const char *compare_debug_dump_opt_spec_function (int, const char **);
 static const char *compare_debug_self_opt_spec_function (int, const char **);
 static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
+static const char *pass_through_libs_spec_func (int, const char **);
 \f
 /* The Specs Language

@@ -531,6 +532,14 @@
 #define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
 #endif

+/* config.h can define PLUGIN_PASSTHROUGH_SPEC to control which
+   libraries are passed through to the final link by the lto-plugin.  */
+#ifndef PLUGIN_PASSTHROUGH_SPEC
+#define PLUGIN_PASSTHROUGH_SPEC " \
+  %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)} \
+  %{static:-plugin-opt=-pass-through=-lc} "
+#endif
+
 /* mudflap specs */
 #ifndef MFWRAP_SPEC
 /* XXX: valid only for GNU ld */
@@ -658,10 +667,8 @@
     %{fuse-linker-plugin: \
     -plugin %(linker_plugin_file) \
     -plugin-opt=%(lto_wrapper) \
-    -plugin-opt=-fresolution=%u.res \
-    %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)}	\
-    %{static:-plugin-opt=-pass-through=-lc}	\
-    } \
+    -plugin-opt=-fresolution=%u.res " \
+    PLUGIN_PASSTHROUGH_SPEC " } \
     %{flto:%<fcompare-debug*} %{fwhopr*:%<fcompare-debug*} \
     %{flto} %{fwhopr*} %l " LINK_PIE_SPEC \
    "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
@@ -1244,6 +1251,7 @@
   { "compare-debug-dump-opt",	compare_debug_dump_opt_spec_function },
   { "compare-debug-self-opt",	compare_debug_self_opt_spec_function },
   { "compare-debug-auxbase-opt", compare_debug_auxbase_opt_spec_function },
+  { "pass-through-libs",	pass_through_libs_spec_func },
 #ifdef EXTRA_SPEC_FUNCTIONS
   EXTRA_SPEC_FUNCTIONS
 #endif
@@ -8216,3 +8224,33 @@

   return name;
 }
+
+/* %:pass-through-libs spec function.  Finds all -l options and input
+   file names in the lib spec passed to it, and makes a list of them
+   prepended with the plugin option to cause them to be passed through
+   to the final link after all the new object files have been added.  */
+
+const char *
+pass_through_libs_spec_func (int argc, const char **argv)
+{
+  char *prepended = xstrdup (" ");
+  int n;
+  /* Shlemiel the painter's algorithm.  Innately horrible, but at least
+     we know that there will never be more than a handful of strings to
+     concat, and it's only once per run, so it's not worth optimising.  */
+  for (n = 0; n < argc; n++)
+    {
+    char *old = prepended;
+      /* Anything that isn't an option is a full path to an output
+         file; pass it through if it ends in '.a'.  Among options,
+	 pass only -l.  */
+      if (argv[n][0] == '-'
+		? argv[n][1] == 'l'
+		: !strcmp (".a", argv[n] + strlen (argv[n]) - 2))
+	prepended = concat (prepended, "-plugin-opt=-pass-through=",
+		argv[n], " ", NULL);
+      if (prepended != old)
+	free (old);
+    }
+  return prepended;
+}
Index: gcc/config/i386/cygming.h
===================================================================
--- gcc/config/i386/cygming.h	(revision 166059)
+++ gcc/config/i386/cygming.h	(working copy)
@@ -142,6 +142,8 @@
 #define SUBTARGET_EXTRA_SPECS						\
   { "mingw_include_path", DEFAULT_TARGET_MACHINE }

+#define PLUGIN_PASSTHROUGH_SPEC " %:pass-through-libs(%o %G %L %G) "
+
 #undef MATH_LIBRARY
 #define MATH_LIBRARY ""


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

* Re: Discussion about merging Go frontend
  2010-10-30 13:59                   ` Dave Korn
@ 2010-10-31  0:31                     ` Richard Henderson
  2010-10-31  3:33                       ` Dave Korn
  0 siblings, 1 reply; 68+ messages in thread
From: Richard Henderson @ 2010-10-31  0:31 UTC (permalink / raw)
  To: Dave Korn
  Cc: Ian Lance Taylor, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc,
	gcc-patches

On 10/30/2010 01:16 AM, Dave Korn wrote:
>> Do we really want to keep re-reading section data for every section
>> lookup we do?  Can't we do this in objfile_open_read?
> 
>   It should only be necessary to do one section lookup per object file anyway.
>  Keep extra data hanging around in memory in the backend just so that we can
> write algorithmically inefficient code in the client?  Seems like a bad
> tradeoff to me!

Uh, really?  I thought there were like a half-dozen lto sections...

>   The line you quoted uses IMAGE_SCN_ALIGN_1BYTES.  That's all we'll ever need
> for LTO sections.

Perhaps, but there's an argument to the create_section function that
specifies the alignment.  If we only need 1-byte alignment that's fine,
but we should either assert that's true, omit the argument, or properly
support it.


r~

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

* Re: Discussion about merging Go frontend
  2010-10-31  0:31                     ` Richard Henderson
@ 2010-10-31  3:33                       ` Dave Korn
  2010-10-31  7:16                         ` Richard Henderson
  0 siblings, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-10-31  3:33 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Ian Lance Taylor, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc,
	gcc-patches

On 30/10/2010 18:57, Richard Henderson wrote:
> On 10/30/2010 01:16 AM, Dave Korn wrote:
>>> Do we really want to keep re-reading section data for every section
>>> lookup we do?  Can't we do this in objfile_open_read?
>>   It should only be necessary to do one section lookup per object file anyway.
>>  Keep extra data hanging around in memory in the backend just so that we can
>> write algorithmically inefficient code in the client?  Seems like a bad
>> tradeoff to me!
> 
> Uh, really?  I thought there were like a half-dozen lto sections...

  Which we iterate over just once, and record them all in a hash table from
the per-section callback, unless I've missed something.

>>   The line you quoted uses IMAGE_SCN_ALIGN_1BYTES.  That's all we'll ever need
>> for LTO sections.
> 
> Perhaps, but there's an argument to the create_section function that
> specifies the alignment.  If we only need 1-byte alignment that's fine,
> but we should either assert that's true, omit the argument, or properly
> support it.

  Fair point.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-10-31  3:33                       ` Dave Korn
@ 2010-10-31  7:16                         ` Richard Henderson
  2010-10-31  8:47                           ` Dave Korn
  0 siblings, 1 reply; 68+ messages in thread
From: Richard Henderson @ 2010-10-31  7:16 UTC (permalink / raw)
  To: Dave Korn
  Cc: Ian Lance Taylor, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc,
	gcc-patches

On 10/30/2010 11:37 AM, Dave Korn wrote:
>> Uh, really?  I thought there were like a half-dozen lto sections...
> 
>   Which we iterate over just once, and record them all in a hash table from
> the per-section callback, unless I've missed something.

Oh, right.  Nevermind then.


r~

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

* Re: Discussion about merging Go frontend
  2010-10-31  7:16                         ` Richard Henderson
@ 2010-10-31  8:47                           ` Dave Korn
  2010-10-31 19:43                             ` Ian Lance Taylor
  0 siblings, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-10-31  8:47 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Ian Lance Taylor, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc,
	gcc-patches

On 30/10/2010 19:24, Richard Henderson wrote:
> On 10/30/2010 11:37 AM, Dave Korn wrote:
>>> Uh, really?  I thought there were like a half-dozen lto sections...
>>   Which we iterate over just once, and record them all in a hash table from
>> the per-section callback, unless I've missed something.
> 
> Oh, right.  Nevermind then.
> 
> 
> r~

  It'd be worth putting a warning comment on the find_section (no "s")
function saying that it's pretty inefficient and that it is best practice to
call find_sections just once and record details rather than make multiple
calls to find_section.  (Both lto FE and lto-plugin are already architected
that way.)

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-10-31  8:47                           ` Dave Korn
@ 2010-10-31 19:43                             ` Ian Lance Taylor
  0 siblings, 0 replies; 68+ messages in thread
From: Ian Lance Taylor @ 2010-10-31 19:43 UTC (permalink / raw)
  To: Dave Korn; +Cc: Richard Henderson, gcc, gcc-patches

Dave Korn <dave.korn.cygwin@gmail.com> writes:

> On 30/10/2010 19:24, Richard Henderson wrote:
>> On 10/30/2010 11:37 AM, Dave Korn wrote:
>>>> Uh, really?  I thought there were like a half-dozen lto sections...
>>>   Which we iterate over just once, and record them all in a hash table from
>>> the per-section callback, unless I've missed something.
>> 
>> Oh, right.  Nevermind then.
>> 
>> 
>> r~
>
>   It'd be worth putting a warning comment on the find_section (no "s")
> function saying that it's pretty inefficient and that it is best practice to
> call find_sections just once and record details rather than make multiple
> calls to find_section.  (Both lto FE and lto-plugin are already architected
> that way.)
>
>     cheers,
>       DaveK

I added a sentence "Note that calling this multiple times is
inefficient; use objfile_find_sections instead."

I added the function because it's what the gccgo frontend needs: it only
needs to find one section.

Ian

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

* Re: Discussion about merging Go frontend
  2010-10-30  8:07                 ` Richard Henderson
  2010-10-30 13:59                   ` Dave Korn
@ 2010-10-31 20:00                   ` Ian Lance Taylor
  1 sibling, 0 replies; 68+ messages in thread
From: Ian Lance Taylor @ 2010-10-31 20:00 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Dave Korn, gcc-patches

Richard Henderson <rth@redhat.com> writes:

>> +extern objfile_read *
>> +objfile_open_read (int descriptor, off_t offset, const char *segment_name,
>> +		   const char **errmsg, int *err);
> ...
>> +extern objfile_write *
>> +objfile_start_write (objfile_attributes *ATTRS, const char *segment_name,
>> +		     const char **errmsg, int *err);
>
> Mismatch in naming conventions?  I like the use of "release"
> to clearly indicate non-closure of the FD.

You're right.  I changed the first to objfile_start_read.

>
>> +  shdr_size = (cl == ELFCLASS32
>> +	       ? sizeof (Elf32_External_Shdr)
>> +	       : sizeof (Elf64_External_Shdr));
>> +  memset (buf, 0, shdr_size);
>
> Constant size memset is easier to optimize.  You might as well
> zero all of BUF, even if we're not going to use it all.  The
> slop between 32 and 64 is minimal.

True.  Fixed.


>> +  if (!objfile_internal_read (objfile->descriptor,
>> +			      objfile->offset + eor->shoff + shdr_size,
>> +			      shdrs,
>> +			      shdr_size * (shnum - 1),
>> +			      &errmsg, err))
>
> Do we really want to keep re-reading section data for every section
> lookup we do?  Can't we do this in objfile_open_read?

I think this is OK as discussed elsewhere.


>> +  set_32 (hdr + offsetof (struct external_scnhdr, s_flags),
>> +	  (STYP_DATA | IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_DISCARDABLE
>> +	   | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ));
>
> You're not recording alignment in the coff object file?
> IMAGE_SCN_ALIGN_<N>BYTES, 1 <= N <= 8192, are all defined
> with a simple function in that nibble.

Changed to this:

  flags = (STYP_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_SHARED
	   | IMAGE_SCN_MEM_READ);
  /* PE can represent alignment up to 13.  */
  if (align > 13)
    align = 13;
  flags |= IMAGE_SCN_ALIGN_POWER_CONST(align);
  set_32 (hdr + offsetof (struct external_scnhdr, s_flags), flags);

Thanks.

Ian

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

* Re: Discussion about merging Go frontend
  2010-10-30 19:30                 ` Dave Korn
@ 2010-10-31 20:18                   ` Ian Lance Taylor
  0 siblings, 0 replies; 68+ messages in thread
From: Ian Lance Taylor @ 2010-10-31 20:18 UTC (permalink / raw)
  To: Dave Korn; +Cc: Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

Dave Korn <dave.korn.cygwin@gmail.com> writes:

>   Attached are the revised version of the file, and a diff to show what I
> changed.  With this version, all the tests in gcc.dg/lto/lto.exp pass as
> before (i.e. there are still a couple of pre-existing FAILs that aren't affected).

Excellent, thanks.  I have incorporated your objfile-coff.c in my
working directory, and will commit it when I commit the whole patch set.

I think it can be committed as soon as objfile-mach-o.c is working.

Ian

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

* Re: Discussion about merging Go frontend
  2010-10-29  6:56               ` Discussion about merging Go frontend Ian Lance Taylor
                                   ` (5 preceding siblings ...)
  2010-10-30 19:30                 ` Dave Korn
@ 2010-11-01 17:36                 ` Tom Tromey
  2010-11-01 18:23                   ` Ian Lance Taylor
  2010-11-01 22:30                   ` Ian Lance Taylor
  2010-11-06 20:01                 ` Eric Botcazou
  7 siblings, 2 replies; 68+ messages in thread
From: Tom Tromey @ 2010-11-01 17:36 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Dave Korn, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

>>>>> "Ian" == Ian Lance Taylor <iant@google.com> writes:

Ian> This patch puts the code in libiberty, but it could equally well go in
Ian> gcc.  Anybody want to make an argument one way or another?

Ian> +extern const char *
Ian> +objfile_attributes_compare (objfile_attributes *attrs1,

GDB already uses the name "objfile" for one of its modules.
I don't think we have any name clashes with this patch right now, but I
would prefer to avoid the eventual confusion.
So, if this is in libiberty, could it please have a different name?

thanks,
Tom


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

* Re: Discussion about merging Go frontend
  2010-11-01 17:36                 ` Tom Tromey
@ 2010-11-01 18:23                   ` Ian Lance Taylor
  2010-11-02 10:51                     ` Paolo Bonzini
  2010-11-01 22:30                   ` Ian Lance Taylor
  1 sibling, 1 reply; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-01 18:23 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Dave Korn, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc, gcc-patches

Tom Tromey <tromey@redhat.com> writes:

>>>>>> "Ian" == Ian Lance Taylor <iant@google.com> writes:
>
> Ian> This patch puts the code in libiberty, but it could equally well go in
> Ian> gcc.  Anybody want to make an argument one way or another?
>
> Ian> +extern const char *
> Ian> +objfile_attributes_compare (objfile_attributes *attrs1,
>
> GDB already uses the name "objfile" for one of its modules.
> I don't think we have any name clashes with this patch right now, but I
> would prefer to avoid the eventual confusion.
> So, if this is in libiberty, could it please have a different name?

Sure.

Any suggestions?

Ian

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

* Re: Discussion about merging Go frontend
  2010-11-01 17:36                 ` Tom Tromey
  2010-11-01 18:23                   ` Ian Lance Taylor
@ 2010-11-01 22:30                   ` Ian Lance Taylor
  2010-11-02 15:06                     ` Ian Lance Taylor
  2010-11-02 17:43                     ` H.J. Lu
  1 sibling, 2 replies; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-01 22:30 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gcc-patches

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

Tom Tromey <tromey@redhat.com> writes:

> GDB already uses the name "objfile" for one of its modules.
> I don't think we have any name clashes with this patch right now, but I
> would prefer to avoid the eventual confusion.
> So, if this is in libiberty, could it please have a different name?

OK, I renamed objfile to simple_object.

This is the current patch, incorporating all suggestions so far.  There
are still reportedly problems with the Mach-O code.

Ian


ChangeLog:

2010-11-01  Ian Lance Taylor  <iant@google.com>

	* configure.ac: Don't set default_enable_lto.  Remove libelf tests.
	* configure: Rebuild.

include/ChangeLog:

2010-11-01  Ian Lance Taylor  <iant@google.com>

	* simple-object.h: New file.

libiberty/ChangeLog:

2010-11-01  Ian Lance Taylor  <iant@google.com>

	* simple-object.c: New file.
	* simple-object-common.h: New file.
	* simple-object-elf.c: New file.
	* simple-object-mach-o.c: New file.
	* simple-object-coff.c: New file.
	* simple-object.txh: New file.
	* configure.ac: Add AC_TYPE_SSIZE_T.
	* Makefile.in: Rebuild dependencies.
	(CFILES): Add simple-object.c, simple-object-coff,
	simple-object-elf.c, and simple-object-mach-o.c.
	(REQUIRED_OFILES): Add corresponding object files.
	* configure: Rebuild.
	* config.in: Rebuild.
	* functions.texi: Rebuild.

gcc/ChangeLog:

2010-11-01  Ian Lance Taylor  <iant@google.com>

	* configure.ac: Remove elf_getshdrstrndx test.  Don't substitute
	LTO_BINARY_READER or LTO_USE_LIBELF.  Remove LIBELFLIBS and
	LIBELFINC.  Remove HAVE_libelf.
	* gcc/config.gcc: Don't set lto_binary_reader.
	* gcc/Makefile.in (LIBELFLIBS, LIBELFINC): Remove variables.
	(LTO_BINARY_READER, LTO_USE_LIBELF): Remove variables.
	(LIBS): Remove $(LIBELFLIBS).
	(INCLUDES): Remove $(LIBELFINC).
	* doc/install.texi (Prerequisites): Remove libelf paragraphs.
	(Configuration): Mention --disable-lto.  Remove --with-libelf
	paragraph.
	* configure: Rebuild.
	* config.in: Rebuild.

gcc/lto/ChangeLog:

2010-11-01  Ian Lance Taylor  <iant@google.com>

	* lto-object.c: New file.
	* lto-elf.c: Remove file.
	* lto-macho.c: Remove file.
	* lto-macho.h: Remove file.
	* lto-coff.c: Remove file.
	* lto-coff.h: Remove file.
	* Make-lang.in (LTO_OBJS): Change lto/$(LTO_BINARY_READER).o to
	lto/lto-object.o.
	($(LTO_EXE)): Remove $(LTO_USE_LIBELF)
	(lto/lto-objfile.o): New target.
	(lto/lto-elf.o, lto/lto-coff.o, lto/lto-macho.o): Remove targets.
	(lto/lto.o): Remove $(LIBIBERTY_H).



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: objfile --]
[-- Type: text/x-diff, Size: 249532 bytes --]

Index: include/simple-object.h
===================================================================
--- include/simple-object.h	(revision 0)
+++ include/simple-object.h	(revision 0)
@@ -0,0 +1,203 @@
+/* simple-object.h -- simple routines to read and write object files
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+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, 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, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#ifndef SIMPLE_OBJECT_H
+#define SIMPLE_OBJECT_H
+
+#include <stddef.h>
+#include <sys/types.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This header file provides four types with associated functions.
+   They are used to read and write object files.  This is a minimal
+   interface, intended to support the needs of gcc without bringing in
+   all the power and complexity of BFD.  */
+
+/* The type simple_object_read * is used to read an existing object
+   file.  */
+
+typedef struct simple_object_read_struct simple_object_read;
+
+/* Create an simple_object_read given DESCRIPTOR, an open file
+   descriptor, and OFFSET, an offset within the file.  The offset is
+   for use with archives, and should be 0 for an ordinary object file.
+   The descriptor must remain open until done with the returned
+   simple_object_read.  SEGMENT_NAME is used on Mach-O and is required
+   on that platform: it means to only look at sections within the
+   segment with that name.  It is ignored for other object file
+   formats.  On error, this function returns NULL, and sets *ERRMSG to
+   an error string and sets *ERR to an errno value or 0 if there is no
+   relevant errno.  */
+
+extern simple_object_read *
+simple_object_start_read (int descriptor, off_t offset,
+			  const char *segment_name, const char **errmsg,
+			  int *err);
+
+/* Call PFN for each section in SIMPLE_OBJECT, passing it the section
+   name, offset within the file of the section contents, and length of
+   the section contents.  The offset within the file is relative to
+   the offset passed to simple_object_start_read.  The DATA argument
+   to simple_object_find_sections is passed on to PFN.  If PFN returns
+   0, the loop is stopped and simple_object_find_sections returns.  If
+   PFN returns non-zero, the loop continues.  On success this returns
+   NULL.  On error it returns an error string, and sets *ERR to an
+   errno value or 0 if there is no relevant errno.  */
+
+extern const char *
+simple_object_find_sections (simple_object_read *simple_object,
+			     int (*pfn) (void *data, const char *,
+					 off_t offset, off_t length),
+			     void *data,
+			     int *err);
+
+/* Look for the section NAME in SIMPLE_OBJECT.  This returns
+   information for the first section NAME in SIMPLE_OBJECT.  Note that
+   calling this multiple times is inefficient; use
+   simple_object_find_sections instead.
+
+   If found, return 1 and set *OFFSET to the offset in the file of the
+   section contents and set *LENGTH to the length of the section
+   contents.  *OFFSET will be relative to the offset passed to
+   simple_object_start_read.
+
+   If the section is not found, and no error occurs, return 0 and set
+   *ERRMSG to NULL.
+
+   If an error occurs, return 0, set *ERRMSG to an error message, and
+   set *ERR to an errno value or 0 if there is no relevant errno.  */
+
+extern int
+simple_object_find_section (simple_object_read *simple_object,
+			    const char *name, off_t *offset, off_t *length,
+			    const char **errmsg, int *err);
+
+/* Release all resources associated with SIMPLE_OBJECT.  This does not
+   close the file descriptor.  */
+
+extern void
+simple_object_release_read (simple_object_read *);
+
+/* The type simple_object_attributes holds the attributes of an object
+   file that matter for creating a file or ensuring that two files are
+   compatible.  This is a set of magic numbers.  */
+
+typedef struct simple_object_attributes_struct simple_object_attributes;
+
+/* Fetch the attributes of SIMPLE_OBJECT.  This information will
+   persist until simple_object_attributes_release is called, even if
+   SIMPLE_OBJECT is closed.  On error this returns NULL, sets *ERRMSG
+   to an error message, and sets *ERR to an errno value or 0 if there
+   isn't one.  */
+
+extern simple_object_attributes *
+simple_object_fetch_attributes (simple_object_read *simple_object,
+				const char **errmsg, int *err);
+
+/* Compare ATTRS1 and ATTRS2.  If they could be linked together
+   without error, return NULL.  Otherwise, return an error message,
+   set *ERR to an errno value or 0 if there isn't one.  */
+
+extern const char *
+simple_object_attributes_compare (simple_object_attributes *attrs1,
+			    simple_object_attributes *attrs2,
+			    int *err);
+
+/* Release all resources associated with ATTRS.  */
+
+extern void
+simple_object_release_attributes (simple_object_attributes *attrs);
+
+/* The type simple_object_write is used to create a new object file.  */
+
+typedef struct simple_object_write_struct simple_object_write;
+
+/* Start creating a new object file which is like ATTRS.  You must
+   fetch attribute information from an existing object file before you
+   can create a new one.  There is currently no support for creating
+   an object file de novo.  The segment name is only used on Mach-O,
+   where it is required.  It means that all sections are created
+   within that segment.  It is ignored for other object file formats.
+   On error this function returns NULL, sets *ERRMSG to an error
+   message, and sets *ERR to an errno value or 0 if there isn't
+   one.  */
+
+extern simple_object_write *
+simple_object_start_write (simple_object_attributes *attrs,
+			   const char *segment_name,
+			   const char **errmsg, int *err);
+
+/* The type simple_object_write_section is a handle for a section
+   which is being written.  */
+
+typedef struct simple_object_write_section_struct simple_object_write_section;
+
+/* Add a section to SIMPLE_OBJECT.  NAME is the name of the new
+   section.  ALIGN is the required alignment expressed as the number
+   of required low-order 0 bits (e.g., 2 for alignment to a 32-bit
+   boundary).  The section is created as containing data, readable,
+   not writable, not executable, not loaded at runtime.  On error this
+   returns NULL, sets *ERRMSG to an error message, and sets *ERR to an
+   errno value or 0 if there isn't one.  */
+
+extern simple_object_write_section *
+simple_object_write_create_section (simple_object_write *simple_object,
+				    const char *name, unsigned int align,
+				    const char **errmsg, int *err);
+
+/* Add data BUFFER/SIZE to SECTION in SIMPLE_OBJECT.  If COPY is
+   non-zero, the data will be copied into memory if necessary.  If
+   COPY is zero, BUFFER must persist until SIMPLE_OBJECT is released.
+   On success this returns NULL.  On error this returns an error
+   message, and sets *ERR to an errno value or 0 if there isn't
+   one.  */
+
+extern const char *
+simple_object_write_add_data (simple_object_write *simple_object,
+			      simple_object_write_section *section,
+			      const void *buffer, size_t size,
+			      int copy, int *err);
+
+/* Write the complete object file to DESCRIPTOR, an open file
+   descriptor.  This returns NULL on success.  On error this returns
+   an error message, and sets *ERR to an errno value or 0 if there
+   isn't one.  */
+
+extern const char *
+simple_object_write_to_file (simple_object_write *simple_object,
+			     int descriptor, int *err);
+
+/* Release all resources associated with SIMPLE_OBJECT, including any
+   simple_object_write_section's that may have been created.  */
+
+extern void
+simple_object_release_write (simple_object_write *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: libiberty/simple-object-elf.c
===================================================================
--- libiberty/simple-object-elf.c	(revision 0)
+++ libiberty/simple-object-elf.c	(revision 0)
@@ -0,0 +1,916 @@
+/* simple-object-elf.c -- routines to manipulate ELF object files.
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+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, 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, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "libiberty.h"
+#include "simple-object.h"
+
+#include <errno.h>
+#include <stddef.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "simple-object-common.h"
+
+/* ELF structures and constants.  */
+
+/* 32-bit ELF file header.  */
+
+typedef struct {
+  unsigned char	e_ident[16];		/* ELF "magic number" */
+  unsigned char	e_type[2];		/* Identifies object file type */
+  unsigned char	e_machine[2];		/* Specifies required architecture */
+  unsigned char	e_version[4];		/* Identifies object file version */
+  unsigned char	e_entry[4];		/* Entry point virtual address */
+  unsigned char	e_phoff[4];		/* Program header table file offset */
+  unsigned char	e_shoff[4];		/* Section header table file offset */
+  unsigned char	e_flags[4];		/* Processor-specific flags */
+  unsigned char	e_ehsize[2];		/* ELF header size in bytes */
+  unsigned char	e_phentsize[2];		/* Program header table entry size */
+  unsigned char	e_phnum[2];		/* Program header table entry count */
+  unsigned char	e_shentsize[2];		/* Section header table entry size */
+  unsigned char	e_shnum[2];		/* Section header table entry count */
+  unsigned char	e_shstrndx[2];		/* Section header string table index */
+} Elf32_External_Ehdr;
+
+/* 64-bit ELF file header.  */
+
+typedef struct {
+  unsigned char	e_ident[16];		/* ELF "magic number" */
+  unsigned char	e_type[2];		/* Identifies object file type */
+  unsigned char	e_machine[2];		/* Specifies required architecture */
+  unsigned char	e_version[4];		/* Identifies object file version */
+  unsigned char	e_entry[8];		/* Entry point virtual address */
+  unsigned char	e_phoff[8];		/* Program header table file offset */
+  unsigned char	e_shoff[8];		/* Section header table file offset */
+  unsigned char	e_flags[4];		/* Processor-specific flags */
+  unsigned char	e_ehsize[2];		/* ELF header size in bytes */
+  unsigned char	e_phentsize[2];		/* Program header table entry size */
+  unsigned char	e_phnum[2];		/* Program header table entry count */
+  unsigned char	e_shentsize[2];		/* Section header table entry size */
+  unsigned char	e_shnum[2];		/* Section header table entry count */
+  unsigned char	e_shstrndx[2];		/* Section header string table index */
+} Elf64_External_Ehdr;
+
+/* Indexes and values in e_ident field of Ehdr.  */
+
+#define EI_MAG0		0	/* File identification byte 0 index */
+#define ELFMAG0		   0x7F	/* Magic number byte 0 */
+
+#define EI_MAG1		1	/* File identification byte 1 index */
+#define ELFMAG1		    'E'	/* Magic number byte 1 */
+
+#define EI_MAG2		2	/* File identification byte 2 index */
+#define ELFMAG2		    'L'	/* Magic number byte 2 */
+
+#define EI_MAG3		3	/* File identification byte 3 index */
+#define ELFMAG3		    'F'	/* Magic number byte 3 */
+
+#define EI_CLASS	4	/* File class */
+#define ELFCLASSNONE	      0	/* Invalid class */
+#define ELFCLASS32	      1	/* 32-bit objects */
+#define ELFCLASS64	      2	/* 64-bit objects */
+
+#define EI_DATA		5	/* Data encoding */
+#define ELFDATANONE	      0	/* Invalid data encoding */
+#define ELFDATA2LSB	      1	/* 2's complement, little endian */
+#define ELFDATA2MSB	      2	/* 2's complement, big endian */
+
+#define EI_VERSION	6	/* File version */
+#define EV_CURRENT	1		/* Current version */
+
+#define EI_OSABI	7	/* Operating System/ABI indication */
+
+/* Values for e_type field of Ehdr.  */
+
+#define ET_REL		1	/* Relocatable file */
+
+/* Special section index values.  */
+
+#define SHN_LORESERVE	0xFF00		/* Begin range of reserved indices */
+#define SHN_XINDEX	0xFFFF		/* Section index is held elsewhere */
+
+/* 32-bit ELF program header.  */
+
+typedef struct {
+  unsigned char	p_type[4];		/* Identifies program segment type */
+  unsigned char	p_offset[4];		/* Segment file offset */
+  unsigned char	p_vaddr[4];		/* Segment virtual address */
+  unsigned char	p_paddr[4];		/* Segment physical address */
+  unsigned char	p_filesz[4];		/* Segment size in file */
+  unsigned char	p_memsz[4];		/* Segment size in memory */
+  unsigned char	p_flags[4];		/* Segment flags */
+  unsigned char	p_align[4];		/* Segment alignment, file & memory */
+} Elf32_External_Phdr;
+
+/* 64-bit ELF program header.  */
+
+typedef struct {
+  unsigned char	p_type[4];		/* Identifies program segment type */
+  unsigned char	p_flags[4];		/* Segment flags */
+  unsigned char	p_offset[8];		/* Segment file offset */
+  unsigned char	p_vaddr[8];		/* Segment virtual address */
+  unsigned char	p_paddr[8];		/* Segment physical address */
+  unsigned char	p_filesz[8];		/* Segment size in file */
+  unsigned char	p_memsz[8];		/* Segment size in memory */
+  unsigned char	p_align[8];		/* Segment alignment, file & memory */
+} Elf64_External_Phdr;
+
+/* 32-bit ELF section header */
+
+typedef struct {
+  unsigned char	sh_name[4];		/* Section name, index in string tbl */
+  unsigned char	sh_type[4];		/* Type of section */
+  unsigned char	sh_flags[4];		/* Miscellaneous section attributes */
+  unsigned char	sh_addr[4];		/* Section virtual addr at execution */
+  unsigned char	sh_offset[4];		/* Section file offset */
+  unsigned char	sh_size[4];		/* Size of section in bytes */
+  unsigned char	sh_link[4];		/* Index of another section */
+  unsigned char	sh_info[4];		/* Additional section information */
+  unsigned char	sh_addralign[4];	/* Section alignment */
+  unsigned char	sh_entsize[4];		/* Entry size if section holds table */
+} Elf32_External_Shdr;
+
+/* 64-bit ELF section header.  */
+
+typedef struct {
+  unsigned char	sh_name[4];		/* Section name, index in string tbl */
+  unsigned char	sh_type[4];		/* Type of section */
+  unsigned char	sh_flags[8];		/* Miscellaneous section attributes */
+  unsigned char	sh_addr[8];		/* Section virtual addr at execution */
+  unsigned char	sh_offset[8];		/* Section file offset */
+  unsigned char	sh_size[8];		/* Size of section in bytes */
+  unsigned char	sh_link[4];		/* Index of another section */
+  unsigned char	sh_info[4];		/* Additional section information */
+  unsigned char	sh_addralign[8];	/* Section alignment */
+  unsigned char	sh_entsize[8];		/* Entry size if section holds table */
+} Elf64_External_Shdr;
+
+/* Values for sh_type field.  */
+
+#define SHT_PROGBITS	1		/* Program data */
+#define SHT_STRTAB	3		/* A string table */
+
+/* Functions to fetch and store different ELF types, depending on the
+   endianness and size.  */
+
+struct elf_type_functions
+{
+  unsigned short (*fetch_Elf_Half) (const unsigned char *);
+  unsigned int (*fetch_Elf_Word) (const unsigned char *);
+  ulong_type (*fetch_Elf_Addr) (const unsigned char *);
+  void (*set_Elf_Half) (unsigned char *, unsigned short);
+  void (*set_Elf_Word) (unsigned char *, unsigned int);
+  void (*set_Elf_Addr) (unsigned char *, ulong_type);
+};
+
+static const struct elf_type_functions elf_big_32_functions =
+{
+  simple_object_fetch_big_16,
+  simple_object_fetch_big_32,
+  simple_object_fetch_big_32_ulong,
+  simple_object_set_big_16,
+  simple_object_set_big_32,
+  simple_object_set_big_32_ulong
+};
+
+static const struct elf_type_functions elf_little_32_functions =
+{
+  simple_object_fetch_little_16,
+  simple_object_fetch_little_32,
+  simple_object_fetch_little_32_ulong,
+  simple_object_set_little_16,
+  simple_object_set_little_32,
+  simple_object_set_little_32_ulong
+};
+
+#ifdef UNSIGNED_64BIT_TYPE
+
+static const struct elf_type_functions elf_big_64_functions =
+{
+  simple_object_fetch_big_16,
+  simple_object_fetch_big_32,
+  simple_object_fetch_big_64,
+  simple_object_set_big_16,
+  simple_object_set_big_32,
+  simple_object_set_big_64
+};
+
+static const struct elf_type_functions elf_little_64_functions =
+{
+  simple_object_fetch_little_16,
+  simple_object_fetch_little_32,
+  simple_object_fetch_little_64,
+  simple_object_set_little_16,
+  simple_object_set_little_32,
+  simple_object_set_little_64
+};
+
+#endif
+
+/* Hideous macro to fetch the value of a field from an external ELF
+   struct of some sort.  TYPEFUNCS is the set of type functions.
+   BUFFER points to the external data.  STRUCTTYPE is the appropriate
+   struct type.  FIELD is a field within the struct.  TYPE is the type
+   of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr.  */
+
+#define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \
+  ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD)))
+
+/* Even more hideous macro to fetch the value of FIELD from BUFFER.
+   SIZE is 32 or 64.  STRUCTTYPE is the name of the struct from
+   elf/external.h: Ehdr, Shdr, etc.  FIELD is the name of a field in
+   the struct.  TYPE is the type of the field in the struct: Elf_Half,
+   Elf_Word, or Elf_Addr.  */
+
+#define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER,	\
+			      FIELD, TYPE)				\
+  ELF_FETCH_STRUCT_FIELD (TYPEFUNCS,					\
+			  Elf ## SIZE ## _External_ ## STRUCTTYPE,	\
+			  FIELD, BUFFER, TYPE)
+
+/* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value.  */
+
+#define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER,		\
+			FIELD, TYPE)					\
+  ((CLASS) == ELFCLASS32						\
+    ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,	\
+			     TYPE)					\
+    : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,	\
+			     TYPE))
+
+/* Hideous macro to set the value of a field in an external ELF
+   structure to VAL.  TYPEFUNCS is the set of type functions.  BUFFER
+   points to the external data.  STRUCTTYPE is the appropriate
+   structure type.  FIELD is a field within the struct.  TYPE is the
+   type of the field in the struct: Elf_Half, Elf_Word, or
+   Elf_Addr.  */
+
+#define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \
+  (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL))
+
+/* Even more hideous macro to set the value of FIELD in BUFFER to VAL.
+   SIZE is 32 or 64.  STRUCTTYPE is the name of the struct from
+   elf/external.h: Ehdr, Shdr, etc.  FIELD is the name of a field in
+   the struct.  TYPE is the type of the field in the struct: Elf_Half,
+   Elf_Word, or Elf_Addr.  */
+
+#define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \
+			    TYPE, VAL)					\
+  ELF_SET_STRUCT_FIELD (TYPEFUNCS,					\
+			Elf ## SIZE ## _External_ ## STRUCTTYPE,	\
+			FIELD, BUFFER, TYPE, VAL)
+
+/* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value.  */
+
+#define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD,	\
+		      TYPE, VAL)					\
+  ((CLASS) == ELFCLASS32						\
+    ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD,	\
+			   TYPE, VAL)					\
+    : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD,	\
+			   TYPE, VAL))
+
+/* Private data for an simple_object_read.  */
+
+struct simple_object_elf_read
+{
+  /* Type functions.  */
+  const struct elf_type_functions* type_functions;
+  /* Elf data.  */
+  unsigned char ei_data;
+  /* Elf class.  */
+  unsigned char ei_class;
+  /* ELF OS ABI.  */
+  unsigned char ei_osabi;
+  /* Elf machine number.  */
+  unsigned short machine;
+  /* Processor specific flags.  */
+  unsigned int flags;
+  /* File offset of section headers.  */
+  ulong_type shoff;
+  /* Number of sections.  */
+  unsigned int shnum;
+  /* Index of string table section header.  */
+  unsigned int shstrndx;
+};
+
+/* Private data for an simple_object_attributes.  */
+
+struct simple_object_elf_attributes
+{
+  /* Type functions.  */
+  const struct elf_type_functions* type_functions;
+  /* Elf data.  */
+  unsigned char ei_data;
+  /* Elf class.  */
+  unsigned char ei_class;
+  /* ELF OS ABI.  */
+  unsigned char ei_osabi;
+  /* Elf machine number.  */
+  unsigned short machine;
+  /* Processor specific flags.  */
+  unsigned int flags;
+};
+
+/* See if we have an ELF file.  */
+
+static void *
+simple_object_elf_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
+			 int descriptor, off_t offset,
+			 const char *segment_name ATTRIBUTE_UNUSED,
+			 const char **errmsg, int *err)
+{
+  unsigned char ei_data;
+  unsigned char ei_class;
+  const struct elf_type_functions *type_functions;
+  unsigned char ehdr[sizeof (Elf64_External_Ehdr)];
+  struct simple_object_elf_read *eor;
+
+  if (header[EI_MAG0] != ELFMAG0
+      || header[EI_MAG1] != ELFMAG1
+      || header[EI_MAG2] != ELFMAG2
+      || header[EI_MAG3] != ELFMAG3
+      || header[EI_VERSION] != EV_CURRENT)
+    {
+      *errmsg = NULL;
+      *err = 0;
+      return NULL;
+    }
+
+  ei_data = header[EI_DATA];
+  if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB)
+    {
+      *errmsg = "unknown ELF endianness";
+      *err = 0;
+      return NULL;
+    }
+
+  ei_class = header[EI_CLASS];
+  switch (ei_class)
+    {
+    case ELFCLASS32:
+      type_functions = (ei_data == ELFDATA2LSB
+			? &elf_little_32_functions
+			: &elf_big_32_functions);
+      break;
+
+    case ELFCLASS64:
+#ifndef UNSIGNED_64BIT_TYPE
+      *errmsg = "64-bit ELF objects not supported";
+      *err = 0;
+      return NULL;
+#else
+      type_functions = (ei_data == ELFDATA2LSB
+			? &elf_little_64_functions
+			: &elf_big_64_functions);
+      break;
+#endif
+
+    default:
+      *errmsg = "unrecognized ELF size";
+      *err = 0;
+      return NULL;
+    }
+
+  if (!simple_object_internal_read (descriptor, offset, ehdr, sizeof ehdr,
+				    errmsg, err))
+    return NULL;
+
+  eor = XNEW (struct simple_object_elf_read);
+  eor->type_functions = type_functions;
+  eor->ei_data = ei_data;
+  eor->ei_class = ei_class;
+  eor->ei_osabi = header[EI_OSABI];
+  eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
+				  e_machine, Elf_Half);
+  eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
+				e_flags, Elf_Word);
+  eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
+				e_shoff, Elf_Addr);
+  eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
+				e_shnum, Elf_Half);
+  eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
+				   e_shstrndx, Elf_Half);
+
+  if ((eor->shnum == 0 || eor->shstrndx == SHN_XINDEX)
+      && eor->shoff != 0)
+    {
+      unsigned char shdr[sizeof (Elf64_External_Shdr)];
+
+      /* Object file has more than 0xffff sections.  */
+
+      if (!simple_object_internal_read (descriptor, offset + eor->shoff, shdr,
+					(ei_class == ELFCLASS32
+					 ? sizeof (Elf32_External_Shdr)
+					 : sizeof (Elf64_External_Shdr)),
+					errmsg, err))
+	{
+	  XDELETE (eor);
+	  return NULL;
+	}
+
+      if (eor->shnum == 0)
+	eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				      shdr, sh_size, Elf_Addr);
+
+      if (eor->shstrndx == SHN_XINDEX)
+	{
+	  eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+					   shdr, sh_link, Elf_Word);
+
+	  /* Versions of the GNU binutils between 2.12 and 2.18 did
+	     not handle objects with more than SHN_LORESERVE sections
+	     correctly.  All large section indexes were offset by
+	     0x100.  There is more information at
+	     http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .
+	     Fortunately these object files are easy to detect, as the
+	     GNU binutils always put the section header string table
+	     near the end of the list of sections.  Thus if the
+	     section header string table index is larger than the
+	     number of sections, then we know we have to subtract
+	     0x100 to get the real section index.  */
+	  if (eor->shstrndx >= eor->shnum
+	      && eor->shstrndx >= SHN_LORESERVE + 0x100)
+	    eor->shstrndx -= 0x100;
+	}
+    }
+
+  if (eor->shstrndx >= eor->shnum)
+    {
+      *errmsg = "invalid ELF shstrndx >= shnum";
+      *err = 0;
+      XDELETE (eor);
+      return NULL;
+    }
+
+  return (void *) eor;
+}
+
+/* Find all sections in an ELF file.  */
+
+static const char *
+simple_object_elf_find_sections (simple_object_read *sobj,
+				 int (*pfn) (void *, const char *,
+					     off_t offset, off_t length),
+				 void *data,
+				 int *err)
+{
+  struct simple_object_elf_read *eor =
+    (struct simple_object_elf_read *) sobj->data;
+  const struct elf_type_functions *type_functions = eor->type_functions;
+  unsigned char ei_class = eor->ei_class;
+  size_t shdr_size;
+  unsigned int shnum;
+  unsigned char *shdrs;
+  const char *errmsg;
+  unsigned char *shstrhdr;
+  size_t name_size;
+  off_t shstroff;
+  unsigned char *names;
+  unsigned int i;
+
+  shdr_size = (ei_class == ELFCLASS32
+	       ? sizeof (Elf32_External_Shdr)
+	       : sizeof (Elf64_External_Shdr));
+
+  /* Read the section headers.  We skip section 0, which is not a
+     useful section.  */
+
+  shnum = eor->shnum;
+  shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
+
+  if (!simple_object_internal_read (sobj->descriptor,
+				    sobj->offset + eor->shoff + shdr_size,
+				    shdrs,
+				    shdr_size * (shnum - 1),
+				    &errmsg, err))
+    {
+      XDELETEVEC (shdrs);
+      return errmsg;
+    }
+
+  /* Read the section names.  */
+
+  shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
+  name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+			       shstrhdr, sh_size, Elf_Addr);
+  shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+			      shstrhdr, sh_offset, Elf_Addr);
+  names = XNEWVEC (unsigned char, name_size);
+  if (!simple_object_internal_read (sobj->descriptor,
+				    sobj->offset + shstroff,
+				    names, name_size, &errmsg, err))
+    {
+      XDELETEVEC (names);
+      XDELETEVEC (shdrs);
+      return errmsg;
+    }
+
+  for (i = 1; i < shnum; ++i)
+    {
+      unsigned char *shdr;
+      unsigned int sh_name;
+      const char *name;
+      off_t offset;
+      off_t length;
+
+      shdr = shdrs + (i - 1) * shdr_size;
+      sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				 shdr, sh_name, Elf_Word);
+      if (sh_name >= name_size)
+	{
+	  *err = 0;
+	  XDELETEVEC (names);
+	  XDELETEVEC (shdrs);
+	  return "ELF section name out of range";
+	}
+
+      name = (const char *) names + sh_name;
+      offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				shdr, sh_offset, Elf_Addr);
+      length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				shdr, sh_size, Elf_Addr);
+
+      if (!(*pfn) (data, name, offset, length))
+	break;
+    }
+
+  XDELETEVEC (names);
+  XDELETEVEC (shdrs);
+
+  return NULL;
+}
+
+/* Fetch the attributes for an simple_object_read.  */
+
+static void *
+simple_object_elf_fetch_attributes (simple_object_read *sobj,
+				    const char **errmsg ATTRIBUTE_UNUSED,
+				    int *err ATTRIBUTE_UNUSED)
+{
+  struct simple_object_elf_read *eor =
+    (struct simple_object_elf_read *) sobj->data;
+  struct simple_object_elf_attributes *ret;
+
+  ret = XNEW (struct simple_object_elf_attributes);
+  ret->type_functions = eor->type_functions;
+  ret->ei_data = eor->ei_data;
+  ret->ei_class = eor->ei_class;
+  ret->ei_osabi = eor->ei_osabi;
+  ret->machine = eor->machine;
+  ret->flags = eor->flags;
+  return ret;
+}
+
+/* Release the privata data for an simple_object_read.  */
+
+static void
+simple_object_elf_release_read (void *data)
+{
+  XDELETE (data);
+}
+
+/* Compare two attributes structures.  */
+
+static const char *
+simple_object_elf_attributes_compare (void *data1, void *data2, int *err)
+{
+  struct simple_object_elf_attributes *attrs1 =
+    (struct simple_object_elf_attributes *) data1;
+  struct simple_object_elf_attributes *attrs2 =
+    (struct simple_object_elf_attributes *) data2;
+
+  if (attrs1->ei_data != attrs2->ei_data
+      || attrs1->ei_class != attrs2->ei_class
+      || attrs1->machine != attrs2->machine)
+    {
+      *err = 0;
+      return "ELF object format mismatch";
+    }
+  return NULL;
+}
+
+/* Release the private data for an attributes structure.  */
+
+static void
+simple_object_elf_release_attributes (void *data)
+{
+  XDELETE (data);
+}
+
+/* Prepare to write out a file.  */
+
+static void *
+simple_object_elf_start_write (void *attributes_data,
+			       const char **errmsg ATTRIBUTE_UNUSED,
+			       int *err ATTRIBUTE_UNUSED)
+{
+  struct simple_object_elf_attributes *attrs =
+    (struct simple_object_elf_attributes *) attributes_data;
+  struct simple_object_elf_attributes *ret;
+
+  /* We're just going to record the attributes, but we need to make a
+     copy because the user may delete them.  */
+  ret = XNEW (struct simple_object_elf_attributes);
+  *ret = *attrs;
+  return ret;
+}
+
+/* Write out an ELF ehdr.  */
+
+static int
+simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor,
+			      const char **errmsg, int *err)
+{
+  struct simple_object_elf_attributes *attrs =
+    (struct simple_object_elf_attributes *) sobj->data;
+  const struct elf_type_functions* fns;
+  unsigned char cl;
+  size_t ehdr_size;
+  unsigned char buf[sizeof (Elf64_External_Ehdr)];
+  simple_object_write_section *section;
+  unsigned int shnum;
+
+  fns = attrs->type_functions;
+  cl = attrs->ei_class;
+
+  shnum = 0;
+  for (section = sobj->sections; section != NULL; section = section->next)
+    ++shnum;
+  if (shnum > 0)
+    {
+      /* Add a section header for the dummy section and one for
+	 .shstrtab.  */
+      shnum += 2;
+    }
+
+  ehdr_size = (cl == ELFCLASS32
+	       ? sizeof (Elf32_External_Ehdr)
+	       : sizeof (Elf64_External_Ehdr));
+  memset (buf, 0, sizeof (Elf64_External_Ehdr));
+
+  buf[EI_MAG0] = ELFMAG0;
+  buf[EI_MAG1] = ELFMAG1;
+  buf[EI_MAG2] = ELFMAG2;
+  buf[EI_MAG3] = ELFMAG3;
+  buf[EI_CLASS] = cl;
+  buf[EI_DATA] = attrs->ei_data;
+  buf[EI_VERSION] = EV_CURRENT;
+  buf[EI_OSABI] = attrs->ei_osabi;
+
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_type, Elf_Half, ET_REL);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_machine, Elf_Half, attrs->machine);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_version, Elf_Word, EV_CURRENT);
+  /* e_entry left as zero.  */
+  /* e_phoff left as zero.  */
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shoff, Elf_Addr, ehdr_size);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_flags, Elf_Word, attrs->flags);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_ehsize, Elf_Half, ehdr_size);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_phentsize, Elf_Half,
+		 (cl == ELFCLASS32
+		  ? sizeof (Elf32_External_Phdr)
+		  : sizeof (Elf64_External_Phdr)));
+  /* e_phnum left as zero.  */
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shentsize, Elf_Half,
+		 (cl == ELFCLASS32
+		  ? sizeof (Elf32_External_Shdr)
+		  : sizeof (Elf64_External_Shdr)));
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half, shnum);
+  ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half,
+		 shnum == 0 ? 0 : shnum - 1);
+
+  return simple_object_internal_write (descriptor, 0, buf, ehdr_size,
+				       errmsg, err);
+}
+
+/* Write out an ELF shdr.  */
+
+static int
+simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
+			      off_t offset, unsigned int sh_name,
+			      unsigned int sh_type, unsigned int sh_flags,
+			      unsigned int sh_offset, unsigned int sh_size,
+			      unsigned int sh_addralign, const char **errmsg,
+			      int *err)
+{
+  struct simple_object_elf_attributes *attrs =
+    (struct simple_object_elf_attributes *) sobj->data;
+  const struct elf_type_functions* fns;
+  unsigned char cl;
+  size_t shdr_size;
+  unsigned char buf[sizeof (Elf64_External_Shdr)];
+
+  fns = attrs->type_functions;
+  cl = attrs->ei_class;
+
+  shdr_size = (cl == ELFCLASS32
+	       ? sizeof (Elf32_External_Shdr)
+	       : sizeof (Elf64_External_Shdr));
+  memset (buf, 0, sizeof (Elf64_External_Shdr));
+
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
+  /* sh_link left as zero.  */
+  /* sh_info left as zero.  */
+  ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
+  /* sh_entsize left as zero.  */
+
+  return simple_object_internal_write (descriptor, offset, buf, shdr_size,
+				       errmsg, err);
+}
+
+/* Write out a complete ELF file.
+   Ehdr
+   initial dummy Shdr
+   user-created Shdrs
+   .shstrtab Shdr
+   user-created section data
+   .shstrtab data  */
+
+static const char *
+simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
+				 int *err)
+{
+  struct simple_object_elf_attributes *attrs =
+    (struct simple_object_elf_attributes *) sobj->data;
+  unsigned char cl;
+  size_t ehdr_size;
+  size_t shdr_size;
+  const char *errmsg;
+  simple_object_write_section *section;
+  unsigned int shnum;
+  size_t shdr_offset;
+  size_t sh_offset;
+  size_t sh_name;
+  unsigned char zero;
+
+  if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
+    return errmsg;
+
+  cl = attrs->ei_class;
+  if (cl == ELFCLASS32)
+    {
+      ehdr_size = sizeof (Elf32_External_Ehdr);
+      shdr_size = sizeof (Elf32_External_Shdr);
+    }
+  else
+    {
+      ehdr_size = sizeof (Elf64_External_Ehdr);
+      shdr_size = sizeof (Elf64_External_Shdr);
+    }
+
+  shnum = 0;
+  for (section = sobj->sections; section != NULL; section = section->next)
+    ++shnum;
+  if (shnum == 0)
+    return NULL;
+
+  /* Add initial dummy Shdr and .shstrtab.  */
+  shnum += 2;
+
+  shdr_offset = ehdr_size;
+  sh_offset = shdr_offset + shnum * shdr_size;
+
+  if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
+				     0, 0, 0, 0, 0, 0, &errmsg, err))
+    return errmsg;
+
+  shdr_offset += shdr_size;
+
+  sh_name = 1;
+  for (section = sobj->sections; section != NULL; section = section->next)
+    {
+      size_t mask;
+      size_t new_sh_offset;
+      size_t sh_size;
+      struct simple_object_write_section_buffer *buffer;
+
+      mask = (1U << section->align) - 1;
+      new_sh_offset = sh_offset + mask;
+      new_sh_offset &= ~ mask;
+      while (new_sh_offset > sh_offset)
+	{
+	  unsigned char zeroes[16];
+	  size_t write;
+
+	  memset (zeroes, 0, sizeof zeroes);
+	  write = new_sh_offset - sh_offset;
+	  if (write > sizeof zeroes)
+	    write = sizeof zeroes;
+	  if (!simple_object_internal_write (descriptor, sh_offset, zeroes,
+					     write, &errmsg, err))
+	    return errmsg;
+	  sh_offset += write;
+	}
+
+      sh_size = 0;
+      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
+	{
+	  if (!simple_object_internal_write (descriptor, sh_offset + sh_size,
+					     ((const unsigned char *)
+					      buffer->buffer),
+					     buffer->size, &errmsg, err))
+	    return errmsg;
+	  sh_size += buffer->size;
+	}
+
+      if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
+					 sh_name, SHT_PROGBITS, 0, sh_offset,
+					 sh_size, 1U << section->align,
+					 &errmsg, err))
+	return errmsg;
+
+      shdr_offset += shdr_size;
+      sh_name += strlen (section->name) + 1;
+      sh_offset += sh_size;
+    }
+
+  if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
+				     sh_name, SHT_STRTAB, 0, sh_offset,
+				     sh_name + strlen (".shstrtab") + 1,
+				     1, &errmsg, err))
+    return errmsg;
+
+  /* .shstrtab has a leading zero byte.  */
+  zero = 0;
+  if (!simple_object_internal_write (descriptor, sh_offset, &zero, 1,
+				     &errmsg, err))
+    return errmsg;
+  ++sh_offset;
+
+  for (section = sobj->sections; section != NULL; section = section->next)
+    {
+      size_t len;
+
+      len = strlen (section->name) + 1;
+      if (!simple_object_internal_write (descriptor, sh_offset,
+					 (const unsigned char *) section->name,
+					 len, &errmsg, err))
+	return errmsg;
+      sh_offset += len;
+    }
+
+  if (!simple_object_internal_write (descriptor, sh_offset,
+				     (const unsigned char *) ".shstrtab",
+				     strlen (".shstrtab") + 1, &errmsg, err))
+    return errmsg;
+
+  return NULL;
+}
+
+/* Release the private data for an simple_object_write structure.  */
+
+static void
+simple_object_elf_release_write (void *data)
+{
+  XDELETE (data);
+}
+
+/* The ELF functions.  */
+
+const struct simple_object_functions simple_object_elf_functions =
+{
+  simple_object_elf_match,
+  simple_object_elf_find_sections,
+  simple_object_elf_fetch_attributes,
+  simple_object_elf_release_read,
+  simple_object_elf_attributes_compare,
+  simple_object_elf_release_attributes,
+  simple_object_elf_start_write,
+  simple_object_elf_write_to_file,
+  simple_object_elf_release_write
+};
Index: libiberty/configure.ac
===================================================================
--- libiberty/configure.ac	(revision 166080)
+++ libiberty/configure.ac	(working copy)
@@ -290,6 +290,7 @@ fi
 
 AC_TYPE_INTPTR_T
 AC_TYPE_UINTPTR_T
+AC_TYPE_SSIZE_T
 
 # Given the above check, we always have uintptr_t or a fallback
 # definition.  So define HAVE_UINTPTR_T in case any imported code
Index: libiberty/simple-object-mach-o.c
===================================================================
--- libiberty/simple-object-mach-o.c	(revision 0)
+++ libiberty/simple-object-mach-o.c	(revision 0)
@@ -0,0 +1,1026 @@
+/* simple-object-mach-o.c -- routines to manipulate Mach-O object files.
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+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, 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, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "libiberty.h"
+#include "simple-object.h"
+
+#include <stddef.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "simple-object-common.h"
+
+/* Mach-O structures and constants.  */
+
+/* Mach-O header (32-bit version).  */
+
+struct mach_o_header_32
+{
+  unsigned char magic[4];	/* Magic number.  */
+  unsigned char cputype[4];	/* CPU that this object is for.  */
+  unsigned char cpusubtype[4];	/* CPU subtype.  */
+  unsigned char filetype[4];	/* Type of file.  */
+  unsigned char ncmds[4];	/* Number of load commands.  */
+  unsigned char sizeofcmds[4];	/* Total size of load commands.  */
+  unsigned char flags[4];	/* Flags for special featues.  */
+};
+
+/* Mach-O header (64-bit version).  */
+
+struct mach_o_header_64
+{
+  unsigned char magic[4];	/* Magic number.  */
+  unsigned char cputype[4];	/* CPU that this object is for.  */
+  unsigned char cpusubtype[4];	/* CPU subtype.  */
+  unsigned char filetype[4];	/* Type of file.  */
+  unsigned char ncmds[4];	/* Number of load commands.  */
+  unsigned char sizeofcmds[4];	/* Total size of load commands.  */
+  unsigned char flags[4];	/* Flags for special featues.  */
+  unsigned char reserved[4];	/* Reserved.  Duh.  */
+};
+
+/* For magic field in header.  */
+
+#define MACH_O_MH_MAGIC			0xfeedface
+#define MACH_O_MH_MAGIC_64		0xfeedfacf
+
+/* For filetype field in header.  */
+
+#define MACH_O_MH_OBJECT		0x01
+
+/* A Mach-O file is a list of load commands.  This is the header of a
+   load command.  */
+
+struct mach_o_load_command
+{
+  unsigned char cmd[4];		/* The type of load command.  */
+  unsigned char cmdsize[4];	/* Size in bytes of entire command.  */
+};
+
+/* For cmd field in load command.   */
+
+#define MACH_O_LC_SEGMENT		0x01
+#define MACH_O_LC_SEGMENT_64		0x19
+
+/* LC_SEGMENT load command.  */
+
+struct mach_o_segment_command_32
+{
+  unsigned char cmd[4];		/* The type of load command (LC_SEGMENT).  */
+  unsigned char cmdsize[4];	/* Size in bytes of entire command.  */
+  unsigned char segname[16];	/* Name of this segment.  */
+  unsigned char vmaddr[4];	/* Virtual memory address of this segment.  */
+  unsigned char vmsize[4];	/* Size there, in bytes.  */
+  unsigned char fileoff[4];	/* Offset in bytes of the data to be mapped.  */
+  unsigned char filesize[4];	/* Size in bytes on disk.  */
+  unsigned char maxprot[4];	/* Maximum permitted vmem protection.  */
+  unsigned char initprot[4];	/* Initial vmem protection.  */
+  unsigned char nsects[4];	/* Number of sections in this segment.  */
+  unsigned char flags[4];	/* Flags that affect the loading.  */
+};
+
+/* LC_SEGMENT_64 load command.  */
+
+struct mach_o_segment_command_64
+{
+  unsigned char cmd[4];		/* The type of load command (LC_SEGMENT_64).  */
+  unsigned char cmdsize[4];	/* Size in bytes of entire command.  */
+  unsigned char segname[16];	/* Name of this segment.  */
+  unsigned char vmaddr[8];	/* Virtual memory address of this segment.  */
+  unsigned char vmsize[8];	/* Size there, in bytes.  */
+  unsigned char fileoff[8];	/* Offset in bytes of the data to be mapped.  */
+  unsigned char filesize[8];	/* Size in bytes on disk.  */
+  unsigned char maxprot[4];	/* Maximum permitted vmem protection.  */
+  unsigned char initprot[4];	/* Initial vmem protection.  */
+  unsigned char nsects[4];	/* Number of sections in this segment.  */
+  unsigned char flags[4];	/* Flags that affect the loading.  */
+};
+
+/* 32-bit section header.  */
+
+struct mach_o_section_32
+{
+  unsigned char sectname[16];	/* Section name.  */
+  unsigned char segname[16];	/* Segment that the section belongs to.  */
+  unsigned char addr[4];	/* Address of this section in memory.  */
+  unsigned char size[4];	/* Size in bytes of this section.  */
+  unsigned char offset[4];	/* File offset of this section.  */
+  unsigned char align[4];	/* log2 of this section's alignment.  */
+  unsigned char reloff[4];	/* File offset of this section's relocs.  */
+  unsigned char nreloc[4];	/* Number of relocs for this section.  */
+  unsigned char flags[4];	/* Section flags/attributes.  */
+  unsigned char reserved1[4];
+  unsigned char reserved2[4];
+};
+
+/* 64-bit section header.  */
+
+struct mach_o_section_64
+{
+  unsigned char sectname[16];	/* Section name.  */
+  unsigned char segname[16];	/* Segment that the section belongs to.  */
+  unsigned char addr[8];	/* Address of this section in memory.  */
+  unsigned char size[8];	/* Size in bytes of this section.  */
+  unsigned char offset[4];	/* File offset of this section.  */
+  unsigned char align[4];	/* log2 of this section's alignment.  */
+  unsigned char reloff[4];	/* File offset of this section's relocs.  */
+  unsigned char nreloc[4];	/* Number of relocs for this section.  */
+  unsigned char flags[4];	/* Section flags/attributes.  */
+  unsigned char reserved1[4];
+  unsigned char reserved2[4];
+  unsigned char reserved3[4];
+};
+
+/* Flags for Mach-O sections.  */
+
+#define MACH_O_S_ATTR_DEBUG			0x02000000
+
+/* The length of a segment or section name.  */
+
+#define MACH_O_NAME_LEN (16)
+
+/* A GNU specific extension for long section names.  */
+
+#define GNU_SECTION_NAMES "__section_names"
+
+/* Private data for an simple_object_read.  */
+
+struct simple_object_mach_o_read
+{
+  /* User specified segment name.  */
+  char *segment_name;
+  /* Magic number.  */
+  unsigned int magic;
+  /* Whether this file is big-endian.  */
+  int is_big_endian;
+  /* CPU type from header.  */
+  unsigned int cputype;
+  /* CPU subtype from header.  */
+  unsigned int cpusubtype;
+  /* Number of commands, from header.  */
+  unsigned int ncmds;
+  /* Flags from header.  */
+  unsigned int flags;
+  /* Reserved field from header, only used on 64-bit.  */
+  unsigned int reserved;
+};
+
+/* Private data for an simple_object_attributes.  */
+
+struct simple_object_mach_o_attributes
+{
+  /* Magic number.  */
+  unsigned int magic;
+  /* Whether this file is big-endian.  */
+  int is_big_endian;
+  /* CPU type from header.  */
+  unsigned int cputype;
+  /* CPU subtype from header.  */
+  unsigned int cpusubtype;
+  /* Flags from header.  */
+  unsigned int flags;
+  /* Reserved field from header, only used on 64-bit.  */
+  unsigned int reserved;
+};
+
+/* See if we have a Mach-O file.  */
+
+static void *
+simple_object_mach_o_match (
+    unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
+    int descriptor,
+    off_t offset,
+    const char *segment_name,
+    const char **errmsg,
+    int *err)
+{
+  unsigned int magic;
+  int is_big_endian;
+  unsigned int (*fetch_32) (const unsigned char *);
+  unsigned int filetype;
+  struct simple_object_mach_o_read *omr;
+  unsigned char buf[sizeof (struct mach_o_header_64)];
+  unsigned char *b;
+
+  magic = simple_object_fetch_big_32 (header);
+  if (magic == MACH_O_MH_MAGIC || magic == MACH_O_MH_MAGIC_64)
+    is_big_endian = 1;
+  else
+    {
+      magic = simple_object_fetch_little_32 (header);
+      if (magic == MACH_O_MH_MAGIC || magic == MACH_O_MH_MAGIC_64)
+	is_big_endian = 0;
+      else
+	{
+	  *errmsg = NULL;
+	  *err = 0;
+	  return NULL;
+	}
+    }
+
+#ifndef UNSIGNED_64BIT_TYPE
+  if (magic == MACH_O_MH_MAGIC_64)
+    {
+      *errmsg = "64-bit Mach-O objects not supported";
+      *err = 0;
+      return NULL;
+    }
+#endif
+
+  /* We require the user to provide a segment name.  This is
+     unfortunate but I don't see any good choices here.  */
+
+  if (segment_name == NULL)
+    {
+      *errmsg = "Mach-O file found but no segment name specified";
+      *err = 0;
+      return NULL;
+    }
+
+  if (strlen (segment_name) > MACH_O_NAME_LEN)
+    {
+      *errmsg = "Mach-O segment name too long";
+      *err = 0;
+      return NULL;
+    }
+
+  /* The 32-bit and 64-bit headers are similar enough that we can use
+     the same code.  */
+
+  fetch_32 = (is_big_endian
+	      ? simple_object_fetch_big_32
+	      : simple_object_fetch_little_32);
+
+  if (!simple_object_internal_read (descriptor, offset, buf,
+				    (magic == MACH_O_MH_MAGIC
+				     ? sizeof (struct mach_o_header_32)
+				     : sizeof (struct mach_o_header_64)),
+				    errmsg, err))
+    return NULL;
+
+  b = &buf[0];
+
+  filetype = (*fetch_32) (b + offsetof (struct mach_o_header_32, filetype));
+  if (filetype != MACH_O_MH_OBJECT)
+    {
+      *errmsg = "Mach-O file is not object file";
+      *err = 0;
+      return NULL;
+    }
+
+  omr = XNEW (struct simple_object_mach_o_read);
+  omr->segment_name = xstrdup (segment_name);
+  omr->magic = magic;
+  omr->is_big_endian = is_big_endian;
+  omr->cputype = (*fetch_32) (b + offsetof (struct mach_o_header_32, cputype));
+  omr->cpusubtype = (*fetch_32) (b
+				 + offsetof (struct mach_o_header_32,
+					     cpusubtype));
+  omr->ncmds = (*fetch_32) (b + offsetof (struct mach_o_header_32, ncmds));
+  omr->flags = (*fetch_32) (b + offsetof (struct mach_o_header_32, flags));
+  if (magic == MACH_O_MH_MAGIC)
+    omr->reserved = 0;
+  else
+    omr->reserved = (*fetch_32) (b
+				 + offsetof (struct mach_o_header_64,
+					     reserved));
+
+  return (void *) omr;
+}
+
+/* Get the file offset and size from a section header.  */
+
+static void
+simple_object_mach_o_section_info (int is_big_endian, int is_32,
+				   const unsigned char *sechdr, off_t *offset,
+				   size_t *size)
+{
+  unsigned int (*fetch_32) (const unsigned char *);
+  ulong_type (*fetch_64) (const unsigned char *);
+
+  fetch_32 = (is_big_endian
+	      ? simple_object_fetch_big_32
+	      : simple_object_fetch_little_32);
+
+  fetch_64 = NULL;
+#ifdef UNSIGNED_64BIT_TYPE
+  fetch_64 = (is_big_endian
+	      ? simple_object_fetch_big_64
+	      : simple_object_fetch_little_64);
+#endif
+
+  if (is_32)
+    {
+      *offset = fetch_32 (sechdr
+			  + offsetof (struct mach_o_section_32, offset));
+      *size = fetch_32 (sechdr
+			+ offsetof (struct mach_o_section_32, size));
+    }
+  else
+    {
+      *offset = fetch_32 (sechdr
+			  + offsetof (struct mach_o_section_64, offset));
+      *size = fetch_64 (sechdr
+			+ offsetof (struct mach_o_section_64, size));
+    }
+}
+
+/* Handle a segment in a Mach-O file.  Return 1 if we should continue,
+   0 if the caller should return.  */
+
+static int
+simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
+			      const unsigned char *segbuf,
+			      int (*pfn) (void *, const char *, off_t offset,
+					  off_t length),
+			      void *data,
+			      const char **errmsg, int *err)
+{
+  struct simple_object_mach_o_read *omr =
+    (struct simple_object_mach_o_read *) sobj->data;
+  unsigned int (*fetch_32) (const unsigned char *);
+  int is_32;
+  size_t seghdrsize;
+  size_t sechdrsize;
+  size_t sectname_offset;
+  unsigned int nsects;
+  unsigned char *secdata;
+  unsigned int i;
+  unsigned int strtab_index;
+  char *strtab;
+  size_t strtab_size;
+
+  fetch_32 = (omr->is_big_endian
+	      ? simple_object_fetch_big_32
+	      : simple_object_fetch_little_32);
+
+  is_32 = omr->magic == MACH_O_MH_MAGIC;
+
+  if (is_32)
+    {
+      seghdrsize = sizeof (struct mach_o_segment_command_32);
+      sechdrsize = sizeof (struct mach_o_section_32);
+      sectname_offset = offsetof (struct mach_o_section_32, sectname);
+      nsects = (*fetch_32) (segbuf
+			    + offsetof (struct mach_o_segment_command_32,
+					nsects));
+    }
+  else
+    {
+      seghdrsize = sizeof (struct mach_o_segment_command_64);
+      sechdrsize = sizeof (struct mach_o_section_64);
+      sectname_offset = offsetof (struct mach_o_section_64, sectname);
+      nsects = (*fetch_32) (segbuf
+			    + offsetof (struct mach_o_segment_command_64,
+					nsects));
+    }
+
+  secdata = XNEWVEC (unsigned char, nsects * sechdrsize);
+  if (!simple_object_internal_read (sobj->descriptor, offset + seghdrsize,
+				    secdata, nsects * sechdrsize, errmsg, err))
+    {
+      XDELETEVEC (secdata);
+      return 0;
+    }
+
+  /* Scan for a __section_names section.  This is in effect a GNU
+     extension that permits section names longer than 16 chars.  */
+
+  for (i = 0; i < nsects; ++i)
+    {
+      size_t nameoff;
+
+      nameoff = i * sechdrsize + sectname_offset;
+      if (strcmp ((char *) secdata + nameoff, GNU_SECTION_NAMES) == 0)
+	break;
+    }
+
+  strtab_index = i;
+  if (strtab_index >= nsects)
+    {
+      strtab = NULL;
+      strtab_size = 0;
+    }
+  else
+    {
+      off_t strtab_offset;
+
+      simple_object_mach_o_section_info (omr->is_big_endian, is_32,
+					 secdata + strtab_index * sechdrsize,
+					 &strtab_offset, &strtab_size);
+      strtab = XNEWVEC (char, strtab_size);
+      if (!simple_object_internal_read (sobj->descriptor,
+					sobj->offset + strtab_offset,
+					(unsigned char *) strtab, strtab_size,
+					errmsg, err))
+	{
+	  XDELETEVEC (strtab);
+	  XDELETEVEC (secdata);
+	  return 0;
+	}
+    }
+
+  /* Process the sections.  */
+
+  for (i = 0; i < nsects; ++i)
+    {
+      const unsigned char *sechdr;
+      char namebuf[MACH_O_NAME_LEN + 1];
+      char *name;
+      off_t secoffset;
+      size_t secsize;
+
+      if (i == strtab_index)
+	continue;
+
+      sechdr = secdata + i * sechdrsize;
+      memcpy (namebuf, sechdr + sectname_offset, MACH_O_NAME_LEN);
+      namebuf[MACH_O_NAME_LEN] = '\0';
+
+      name = &namebuf[0];
+      if (strtab != NULL && name[0] == '_' && name[1] == '_')
+	{
+	  unsigned long stringoffset;
+
+	  if (sscanf (name + 2, "%08lX", &stringoffset) == 1)
+	    {
+	      if (stringoffset >= strtab_size)
+		{
+		  *errmsg = "section name offset out of range";
+		  *err = 0;
+		  XDELETEVEC (strtab);
+		  XDELETEVEC (secdata);
+		  return 0;
+		}
+
+	      name = strtab + stringoffset;
+	    }
+	}
+
+      simple_object_mach_o_section_info (omr->is_big_endian, is_32, sechdr,
+					 &secoffset, &secsize);
+
+      if (!(*pfn) (data, name, secoffset, secsize))
+	{
+	  *errmsg = NULL;
+	  *err = 0;
+	  XDELETEVEC (strtab);
+	  XDELETEVEC (secdata);
+	  return 0;
+	}
+    }
+
+  XDELETEVEC (strtab);
+  XDELETEVEC (secdata);
+
+  return 1;
+}
+
+/* Find all sections in a Mach-O file.  */
+
+static const char *
+simple_object_mach_o_find_sections (simple_object_read *sobj,
+				    int (*pfn) (void *, const char *,
+						off_t offset, off_t length),
+				    void *data,
+				    int *err)
+{
+  struct simple_object_mach_o_read *omr =
+    (struct simple_object_mach_o_read *) sobj->data;
+  off_t offset;
+  size_t seghdrsize;
+  unsigned int (*fetch_32) (const unsigned char *);
+  const char *errmsg;
+  unsigned int i;
+
+  if (omr->magic == MACH_O_MH_MAGIC)
+    {
+      offset = sizeof (struct mach_o_header_32);
+      seghdrsize = sizeof (struct mach_o_segment_command_32);
+    }
+  else
+    {
+      offset = sizeof (struct mach_o_header_64);
+      seghdrsize = sizeof (struct mach_o_segment_command_64);
+    }
+
+  fetch_32 = (omr->is_big_endian
+	      ? simple_object_fetch_big_32
+	      : simple_object_fetch_little_32);
+
+  for (i = 0; i < omr->ncmds; ++i)
+    {
+      unsigned char loadbuf[sizeof (struct mach_o_load_command)];
+      unsigned int cmd;
+      unsigned int cmdsize;
+
+      if (!simple_object_internal_read (sobj->descriptor,
+					sobj->offset + offset,
+					loadbuf,
+					sizeof (struct mach_o_load_command),
+					&errmsg, err))
+	return errmsg;
+
+      cmd = (*fetch_32) (loadbuf + offsetof (struct mach_o_load_command, cmd));
+      cmdsize = (*fetch_32) (loadbuf
+			     + offsetof (struct mach_o_load_command, cmdsize));
+
+      if (cmd == MACH_O_LC_SEGMENT || cmd == MACH_O_LC_SEGMENT_64)
+	{
+	  unsigned char segbuf[sizeof (struct mach_o_segment_command_64)];
+	  char *segname;
+
+	  if (!simple_object_internal_read (sobj->descriptor,
+					    sobj->offset + offset,
+					    segbuf, seghdrsize, &errmsg, err))
+	    return errmsg;
+
+	  /* The segment name is in the same position for both 32-bit
+	     and 64-bit.  */
+	  segname = (char *) (&segbuf[0]
+			      + offsetof (struct mach_o_segment_command_32,
+					  segname));
+	  if (strncmp (omr->segment_name, segname, MACH_O_NAME_LEN) == 0)
+	    {
+	      int r;
+
+	      r = simple_object_mach_o_segment (sobj, offset, segbuf, pfn,
+						data, &errmsg, err);
+	      if (!r)
+		return errmsg;
+
+	      /* We can probably just return NULL here.  There
+		 probably won't be another function with the same
+		 name.  */
+	    }
+	}
+
+      offset += cmdsize;
+    }
+
+  return NULL;
+}
+
+/* Fetch the attributes for an simple_object_read.  */
+
+static void *
+simple_object_mach_o_fetch_attributes (simple_object_read *sobj,
+				       const char **errmsg ATTRIBUTE_UNUSED,
+				       int *err ATTRIBUTE_UNUSED)
+{
+  struct simple_object_mach_o_read *omr =
+    (struct simple_object_mach_o_read *) sobj->data;
+  struct simple_object_mach_o_attributes *ret;
+
+  ret = XNEW (struct simple_object_mach_o_attributes);
+  ret->magic = omr->magic;
+  ret->is_big_endian = omr->is_big_endian;
+  ret->cputype = omr->cputype;
+  ret->cpusubtype = omr->cpusubtype;
+  ret->flags = omr->flags;
+  ret->reserved = omr->reserved;
+  return ret;
+}
+
+/* Release the private data for an simple_object_read.  */
+
+static void
+simple_object_mach_o_release_read (void *data)
+{
+  struct simple_object_mach_o_read *omr =
+    (struct simple_object_mach_o_read *) data;
+
+  free (omr->segment_name);
+  XDELETE (omr);
+}
+
+/* Compare two attributes structures.  */
+
+static const char *
+simple_object_mach_o_attributes_compare (void *data1, void *data2, int *err)
+{
+  struct simple_object_mach_o_attributes *attrs1 =
+    (struct simple_object_mach_o_attributes *) data1;
+  struct simple_object_mach_o_attributes *attrs2 =
+    (struct simple_object_mach_o_attributes *) data2;
+
+  if (attrs1->magic != attrs2->magic
+      || attrs1->is_big_endian != attrs2->is_big_endian
+      || attrs1->cputype != attrs2->cputype)
+    {
+      *err = 0;
+      return "Mach-O object format mismatch";
+    }
+  return NULL;
+}
+
+/* Release the private data for an attributes structure.  */
+
+static void
+simple_object_mach_o_release_attributes (void *data)
+{
+  XDELETE (data);
+}
+
+/* Prepare to write out a file.  */
+
+static void *
+simple_object_mach_o_start_write (void *attributes_data,
+				  const char **errmsg ATTRIBUTE_UNUSED,
+				  int *err ATTRIBUTE_UNUSED)
+{
+  struct simple_object_mach_o_attributes *attrs =
+    (struct simple_object_mach_o_attributes *) attributes_data;
+  struct simple_object_mach_o_attributes *ret;
+
+  /* We're just going to record the attributes, but we need to make a
+     copy because the user may delete them.  */
+  ret = XNEW (struct simple_object_mach_o_attributes);
+  *ret = *attrs;
+  return ret;
+}
+
+/* Write out the header of a Mach-O file.  */
+
+static int
+simple_object_mach_o_write_header (simple_object_write *sobj, int descriptor,
+				   size_t nsects, const char **errmsg,
+				   int *err)
+{
+  struct simple_object_mach_o_attributes *attrs =
+    (struct simple_object_mach_o_attributes *) sobj->data;
+  void (*set_32) (unsigned char *, unsigned int);
+  unsigned char hdrbuf[sizeof (struct mach_o_header_64)];
+  unsigned char *hdr;
+  size_t wrsize;
+
+  set_32 = (attrs->is_big_endian
+	    ? simple_object_set_big_32
+	    : simple_object_set_little_32);
+
+  memset (hdrbuf, 0, sizeof hdrbuf);
+
+  /* The 32-bit and 64-bit headers start out the same.  */
+
+  hdr = &hdrbuf[0];
+  set_32 (hdr + offsetof (struct mach_o_header_32, magic), attrs->magic);
+  set_32 (hdr + offsetof (struct mach_o_header_32, cputype), attrs->cputype);
+  set_32 (hdr + offsetof (struct mach_o_header_32, cpusubtype),
+	  attrs->cpusubtype);
+  set_32 (hdr + offsetof (struct mach_o_header_32, filetype), MACH_O_MH_OBJECT);
+  set_32 (hdr + offsetof (struct mach_o_header_32, ncmds), 1);
+  set_32 (hdr + offsetof (struct mach_o_header_32, flags), attrs->flags);
+  if (attrs->magic == MACH_O_MH_MAGIC)
+    {
+      wrsize = sizeof (struct mach_o_header_32);
+      set_32 (hdr + offsetof (struct mach_o_header_32, sizeofcmds),
+	      (sizeof (struct mach_o_segment_command_32)
+	       + nsects * sizeof (struct mach_o_section_32)));
+    }
+  else
+    {
+      set_32 (hdr + offsetof (struct mach_o_header_64, sizeofcmds),
+	      (sizeof (struct mach_o_segment_command_64)
+	       + nsects * sizeof (struct mach_o_section_64)));
+      set_32 (hdr + offsetof (struct mach_o_header_64, reserved),
+	      attrs->reserved);
+      wrsize = sizeof (struct mach_o_header_64);
+    }
+
+  return simple_object_internal_write (descriptor, 0, hdrbuf, wrsize,
+				       errmsg, err);
+}
+
+/* Write a Mach-O section header.  */
+
+static int
+simple_object_mach_o_write_section_header (simple_object_write *sobj,
+					   int descriptor,
+					   size_t sechdr_offset,
+					   const char *name, size_t secaddr,
+					   size_t secsize, size_t offset,
+					   unsigned int align,
+					   const char **errmsg, int *err)
+{
+  struct simple_object_mach_o_attributes *attrs =
+    (struct simple_object_mach_o_attributes *) sobj->data;
+  void (*set_32) (unsigned char *, unsigned int);
+  unsigned char hdrbuf[sizeof (struct mach_o_section_64)];
+  unsigned char *hdr;
+  size_t sechdrsize;
+
+  set_32 = (attrs->is_big_endian
+	    ? simple_object_set_big_32
+	    : simple_object_set_little_32);
+
+  memset (hdrbuf, 0, sizeof hdrbuf);
+
+  hdr = &hdrbuf[0];
+  if (attrs->magic == MACH_O_MH_MAGIC)
+    {
+      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, sectname),
+	       name, MACH_O_NAME_LEN);
+      strncpy ((char *) hdr + offsetof (struct mach_o_section_32, segname),
+	       sobj->segment_name, MACH_O_NAME_LEN);
+      set_32 (hdr + offsetof (struct mach_o_section_32, addr), secaddr);
+      set_32 (hdr + offsetof (struct mach_o_section_32, size), secsize);
+      set_32 (hdr + offsetof (struct mach_o_section_32, offset), offset);
+      set_32 (hdr + offsetof (struct mach_o_section_32, align), align);
+      /* reloff left as zero.  */
+      /* nreloc left as zero.  */
+      set_32 (hdr + offsetof (struct mach_o_section_32, flags),
+	      MACH_O_S_ATTR_DEBUG);
+      /* reserved1 left as zero.  */
+      /* reserved2 left as zero.  */
+      sechdrsize = sizeof (struct mach_o_section_32);
+    }
+  else
+    {
+#ifdef UNSIGNED_64BIT_TYPE
+      void (*set_64) (unsigned char *, ulong_type);
+
+      set_64 = (attrs->is_big_endian
+		? simple_object_set_big_64
+		: simple_object_set_little_64);
+
+      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, sectname),
+	       name, MACH_O_NAME_LEN);
+      strncpy ((char *) hdr + offsetof (struct mach_o_section_64, segname),
+	       sobj->segment_name, MACH_O_NAME_LEN);
+      set_64 (hdr + offsetof (struct mach_o_section_64, addr), secaddr);
+      set_64 (hdr + offsetof (struct mach_o_section_64, size), secsize);
+      set_32 (hdr + offsetof (struct mach_o_section_64, offset), offset);
+      set_32 (hdr + offsetof (struct mach_o_section_64, align), align);
+      /* reloff left as zero.  */
+      /* nreloc left as zero.  */
+      set_32 (hdr + offsetof (struct mach_o_section_64, flags),
+	      MACH_O_S_ATTR_DEBUG);
+      /* reserved1 left as zero.  */
+      /* reserved2 left as zero.  */
+      /* reserved3 left as zero.  */
+#endif
+      sechdrsize = sizeof (struct mach_o_section_64);
+    }
+
+  return simple_object_internal_write (descriptor, sechdr_offset, hdr,
+				       sechdrsize, errmsg, err);
+}
+
+/* Write out the single segment and the sections of a Mach-O file.  */
+
+static int
+simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
+				    size_t nsects, const char **errmsg,
+				    int *err)
+{
+  struct simple_object_mach_o_attributes *attrs =
+    (struct simple_object_mach_o_attributes *) sobj->data;
+  void (*set_32) (unsigned char *, unsigned int);
+  size_t hdrsize;
+  size_t seghdrsize;
+  size_t sechdrsize;
+  size_t cmdsize;
+  size_t offset;
+  size_t sechdr_offset;
+  size_t secaddr;
+  unsigned int name_offset;
+  simple_object_write_section *section;
+  unsigned char hdrbuf[sizeof (struct mach_o_segment_command_64)];
+  unsigned char *hdr;
+
+  set_32 = (attrs->is_big_endian
+	    ? simple_object_set_big_32
+	    : simple_object_set_little_32);
+
+  /* Write out the sections first.  */
+
+  if (attrs->magic == MACH_O_MH_MAGIC)
+    {
+      hdrsize = sizeof (struct mach_o_header_32);
+      seghdrsize = sizeof (struct mach_o_segment_command_32);
+      sechdrsize = sizeof (struct mach_o_section_32);
+    }
+  else
+    {
+      hdrsize = sizeof (struct mach_o_header_64);
+      seghdrsize = sizeof (struct mach_o_segment_command_64);
+      sechdrsize = sizeof (struct mach_o_section_64);
+    }
+
+  sechdr_offset = hdrsize + seghdrsize;
+  cmdsize = seghdrsize + nsects * sechdrsize;
+  offset = hdrsize + cmdsize;
+  name_offset = 0;
+  secaddr = 0;
+
+  for (section = sobj->sections; section != NULL; section = section->next)
+    {
+      size_t mask;
+      size_t new_offset;
+      size_t secsize;
+      struct simple_object_write_section_buffer *buffer;
+      char namebuf[MACH_O_NAME_LEN + 1];
+
+      mask = (1U << section->align) - 1;
+      new_offset = offset + mask;
+      new_offset &= ~ mask;
+      while (new_offset > offset)
+	{
+	  unsigned char zeroes[16];
+	  size_t write;
+
+	  memset (zeroes, 0, sizeof zeroes);
+	  write = new_offset - offset;
+	  if (write > sizeof zeroes)
+	    write = sizeof zeroes;
+	  if (!simple_object_internal_write (descriptor, offset, zeroes, write,
+					     errmsg, err))
+	    return 0;
+	  offset += write;
+	}
+
+      secsize = 0;
+      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
+	{
+	  if (!simple_object_internal_write (descriptor, offset + secsize,
+					     ((const unsigned char *)
+					      buffer->buffer),
+					     buffer->size, errmsg, err))
+	    return 0;
+	  secsize += buffer->size;
+	}
+
+      snprintf (namebuf, sizeof namebuf, "__%08X", name_offset);
+      if (!simple_object_mach_o_write_section_header (sobj, descriptor,
+						      sechdr_offset, namebuf,
+						      secaddr, secsize, offset,
+						      section->align,
+						      errmsg, err))
+	return 0;
+
+      sechdr_offset += sechdrsize;
+      offset += secsize;
+      name_offset += strlen (section->name) + 1;
+      secaddr += secsize;
+    }
+
+  /* Write out the section names.  */
+
+  if (!simple_object_mach_o_write_section_header (sobj, descriptor,
+						  sechdr_offset,
+						  GNU_SECTION_NAMES, secaddr,
+						  name_offset, offset, 0,
+						  errmsg, err))
+    return 0;
+
+  for (section = sobj->sections; section != NULL; section = section->next)
+    {
+      size_t namelen;
+
+      namelen = strlen (section->name) + 1;
+      if (!simple_object_internal_write (descriptor, offset,
+					 (const unsigned char *) section->name,
+					 namelen, errmsg, err))
+	return 0;
+      offset += namelen;
+    }
+
+  /* Write out the segment header.  */
+
+  memset (hdrbuf, 0, sizeof hdrbuf);
+
+  hdr = &hdrbuf[0];
+  if (attrs->magic == MACH_O_MH_MAGIC)
+    {
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd),
+	      MACH_O_LC_SEGMENT);
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
+	      cmdsize);
+      strncpy (((char *) hdr
+		+ offsetof (struct mach_o_segment_command_32, segname)),
+	       sobj->segment_name, MACH_O_NAME_LEN);
+      /* vmaddr left as zero.  */
+      /* vmsize left as zero.  */
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
+	      hdrsize + cmdsize);
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, filesize),
+	      offset - (hdrsize + cmdsize));
+      /* maxprot left as zero.  */
+      /* initprot left as zero.  */
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
+	      nsects);
+      /* flags left as zero.  */
+    }
+  else
+    {
+#ifdef UNSIGNED_64BIT_TYPE
+      void (*set_64) (unsigned char *, ulong_type);
+
+      set_64 = (attrs->is_big_endian
+		? simple_object_set_big_64
+		: simple_object_set_little_64);
+
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmd),
+	      MACH_O_LC_SEGMENT);
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
+	      cmdsize);
+      strncpy (((char *) hdr
+		+ offsetof (struct mach_o_segment_command_32, segname)),
+	       sobj->segment_name, MACH_O_NAME_LEN);
+      /* vmaddr left as zero.  */
+      /* vmsize left as zero.  */
+      set_64 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
+	      hdrsize + cmdsize);
+      set_64 (hdr + offsetof (struct mach_o_segment_command_32, filesize),
+	      offset - (hdrsize + cmdsize));
+      /* maxprot left as zero.  */
+      /* initprot left as zero.  */
+      set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
+	      nsects);
+      /* flags left as zero.  */
+#endif
+    }
+
+  return simple_object_internal_write (descriptor, hdrsize, hdr, seghdrsize,
+				       errmsg, err);
+}
+
+/* Write out a complete Mach-O file.  */
+
+static const char *
+simple_object_mach_o_write_to_file (simple_object_write *sobj, int descriptor,
+				    int *err)
+{
+  size_t nsects;
+  simple_object_write_section *section;
+  const char *errmsg;
+
+  /* Start at 1 for symbol_names section.  */
+  nsects = 1;
+  for (section = sobj->sections; section != NULL; section = section->next)
+    ++nsects;
+
+  if (!simple_object_mach_o_write_header (sobj, descriptor, nsects,
+					  &errmsg, err))
+    return errmsg;
+
+  if (!simple_object_mach_o_write_segment (sobj, descriptor, nsects,
+					   &errmsg, err))
+    return errmsg;
+
+  return NULL;
+}
+
+/* Release the private data for an simple_object_write structure.  */
+
+static void
+simple_object_mach_o_release_write (void *data)
+{
+  XDELETE (data);
+}
+
+/* The Mach-O functions.  */
+
+const struct simple_object_functions simple_object_mach_o_functions =
+{
+  simple_object_mach_o_match,
+  simple_object_mach_o_find_sections,
+  simple_object_mach_o_fetch_attributes,
+  simple_object_mach_o_release_read,
+  simple_object_mach_o_attributes_compare,
+  simple_object_mach_o_release_attributes,
+  simple_object_mach_o_start_write,
+  simple_object_mach_o_write_to_file,
+  simple_object_mach_o_release_write
+};
Index: libiberty/simple-object-coff.c
===================================================================
--- libiberty/simple-object-coff.c	(revision 0)
+++ libiberty/simple-object-coff.c	(revision 0)
@@ -0,0 +1,804 @@
+/* simple-object-coff.c -- routines to manipulate COFF object files.
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+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, 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, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "libiberty.h"
+#include "simple-object.h"
+
+#include <errno.h>
+#include <stddef.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "simple-object-common.h"
+
+/* COFF structures and constants.  */
+
+/* COFF file header.  */
+
+struct external_filehdr
+{
+  unsigned char f_magic[2];	/* magic number			*/
+  unsigned char f_nscns[2];	/* number of sections		*/
+  unsigned char f_timdat[4];	/* time & date stamp		*/
+  unsigned char f_symptr[4];	/* file pointer to symtab	*/
+  unsigned char f_nsyms[4];	/* number of symtab entries	*/
+  unsigned char f_opthdr[2];	/* sizeof(optional hdr)		*/
+  unsigned char f_flags[2];	/* flags			*/
+};
+
+/* Bits for filehdr f_flags field.  */
+
+#define F_EXEC			(0x0002)
+#define IMAGE_FILE_SYSTEM	(0x1000)
+#define IMAGE_FILE_DLL		(0x2000)
+
+/* COFF section header.  */
+
+struct external_scnhdr
+{
+  unsigned char s_name[8];	/* section name				*/
+  unsigned char s_paddr[4];	/* physical address, aliased s_nlib 	*/
+  unsigned char s_vaddr[4];	/* virtual address			*/
+  unsigned char s_size[4];	/* section size				*/
+  unsigned char s_scnptr[4];	/* file ptr to raw data for section 	*/
+  unsigned char s_relptr[4];	/* file ptr to relocation		*/
+  unsigned char s_lnnoptr[4];	/* file ptr to line numbers		*/
+  unsigned char s_nreloc[2];	/* number of relocation entries		*/
+  unsigned char s_nlnno[2];	/* number of line number entries	*/
+  unsigned char s_flags[4];	/* flags				*/
+};
+
+/* The length of the s_name field in struct external_scnhdr.  */
+
+#define SCNNMLEN (8)
+
+/* Bits for scnhdr s_flags field.  This includes some bits defined
+   only for PE.  This may need to be moved into coff_magic.  */
+
+#define STYP_DATA			(1 << 6)
+#define IMAGE_SCN_MEM_DISCARDABLE	(1 << 25)
+#define IMAGE_SCN_MEM_SHARED		(1 << 28)
+#define IMAGE_SCN_MEM_READ		(1 << 30)
+
+#define IMAGE_SCN_ALIGN_POWER_BIT_POS	     20
+#define IMAGE_SCN_ALIGN_POWER_CONST(val)     \
+  (((val) + 1) << IMAGE_SCN_ALIGN_POWER_BIT_POS)
+
+/* COFF symbol table entry.  */
+
+#define E_SYMNMLEN	8	/* # characters in a symbol name	*/
+
+struct external_syment
+{
+  union
+  {
+    unsigned char e_name[E_SYMNMLEN];
+
+    struct
+    {
+      unsigned char e_zeroes[4];
+      unsigned char e_offset[4];
+    } e;
+  } e;
+
+  unsigned char e_value[4];
+  unsigned char e_scnum[2];
+  unsigned char e_type[2];
+  unsigned char e_sclass[1];
+  unsigned char e_numaux[1];
+};
+
+/* Length allowed for filename in aux sym format 4.  */
+
+#define E_FILNMLEN	18
+
+/* Omits x_sym and other unused variants.  */
+
+union external_auxent
+{
+  /* Aux sym format 4: file.  */
+  union
+  {
+    char x_fname[E_FILNMLEN];
+    struct
+    {
+      unsigned char x_zeroes[4];
+      unsigned char x_offset[4];
+    } x_n;
+  } x_file;
+  /* Aux sym format 5: section.  */
+  struct
+  {
+    unsigned char x_scnlen[4];		/* section length		*/
+    unsigned char x_nreloc[2];		/* # relocation entries		*/
+    unsigned char x_nlinno[2];		/* # line numbers		*/
+    unsigned char x_checksum[4];	/* section COMDAT checksum	*/
+    unsigned char x_associated[2];	/* COMDAT assoc section index	*/
+    unsigned char x_comdat[1];		/* COMDAT selection number	*/
+  } x_scn;
+};
+
+/* Symbol-related constants.  */
+
+#define IMAGE_SYM_DEBUG		(-2)
+#define IMAGE_SYM_TYPE_NULL	(0)
+#define IMAGE_SYM_DTYPE_NULL	(0)
+#define IMAGE_SYM_CLASS_STATIC	(3)
+#define IMAGE_SYM_CLASS_FILE	(103)
+
+#define IMAGE_SYM_TYPE \
+  ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL)
+
+/* Private data for an simple_object_read.  */
+
+struct simple_object_coff_read
+{
+  /* Magic number.  */
+  unsigned short magic;
+  /* Whether the file is big-endian.  */
+  unsigned char is_big_endian;
+  /* Number of sections.  */
+  unsigned short nscns;
+  /* File offset of symbol table.  */
+  off_t symptr;
+  /* Number of symbol table entries.  */
+  unsigned int nsyms;
+  /* Flags.  */
+  unsigned short flags;
+  /* Offset of section headers in file.  */
+  off_t scnhdr_offset;
+};
+
+/* Private data for an simple_object_attributes.  */
+
+struct simple_object_coff_attributes
+{
+  /* Magic number.  */
+  unsigned short magic;
+  /* Whether the file is big-endian.  */
+  unsigned char is_big_endian;
+  /* Flags.  */
+  unsigned short flags;
+};
+
+/* There is no magic number which indicates a COFF file as opposed to
+   any other sort of file.  Instead, each COFF file starts with a
+   two-byte magic number which also indicates the type of the target.
+   This struct holds a magic number as well as characteristics of that
+   COFF format.  */
+
+struct coff_magic_struct
+{
+  /* Magic number.  */
+  unsigned short magic;
+  /* Whether this magic number is for a big-endian file.  */
+  unsigned char is_big_endian;
+  /* Flag bits, in the f_flags fields, which indicates that this file
+     is not a relocatable object file.  There is no flag which
+     specifically indicates a relocatable object file, it is only
+     implied by the absence of these flags.  */
+  unsigned short non_object_flags;
+};
+
+/* This is a list of the COFF magic numbers which we recognize, namely
+   the ones used on Windows.  More can be added as needed.  */
+
+static const struct coff_magic_struct coff_magic[] =
+{
+  /* i386.  */
+  { 0x14c, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL },
+  /* x86_64.  */
+  { 0x8664, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL }
+};
+
+/* See if we have a COFF file.  */
+
+static void *
+simple_object_coff_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
+			  int descriptor, off_t offset,
+			  const char *segment_name ATTRIBUTE_UNUSED,
+			  const char **errmsg, int *err)
+{
+  size_t c;
+  unsigned short magic_big;
+  unsigned short magic_little;
+  unsigned short magic;
+  size_t i;
+  int is_big_endian;
+  unsigned short (*fetch_16) (const unsigned char *);
+  unsigned int (*fetch_32) (const unsigned char *);
+  unsigned char hdrbuf[sizeof (struct external_filehdr)];
+  unsigned short flags;
+  struct simple_object_coff_read *ocr;
+
+  c = sizeof (coff_magic) / sizeof (coff_magic[0]);
+  magic_big = simple_object_fetch_big_16 (header);
+  magic_little = simple_object_fetch_little_16 (header);
+  for (i = 0; i < c; ++i)
+    {
+      if (coff_magic[i].is_big_endian
+	  ? coff_magic[i].magic == magic_big
+	  : coff_magic[i].magic == magic_little)
+	break;
+    }
+  if (i >= c)
+    {
+      *errmsg = NULL;
+      *err = 0;
+      return NULL;
+    }
+  is_big_endian = coff_magic[i].is_big_endian;
+
+  magic = is_big_endian ? magic_big : magic_little;
+  fetch_16 = (is_big_endian
+	      ? simple_object_fetch_big_16
+	      : simple_object_fetch_little_16);
+  fetch_32 = (is_big_endian
+	      ? simple_object_fetch_big_32
+	      : simple_object_fetch_little_32);
+
+  if (!simple_object_internal_read (descriptor, offset, hdrbuf, sizeof hdrbuf,
+				    errmsg, err))
+    return NULL;
+
+  flags = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_flags));
+  if ((flags & coff_magic[i].non_object_flags) != 0)
+    {
+      *errmsg = "not relocatable object file";
+      *err = 0;
+      return NULL;
+    }
+
+  ocr = XNEW (struct simple_object_coff_read);
+  ocr->magic = magic;
+  ocr->is_big_endian = is_big_endian;
+  ocr->nscns = fetch_16 (hdrbuf + offsetof (struct external_filehdr, f_nscns));
+  ocr->symptr = fetch_32 (hdrbuf
+			  + offsetof (struct external_filehdr, f_symptr));
+  ocr->nsyms = fetch_32 (hdrbuf + offsetof (struct external_filehdr, f_nsyms));
+  ocr->flags = flags;
+  ocr->scnhdr_offset = (sizeof (struct external_filehdr)
+			+ fetch_16 (hdrbuf + offsetof (struct external_filehdr,
+						       f_opthdr)));
+
+  return (void *) ocr;
+}
+
+/* Read the string table in a COFF file.  */
+
+static char *
+simple_object_coff_read_strtab (simple_object_read *sobj, size_t *strtab_size,
+				const char **errmsg, int *err)
+{
+  struct simple_object_coff_read *ocr =
+    (struct simple_object_coff_read *) sobj->data;
+  off_t strtab_offset;
+  unsigned char strsizebuf[4];
+  size_t strsize;
+  char *strtab;
+
+  strtab_offset = ocr->symptr + ocr->nsyms * sizeof (struct external_syment);
+  if (!simple_object_internal_read (sobj->descriptor, strtab_offset,
+				    strsizebuf, 4, errmsg, err))
+    return NULL;
+  strsize = (ocr->is_big_endian
+	     ? simple_object_fetch_big_32 (strsizebuf)
+	     : simple_object_fetch_little_32 (strsizebuf));
+  strtab = XNEWVEC (char, strsize);
+  if (!simple_object_internal_read (sobj->descriptor, strtab_offset,
+				    (unsigned char *) strtab, strsize, errmsg,
+				    err))
+    {
+      XDELETEVEC (strtab);
+      return NULL;
+    }
+  *strtab_size = strsize;
+  return strtab;
+}
+
+/* Find all sections in a COFF file.  */
+
+static const char *
+simple_object_coff_find_sections (simple_object_read *sobj,
+				  int (*pfn) (void *, const char *,
+					      off_t offset, off_t length),
+				  void *data,
+				  int *err)
+{
+  struct simple_object_coff_read *ocr =
+    (struct simple_object_coff_read *) sobj->data;
+  size_t scnhdr_size;
+  unsigned char *scnbuf;
+  const char *errmsg;
+  unsigned int (*fetch_32) (const unsigned char *);
+  unsigned int nscns;
+  char *strtab;
+  size_t strtab_size;
+  unsigned int i;
+
+  scnhdr_size = sizeof (struct external_scnhdr);
+  scnbuf = XNEWVEC (unsigned char, scnhdr_size * ocr->nscns);
+  if (!simple_object_internal_read (sobj->descriptor,
+				    sobj->offset + ocr->scnhdr_offset,
+				    scnbuf, scnhdr_size * ocr->nscns, &errmsg,
+				    err))
+    {
+      XDELETEVEC (scnbuf);
+      return errmsg;
+    }
+
+  fetch_32 = (ocr->is_big_endian
+	      ? simple_object_fetch_big_32
+	      : simple_object_fetch_little_32);
+
+  nscns = ocr->nscns;
+  strtab = NULL;
+  strtab_size = 0;
+  for (i = 0; i < nscns; ++i)
+    {
+      unsigned char *scnhdr;
+      unsigned char *scnname;
+      char namebuf[SCNNMLEN + 1];
+      char *name;
+      off_t scnptr;
+      unsigned int size;
+
+      scnhdr = scnbuf + i * scnhdr_size;
+      scnname = scnhdr + offsetof (struct external_scnhdr, s_name);
+      memcpy (namebuf, scnname, SCNNMLEN);
+      namebuf[SCNNMLEN] = '\0';
+      name = &namebuf[0];
+      if (namebuf[0] == '/')
+	{
+	  size_t strindex;
+	  char *end;
+
+	  strindex = strtol (namebuf + 1, &end, 10);
+	  if (*end == '\0')
+	    {
+	      /* The real section name is found in the string
+		 table.  */
+	      if (strtab == NULL)
+		{
+		  strtab = simple_object_coff_read_strtab (sobj,
+							   &strtab_size,
+							   &errmsg, err);
+		  if (strtab == NULL)
+		    {
+		      XDELETEVEC (scnbuf);
+		      return errmsg;
+		    }
+		}
+
+	      if (strindex < 4 || strindex >= strtab_size)
+		{
+		  XDELETEVEC (strtab);
+		  XDELETEVEC (scnbuf);
+		  *err = 0;
+		  return "section string index out of range";
+		}
+
+	      name = strtab + strindex;
+	    }
+	}
+
+      scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr, s_scnptr));
+      size = fetch_32 (scnhdr + offsetof (struct external_scnhdr, s_size));
+
+      if (!(*pfn) (data, name, scnptr, size))
+	break;
+    }
+
+  if (strtab != NULL)
+    XDELETEVEC (strtab);
+  XDELETEVEC (scnbuf);
+
+  return NULL;
+}
+
+/* Fetch the attributes for an simple_object_read.  */
+
+static void *
+simple_object_coff_fetch_attributes (simple_object_read *sobj,
+				     const char **errmsg ATTRIBUTE_UNUSED,
+				     int *err ATTRIBUTE_UNUSED)
+{
+  struct simple_object_coff_read *ocr =
+    (struct simple_object_coff_read *) sobj->data;
+  struct simple_object_coff_attributes *ret;
+
+  ret = XNEW (struct simple_object_coff_attributes);
+  ret->magic = ocr->magic;
+  ret->is_big_endian = ocr->is_big_endian;
+  ret->flags = ocr->flags;
+  return ret;
+}
+
+/* Release the private data for an simple_object_read.  */
+
+static void
+simple_object_coff_release_read (void *data)
+{
+  XDELETE (data);
+}
+
+/* Compare two attributes structures.  */
+
+static const char *
+simple_object_coff_attributes_compare (void *data1, void *data2, int *err)
+{
+  struct simple_object_coff_attributes *attrs1 =
+    (struct simple_object_coff_attributes *) data1;
+  struct simple_object_coff_attributes *attrs2 =
+    (struct simple_object_coff_attributes *) data2;
+
+  if (attrs1->magic != attrs2->magic
+      || attrs1->is_big_endian != attrs2->is_big_endian)
+    {
+      *err = 0;
+      return "COFF object format mismatch";
+    }
+  return NULL;
+}
+
+/* Release the private data for an attributes structure.  */
+
+static void
+simple_object_coff_release_attributes (void *data)
+{
+  XDELETE (data);
+}
+
+/* Prepare to write out a file.  */
+
+static void *
+simple_object_coff_start_write (void *attributes_data,
+				const char **errmsg ATTRIBUTE_UNUSED,
+				int *err ATTRIBUTE_UNUSED)
+{
+  struct simple_object_coff_attributes *attrs =
+    (struct simple_object_coff_attributes *) attributes_data;
+  struct simple_object_coff_attributes *ret;
+
+  /* We're just going to record the attributes, but we need to make a
+     copy because the user may delete them.  */
+  ret = XNEW (struct simple_object_coff_attributes);
+  *ret = *attrs;
+  return ret;
+}
+
+/* Write out a COFF filehdr.  */
+
+static int
+simple_object_coff_write_filehdr (simple_object_write *sobj, int descriptor,
+				  unsigned int nscns, size_t symtab_offset,
+				  unsigned int nsyms, const char **errmsg,
+				  int *err)
+{
+  struct simple_object_coff_attributes *attrs =
+    (struct simple_object_coff_attributes *) sobj->data;
+  unsigned char hdrbuf[sizeof (struct external_filehdr)];
+  unsigned char *hdr;
+  void (*set_16) (unsigned char *, unsigned short);
+  void (*set_32) (unsigned char *, unsigned int);
+
+  hdr = &hdrbuf[0];
+
+  set_16 = (attrs->is_big_endian
+	    ? simple_object_set_big_16
+	    : simple_object_set_little_16);
+  set_32 = (attrs->is_big_endian
+	    ? simple_object_set_big_32
+	    : simple_object_set_little_32);
+
+  memset (hdr, 0, sizeof (struct external_filehdr));
+
+  set_16 (hdr + offsetof (struct external_filehdr, f_magic), attrs->magic);
+  set_16 (hdr + offsetof (struct external_filehdr, f_nscns), nscns);
+  /* f_timdat left as zero.  */
+  set_32 (hdr + offsetof (struct external_filehdr, f_symptr), symtab_offset);
+  set_32 (hdr + offsetof (struct external_filehdr, f_nsyms), nsyms);
+  /* f_opthdr left as zero.  */
+  set_16 (hdr + offsetof (struct external_filehdr, f_flags), attrs->flags);
+
+  return simple_object_internal_write (descriptor, 0, hdrbuf,
+				       sizeof (struct external_filehdr),
+				       errmsg, err);
+}
+
+/* Write out a COFF section header.  */
+
+static int
+simple_object_coff_write_scnhdr (simple_object_write *sobj, int descriptor,
+				 const char *name, size_t *name_offset,
+				 off_t scnhdr_offset, size_t scnsize,
+				 off_t offset, unsigned int align,
+				 const char **errmsg, int *err)
+{
+  struct simple_object_coff_attributes *attrs =
+    (struct simple_object_coff_attributes *) sobj->data;
+  void (*set_32) (unsigned char *, unsigned int);
+  unsigned char hdrbuf[sizeof (struct external_scnhdr)];
+  unsigned char *hdr;
+  size_t namelen;
+  unsigned int flags;
+
+  set_32 = (attrs->is_big_endian
+	    ? simple_object_set_big_32
+	    : simple_object_set_little_32);
+
+  memset (hdrbuf, 0, sizeof hdrbuf);
+  hdr = &hdrbuf[0];
+
+  namelen = strlen (name);
+  if (namelen <= SCNNMLEN)
+    strncpy ((char *) hdr + offsetof (struct external_scnhdr, s_name), name,
+	     SCNNMLEN);
+  else
+    {
+      snprintf ((char *) hdr + offsetof (struct external_scnhdr, s_name),
+		SCNNMLEN, "/%lu", (unsigned long) *name_offset);
+      *name_offset += namelen + 1;
+    }
+
+  /* s_paddr left as zero.  */
+  /* s_vaddr left as zero.  */
+  set_32 (hdr + offsetof (struct external_scnhdr, s_size), scnsize);
+  set_32 (hdr + offsetof (struct external_scnhdr, s_scnptr), offset);
+  /* s_relptr left as zero.  */
+  /* s_lnnoptr left as zero.  */
+  /* s_nreloc left as zero.  */
+  /* s_nlnno left as zero.  */
+  flags = (STYP_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_SHARED
+	   | IMAGE_SCN_MEM_READ);
+  /* PE can represent alignment up to 13.  */
+  if (align > 13)
+    align = 13;
+  flags |= IMAGE_SCN_ALIGN_POWER_CONST(align);
+  set_32 (hdr + offsetof (struct external_scnhdr, s_flags), flags);
+
+  return simple_object_internal_write (descriptor, scnhdr_offset, hdrbuf,
+				       sizeof (struct external_scnhdr),
+				       errmsg, err);
+}
+
+/* Write out a complete COFF file.  */
+
+static const char *
+simple_object_coff_write_to_file (simple_object_write *sobj, int descriptor,
+				  int *err)
+{
+  struct simple_object_coff_attributes *attrs =
+    (struct simple_object_coff_attributes *) sobj->data;
+  unsigned int nscns, secnum;
+  simple_object_write_section *section;
+  off_t scnhdr_offset;
+  size_t symtab_offset;
+  off_t secsym_offset;
+  unsigned int nsyms;
+  size_t offset;
+  size_t name_offset;
+  const char *errmsg;
+  unsigned char strsizebuf[4];
+  /* The interface doesn't give us access to the name of the input file
+     yet.  We want to use its basename for the FILE symbol.  This is
+     what 'gas' uses when told to assemble from stdin.  */
+  const char *source_filename = "fake";
+  size_t sflen;
+  union
+  {
+    struct external_syment sym;
+    union external_auxent aux;
+  } syms[2];
+  void (*set_16) (unsigned char *, unsigned short);
+  void (*set_32) (unsigned char *, unsigned int);
+
+  set_16 = (attrs->is_big_endian
+	    ? simple_object_set_big_16
+	    : simple_object_set_little_16);
+  set_32 = (attrs->is_big_endian
+	    ? simple_object_set_big_32
+	    : simple_object_set_little_32);
+
+  nscns = 0;
+  for (section = sobj->sections; section != NULL; section = section->next)
+    ++nscns;
+
+  scnhdr_offset = sizeof (struct external_filehdr);
+  offset = scnhdr_offset + nscns * sizeof (struct external_scnhdr);
+  name_offset = 4;
+  for (section = sobj->sections; section != NULL; section = section->next)
+    {
+      size_t mask;
+      size_t new_offset;
+      size_t scnsize;
+      struct simple_object_write_section_buffer *buffer;
+
+      mask = (1U << section->align) - 1;
+      new_offset = offset & mask;
+      new_offset &= ~ mask;
+      while (new_offset > offset)
+	{
+	  unsigned char zeroes[16];
+	  size_t write;
+
+	  memset (zeroes, 0, sizeof zeroes);
+	  write = new_offset - offset;
+	  if (write > sizeof zeroes)
+	    write = sizeof zeroes;
+	  if (!simple_object_internal_write (descriptor, offset, zeroes, write,
+					     &errmsg, err))
+	    return errmsg;
+	}
+
+      scnsize = 0;
+      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
+	{
+	  if (!simple_object_internal_write (descriptor, offset + scnsize,
+					     ((const unsigned char *)
+					      buffer->buffer),
+					     buffer->size, &errmsg, err))
+	    return errmsg;
+	  scnsize += buffer->size;
+	}
+
+      if (!simple_object_coff_write_scnhdr (sobj, descriptor, section->name,
+					    &name_offset, scnhdr_offset,
+					    scnsize, offset, section->align,
+					    &errmsg, err))
+	return errmsg;
+
+      scnhdr_offset += sizeof (struct external_scnhdr);
+      offset += scnsize;
+    }
+
+  /* Symbol table is always half-word aligned.  */
+  offset += (offset & 1);
+  /* There is a file symbol and a section symbol per section,
+     and each of these has a single auxiliary symbol following.  */
+  nsyms = 2 * (nscns + 1);
+  symtab_offset = offset;
+  /* Advance across space reserved for symbol table to locate
+     start of string table.  */
+  offset += nsyms * sizeof (struct external_syment);
+
+  /* Write out file symbol.  */
+  memset (&syms[0], 0, sizeof (syms));
+  strcpy ((char *)&syms[0].sym.e.e_name[0], ".file");
+  set_16 (&syms[0].sym.e_scnum[0], IMAGE_SYM_DEBUG);
+  set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
+  syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_FILE;
+  syms[0].sym.e_numaux[0] = 1;
+  /* The name need not be nul-terminated if it fits into the x_fname field
+     directly, but must be if it has to be placed into the string table.  */
+  sflen = strlen (source_filename);
+  if (sflen <= E_FILNMLEN)
+    memcpy (&syms[1].aux.x_file.x_fname[0], source_filename, sflen);
+  else
+    {
+      set_32 (&syms[1].aux.x_file.x_n.x_offset[0], name_offset);
+      if (!simple_object_internal_write (descriptor, offset + name_offset,
+					 ((const unsigned char *)
+					  source_filename),
+					 sflen + 1, &errmsg, err))
+	return errmsg;
+      name_offset += strlen (source_filename) + 1;
+    }
+  if (!simple_object_internal_write (descriptor, symtab_offset,
+				     (const unsigned char *) &syms[0],
+				     sizeof (syms), &errmsg, err))
+    return errmsg;
+
+  /* Write the string table length, followed by the strings and section
+     symbols in step with each other.  */
+  set_32 (strsizebuf, name_offset);
+  if (!simple_object_internal_write (descriptor, offset, strsizebuf, 4,
+				     &errmsg, err))
+    return errmsg;
+
+  name_offset = 4;
+  secsym_offset = symtab_offset + sizeof (syms);
+  memset (&syms[0], 0, sizeof (syms));
+  set_16 (&syms[0].sym.e_type[0], IMAGE_SYM_TYPE);
+  syms[0].sym.e_sclass[0] = IMAGE_SYM_CLASS_STATIC;
+  syms[0].sym.e_numaux[0] = 1;
+  secnum = 1;
+
+  for (section = sobj->sections; section != NULL; section = section->next)
+    {
+      size_t namelen;
+      size_t scnsize;
+      struct simple_object_write_section_buffer *buffer;
+
+      namelen = strlen (section->name);
+      set_16 (&syms[0].sym.e_scnum[0], secnum++);
+      scnsize = 0;
+      for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
+	scnsize += buffer->size;
+      set_32 (&syms[1].aux.x_scn.x_scnlen[0], scnsize);
+      if (namelen > SCNNMLEN)
+	{
+	  set_32 (&syms[0].sym.e.e.e_zeroes[0], 0);
+	  set_32 (&syms[0].sym.e.e.e_offset[0], name_offset);
+	  if (!simple_object_internal_write (descriptor, offset + name_offset,
+					     ((const unsigned char *)
+					      section->name),
+					     namelen + 1, &errmsg, err))
+	    return errmsg;
+	  name_offset += namelen + 1;
+	}
+      else
+	{
+	  memcpy (&syms[0].sym.e.e_name[0], section->name,
+		  strlen (section->name));
+	  memset (&syms[0].sym.e.e_name[strlen (section->name)], 0,
+		  E_SYMNMLEN - strlen (section->name));
+	}
+
+      if (!simple_object_internal_write (descriptor, secsym_offset,
+					 (const unsigned char *) &syms[0],
+					 sizeof (syms), &errmsg, err))
+	return errmsg;
+      secsym_offset += sizeof (syms);
+    }
+
+  if (!simple_object_coff_write_filehdr (sobj, descriptor, nscns,
+					 symtab_offset, nsyms, &errmsg, err))
+    return errmsg;
+
+  return NULL;
+}
+
+/* Release the private data for an simple_object_write structure.  */
+
+static void
+simple_object_coff_release_write (void *data)
+{
+  XDELETE (data);
+}
+
+/* The COFF functions.  */
+
+const struct simple_object_functions simple_object_coff_functions =
+{
+  simple_object_coff_match,
+  simple_object_coff_find_sections,
+  simple_object_coff_fetch_attributes,
+  simple_object_coff_release_read,
+  simple_object_coff_attributes_compare,
+  simple_object_coff_release_attributes,
+  simple_object_coff_start_write,
+  simple_object_coff_write_to_file,
+  simple_object_coff_release_write
+};
Index: libiberty/Makefile.in
===================================================================
--- libiberty/Makefile.in	(revision 166080)
+++ libiberty/Makefile.in	(working copy)
@@ -2,8 +2,8 @@
 # Originally written by K. Richard Pixley <rich@cygnus.com>.
 #
 # Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-# 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
-# Foundation
+# 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+# Free Software Foundation
 #
 # This file is part of the libiberty library.
 # Libiberty is free software; you can redistribute it and/or
@@ -145,6 +145,8 @@ CFILES = alloca.c argv.c asprintf.c atex
          physmem.c putenv.c						\
 	random.c regex.c rename.c rindex.c				\
 	safe-ctype.c setenv.c setproctitle.c sha1.c sigsetmask.c        \
+	 simple-object.c simple-object-coff.c simple-object-elf.c	\
+	 simple-object-mach-o.c						\
          snprintf.c sort.c						\
 	 spaces.c splay-tree.c stpcpy.c stpncpy.c strcasecmp.c		\
 	 strchr.c strdup.c strerror.c strncasecmp.c strncmp.c		\
@@ -172,11 +174,15 @@ REQUIRED_OFILES =							\
 	./getruntime.$(objext) ./hashtab.$(objext) ./hex.$(objext)	\
 	./lbasename.$(objext) ./lrealpath.$(objext)			\
 	./make-relative-prefix.$(objext) ./make-temp-file.$(objext)	\
-	./objalloc.$(objext) ./obstack.$(objext)			\
+	./objalloc.$(objext)						\
+	./obstack.$(objext)						\
 	./partition.$(objext) ./pexecute.$(objext) ./physmem.$(objext)	\
 	./pex-common.$(objext) ./pex-one.$(objext)			\
 	./@pexecute@.$(objext)						\
-	./safe-ctype.$(objext) ./sort.$(objext) ./spaces.$(objext)	\
+	./safe-ctype.$(objext)						\
+	./simple-object.$(objext) ./simple-object-coff.$(objext)	\
+	./simple-object-elf.$(objext) ./simple-object-mach-o.$(objext)	\
+	./sort.$(objext) ./spaces.$(objext)				\
 	./splay-tree.$(objext) ./strerror.$(objext)			\
 	./strsignal.$(objext) ./unlink-if-ordinary.$(objext)		\
 	./xatexit.$(objext) ./xexit.$(objext) ./xmalloc.$(objext)	\
@@ -312,7 +318,7 @@ TEXISRC = \
 # Additional files that have texi snippets that need to be collected
 # and sorted.  Some are here because the sources are imported from
 # elsewhere.  Others represent headers in ../include.
-TEXIFILES = fnmatch.txh pexecute.txh
+TEXIFILES = fnmatch.txh pexecute.txh simple-object.txh
 
 libiberty.info : $(srcdir)/libiberty.texi $(TEXISRC)
 	$(MAKEINFO) -I$(srcdir) $(srcdir)/libiberty.texi
@@ -965,6 +971,38 @@ $(CONFIGURED_OFILES): stamp-picdir
 	else true; fi
 	$(COMPILE.c) $(srcdir)/sigsetmask.c $(OUTPUT_OPTION)
 
+./simple-object-coff.$(objext): $(srcdir)/simple-object-coff.c config.h \
+	$(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
+	$(srcdir)/simple-object-common.h $(INCDIR)/simple-object.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/simple-object-coff.c -o pic/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/simple-object-coff.c $(OUTPUT_OPTION)
+
+./simple-object-elf.$(objext): $(srcdir)/simple-object-elf.c config.h \
+	$(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
+	$(srcdir)/simple-object-common.h $(INCDIR)/simple-object.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/simple-object-elf.c -o pic/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/simple-object-elf.c $(OUTPUT_OPTION)
+
+./simple-object-mach-o.$(objext): $(srcdir)/simple-object-mach-o.c config.h \
+	$(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
+	$(srcdir)/simple-object-common.h $(INCDIR)/simple-object.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/simple-object-mach-o.c -o pic/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/simple-object-mach-o.c $(OUTPUT_OPTION)
+
+./simple-object.$(objext): $(srcdir)/simple-object.c config.h \
+	$(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
+	$(srcdir)/simple-object-common.h $(INCDIR)/simple-object.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/simple-object.c -o pic/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/simple-object.c $(OUTPUT_OPTION)
+
 ./snprintf.$(objext): $(srcdir)/snprintf.c $(INCDIR)/ansidecl.h
 	if [ x"$(PICFLAG)" != x ]; then \
 	  $(COMPILE.c) $(PICFLAG) $(srcdir)/snprintf.c -o pic/$@; \
Index: libiberty/simple-object-common.h
===================================================================
--- libiberty/simple-object-common.h	(revision 0)
+++ libiberty/simple-object-common.h	(revision 0)
@@ -0,0 +1,354 @@
+/* simple-object-common.h -- common structs for object file manipulation.
+   Copyright (C) 2010 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If not,
+write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+/* Forward reference.  */
+struct simple_object_functions;
+
+/* An object file opened for reading.  */
+
+struct simple_object_read_struct
+{
+  /* The file descriptor.  */
+  int descriptor;
+  /* The offset within the file.  */
+  off_t offset;
+  /* The functions which do the actual work.  */
+  const struct simple_object_functions *functions;
+  /* Private data for the object file format.  */
+  void *data;
+};
+
+/* Object file attributes.  */
+
+struct simple_object_attributes_struct
+{
+  /* The functions which do the actual work.  */
+  const struct simple_object_functions *functions;
+  /* Private data for the object file format.  */
+  void *data;
+};
+
+/* An object file being created.  */
+
+struct simple_object_write_struct
+{
+  /* The functions which do the actual work.  */
+  const struct simple_object_functions *functions;
+  /* The segment_name argument from the user.  */
+  char *segment_name;
+  /* The start of the list of sections.  */
+  simple_object_write_section *sections;
+  /* The last entry in the list of sections.  */
+  simple_object_write_section *last_section;
+  /* Private data for the object file format.  */
+  void *data;
+};
+
+/* A section in an object file being created.  */
+
+struct simple_object_write_section_struct
+{
+  /* Next in the list of sections attached to an
+     simple_object_write.  */
+  simple_object_write_section *next;
+  /* The name of this section.  */
+  char *name;
+  /* The required alignment.  */
+  unsigned int align;
+  /* The first data attached to this section.  */
+  struct simple_object_write_section_buffer *buffers;
+  /* The last data attached to this section.  */
+  struct simple_object_write_section_buffer *last_buffer;
+};
+
+/* Data attached to a section.  */
+
+struct simple_object_write_section_buffer
+{
+  /* The next data for this section.  */
+  struct simple_object_write_section_buffer *next;
+  /* The size of the buffer.  */
+  size_t size;
+  /* The actual bytes.  */
+  const void *buffer;
+  /* A buffer to free, or NULL.  */
+  void *free_buffer;
+};
+
+/* The number of bytes we read from the start of the file to pass to
+   the match function.  */
+#define SIMPLE_OBJECT_MATCH_HEADER_LEN (16)
+
+/* Format-specific object file functions.  */
+
+struct simple_object_functions
+{
+  /* If this file matches these functions, return a new value for the
+     private data for an simple_object_read.  HEADER is the first 16
+     bytes of the file.  DESCRIPTOR, OFFSET, SEGMENT_NAME, ERRMSG, and
+     ERR are as for simple_object_open_read.  If this file does not
+     match, this function should return NULL with *ERRMSG set to
+     NULL.  */
+  void *(*match) (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
+		  int descriptor, off_t offset, const char *segment_name,
+		  const char **errmsg, int *err);
+
+  /* Implement simple_object_find_sections.  */
+  const char *(*find_sections) (simple_object_read *,
+				int (*pfn) (void *, const char *,
+					    off_t offset, off_t length),
+				void *data,
+				int *err);
+
+  /* Return the private data for the attributes for SOBJ.  */
+  void *(*fetch_attributes) (simple_object_read *sobj, const char **errmsg,
+			     int *err);
+
+  /* Release the private data for an simple_object_read.  */
+  void (*release_read) (void *);
+
+  /* Compare the private data for the attributes of two files.  If
+     they are the same, in the sense that they could be linked
+     together, return NULL.  Otherwise return an error message.  */
+  const char *(*attributes_compare) (void *, void *, int *err);
+
+  /* Release the private data for an simple_object_attributes.  */
+  void (*release_attributes) (void *);
+
+  /* Start creating an object file.  */
+  void *(*start_write) (void *attributes_data, const char **errmsg,
+			int *err);
+
+  /* Write the complete object file.  */
+  const char *(*write_to_file) (simple_object_write *sobj, int descriptor,
+				int *err);
+
+  /* Release the private data for an simple_object_write.  */
+  void (*release_write) (void *);
+};
+
+/* The known object file formats.  */
+
+extern const struct simple_object_functions simple_object_coff_functions;
+extern const struct simple_object_functions simple_object_elf_functions;
+extern const struct simple_object_functions simple_object_mach_o_functions;
+
+/* Read SIZE bytes from DESCRIPTOR at file offset OFFSET into BUFFER.
+   Return non-zero on success.  On failure return 0 and set *ERRMSG
+   and *ERR.  */
+
+extern int
+simple_object_internal_read (int descriptor, off_t offset,
+			     unsigned char *buffer, size_t size,
+			     const char **errmsg, int *err);
+
+/* Write SIZE bytes from BUFFER to DESCRIPTOR at file offset OFFSET.
+   Return non-zero on success.  On failure return 0 and set *ERRMSG
+   and *ERR.  */
+
+extern int
+simple_object_internal_write (int descriptor, off_t offset,
+			      const unsigned char *buffer, size_t size,
+			      const char **errmsg, int *err);
+
+/* Define ulong_type as an unsigned 64-bit type if available.
+   Otherwise just make it unsigned long.  */
+
+#ifdef UNSIGNED_64BIT_TYPE
+__extension__ typedef UNSIGNED_64BIT_TYPE ulong_type;
+#else
+typedef unsigned long ulong_type;
+#endif
+
+/* Fetch a big-endian 16-bit value.  */
+
+static inline unsigned short
+simple_object_fetch_big_16 (const unsigned char *buf)
+{
+  return ((unsigned short) buf[0] << 8) | (unsigned short) buf[1];
+}
+
+/* Fetch a little-endian 16-bit value.  */
+
+static inline unsigned short
+simple_object_fetch_little_16 (const unsigned char *buf)
+{
+  return ((unsigned short) buf[1] << 8) | (unsigned short) buf[0];
+}
+
+/* Fetch a big-endian 32-bit value.  */
+
+static inline unsigned int
+simple_object_fetch_big_32 (const unsigned char *buf)
+{
+  return (((unsigned int) buf[0] << 24)
+	  | ((unsigned int) buf[1] << 16)
+	  | ((unsigned int) buf[2] << 8)
+	  | (unsigned int) buf[3]);
+}
+
+/* Fetch a little-endian 32-bit value.  */
+
+static inline unsigned int
+simple_object_fetch_little_32 (const unsigned char *buf)
+{
+  return (((unsigned int) buf[3] << 24)
+	  | ((unsigned int) buf[2] << 16)
+	  | ((unsigned int) buf[1] << 8)
+	  | (unsigned int) buf[0]);
+}
+
+/* Fetch a big-endian 32-bit value as a ulong_type.  */
+
+static inline ulong_type
+simple_object_fetch_big_32_ulong (const unsigned char *buf)
+{
+  return (ulong_type) simple_object_fetch_big_32 (buf);
+}
+
+/* Fetch a little-endian 32-bit value as a ulong_type.  */
+
+static inline ulong_type
+simple_object_fetch_little_32_ulong (const unsigned char *buf)
+{
+  return (ulong_type) simple_object_fetch_little_32 (buf);
+}
+
+#ifdef UNSIGNED_64BIT_TYPE
+
+/* Fetch a big-endian 64-bit value.  */
+
+static inline ulong_type
+simple_object_fetch_big_64 (const unsigned char *buf)
+{
+  return (((ulong_type) buf[0] << 56)
+	  | ((ulong_type) buf[1] << 48)
+	  | ((ulong_type) buf[2] << 40)
+	  | ((ulong_type) buf[3] << 32)
+	  | ((ulong_type) buf[4] << 24)
+	  | ((ulong_type) buf[5] << 16)
+	  | ((ulong_type) buf[6] << 8)
+	  | (ulong_type) buf[7]);
+}
+
+/* Fetch a little-endian 64-bit value.  */
+
+static inline ulong_type
+simple_object_fetch_little_64 (const unsigned char *buf)
+{
+  return (((ulong_type) buf[7] << 56)
+	  | ((ulong_type) buf[6] << 48)
+	  | ((ulong_type) buf[5] << 40)
+	  | ((ulong_type) buf[4] << 32)
+	  | ((ulong_type) buf[3] << 24)
+	  | ((ulong_type) buf[2] << 16)
+	  | ((ulong_type) buf[1] << 8)
+	  | (ulong_type) buf[0]);
+}
+
+#endif
+
+/* Store a big-endian 16-bit value.  */
+
+static inline void
+simple_object_set_big_16 (unsigned char *buf, unsigned short val)
+{
+  buf[0] = (val >> 8) & 0xff;
+  buf[1] = val & 0xff;
+}
+
+/* Store a little-endian 16-bit value.  */
+
+static inline void
+simple_object_set_little_16 (unsigned char *buf, unsigned short val)
+{
+  buf[1] = (val >> 8) & 0xff;
+  buf[0] = val & 0xff;
+}
+
+/* Store a big-endian 32-bit value.  */
+
+static inline void
+simple_object_set_big_32 (unsigned char *buf, unsigned int val)
+{
+  buf[0] = (val >> 24) & 0xff;
+  buf[1] = (val >> 16) & 0xff;
+  buf[2] = (val >> 8) & 0xff;
+  buf[3] = val & 0xff;
+}
+
+/* Store a little-endian 32-bit value.  */
+
+static inline void
+simple_object_set_little_32 (unsigned char *buf, unsigned int val)
+{
+  buf[3] = (val >> 24) & 0xff;
+  buf[2] = (val >> 16) & 0xff;
+  buf[1] = (val >> 8) & 0xff;
+  buf[0] = val & 0xff;
+}
+
+/* Store a big-endian 32-bit value coming in as a ulong_type.  */
+
+static inline void
+simple_object_set_big_32_ulong (unsigned char *buf, ulong_type val)
+{
+  simple_object_set_big_32 (buf, val);
+}
+
+/* Store a little-endian 32-bit value coming in as a ulong_type.  */
+
+static inline void
+simple_object_set_little_32_ulong (unsigned char *buf, ulong_type val)
+{
+  simple_object_set_little_32 (buf, val);
+}
+
+#ifdef UNSIGNED_64BIT_TYPE
+
+/* Store a big-endian 64-bit value.  */
+
+static inline void
+simple_object_set_big_64 (unsigned char *buf, ulong_type val)
+{
+  buf[0] = (val >> 56) & 0xff;
+  buf[1] = (val >> 48) & 0xff;
+  buf[2] = (val >> 40) & 0xff;
+  buf[3] = (val >> 32) & 0xff;
+  buf[4] = (val >> 24) & 0xff;
+  buf[5] = (val >> 16) & 0xff;
+  buf[6] = (val >> 8) & 0xff;
+  buf[7] = val & 0xff;
+}
+
+/* Store a little-endian 64-bit value.  */
+
+static inline void
+simple_object_set_little_64 (unsigned char *buf, ulong_type val)
+{
+  buf[7] = (val >> 56) & 0xff;
+  buf[6] = (val >> 48) & 0xff;
+  buf[5] = (val >> 40) & 0xff;
+  buf[4] = (val >> 32) & 0xff;
+  buf[3] = (val >> 24) & 0xff;
+  buf[2] = (val >> 16) & 0xff;
+  buf[1] = (val >> 8) & 0xff;
+  buf[0] = val & 0xff;
+}
+
Index: libiberty/simple-object.txh
===================================================================
--- libiberty/simple-object.txh	(revision 0)
+++ libiberty/simple-object.txh	(revision 0)
@@ -0,0 +1,168 @@
+@c -*- mode: texinfo -*-
+@deftypefn Extension {simple_object_read *} simple_object_open_read (int @var{descriptor}, off_t @var{offset}, const char *{segment_name}, const char **@var{errmsg}, int *@var{err})
+
+Opens an object file for reading.  Creates and returns an
+@code{simple_object_read} pointer which may be passed to other
+functions to extract data from the object file.
+
+@var{descriptor} holds a file descriptor which permits reading.
+
+@var{offset} is the offset into the file; this will be @code{0} in the
+normal case, but may be a different value when reading an object file
+in an archive file.
+
+@var{segment_name} is only used with the Mach-O file format used on
+Darwin aka Mac OS X.  It is required on that platform, and means to
+only look at sections within the segment with that name.  The
+parameter is ignored on other systems.
+
+If an error occurs, this functions returns @code{NULL} and sets
+@code{*@var{errmsg}} to an error string and sets @code{*@var{err}} to
+an errno value or @code{0} if there is no relevant errno.
+
+@end deftypefn
+
+@deftypefn Extension {const char *} simple_object_find_sections (simple_object_read *@var{simple_object}, int (*@var{pfn}) (void *@var{data}, const char *@var{name}, off_t @var{offset}, off_t @var{length}), void *@var{data}, int *@var{err})
+
+This function calls @var{pfn} for each section in @var{simple_object}.
+It calls @var{pfn} with the section name, the offset within the file
+of the section contents, and the length of the section contents.  The
+offset within the file is relative to the offset passed to
+@code{simple_object_open_read}.  The @var{data} argument to this
+function is passed along to @var{pfn}.
+
+If @var{pfn} returns @code{0}, the loop over the sections stops and
+@code{simple_object_find_sections} returns.  If @var{pfn} returns some
+other value, the loop continues.
+
+On success @code{simple_object_find_sections} returns.  On error it
+returns an error string, and sets @code{*@var{err}} to an errno value
+or @code{0} if there is no relevant errno.
+
+@end deftypefn
+
+@deftypefn Extension {int} simple_object_find_section (simple_object_read *@var{simple_object} off_t *@var{offset}, off_t *@var{length}, const char **@var{errmsg}, int *@var{err})           
+
+Look for the section @var{name} in @var{simple_object}.  This returns
+information for the first section with that name.
+
+If found, return 1 and set @code{*@var{offset}} to the offset in the
+file of the section contents and set @code{*@var{length}} to the
+length of the section contents.  The value in @code{*@var{offset}}
+will be relative to the offset passed to
+@code{simple_object_open_read}.
+
+If the section is not found, and no error occurs,
+@code{simple_object_find_section} returns @code{0} and set
+@code{*@var{errmsg}} to @code{NULL}.
+
+If an error occurs, @code{simple_object_find_section} returns
+@code{0}, sets @code{*@var{errmsg}} to an error message, and sets
+@code{*@var{err}} to an errno value or @code{0} if there is no
+relevant errno.
+
+@end deftypefn
+
+@deftypefn Extension {void} simple_object_release_read (simple_object_read *@var{simple_object})
+
+Release all resources associated with @var{simple_object}.  This does
+not close the file descriptor.
+
+@end deftypefn
+
+@deftypefn Extension {simple_object_attributes *} simple_object_fetch_attributes (simple_object_read *@var{simple_object}, const char **@var{errmsg}, int *@var{err})
+
+Fetch the attributes of @var{simple_object}.  The attributes are
+internal information such as the format of the object file, or the
+architecture it was compiled for.  This information will persist until
+@code{simple_object_attributes_release} is called, even if
+@var{simple_object} itself is released.
+
+On error this returns @code{NULL}, sets @code{*@var{errmsg}} to an
+error message, and sets @code{*@var{err}} to an errno value or
+@code{0} if there is no relevant errno.
+
+@end deftypefn
+
+@deftypefn Extension {const char *} simple_object_attributes_compare (simple_object_attributes *@var{attrs1}, simple_object_attributes *@var{attrs2}, int *@var{err})
+
+Compare @var{attrs1} and @var{attrs2}.  If they could be linked
+together without error, return @code{NULL}.  Otherwise, return an
+error message and set @code{*@var{err}} to an errno value or @code{0}
+if there is no relevant errno.
+
+@end deftypefn
+
+@deftypefn Extension {void} simple_object_release_attributes (simple_object_attributes *@var{attrs})
+
+Release all resources associated with @var{attrs}.
+
+@end deftypefn
+
+@deftypefn Extension {simple_object_write *} simple_object_start_write (simple_object_attributes @var{attrs}, const char *@var{segment_name}, const char **@var{errmsg}, int *@var{err})
+
+Start creating a new object file using the object file format
+described in @var{attrs}.  You must fetch attribute information from
+an existing object file before you can create a new one.  There is
+currently no support for creating an object file de novo.
+
+@var{segment_name} is only used with Mach-O as found on Darwin aka Mac
+OS X.  The parameter is required on that target.  It means that all
+sections are created within the named segment.  It is ignored for
+other object file formats.
+
+On error @code{simple_object_start_write} returns @code{NULL}, sets
+@code{*@var{ERRMSG}} to an error message, and sets @code{*@var{err}}
+to an errno value or @code{0} if there is no relevant errno.
+
+@end deftypefn
+
+@deftypefn Extension {simple_object_write_section *} simple_object_write_create_section (simple_object_write *@var{simple_object}, const char *@var{name}, unsigned int @var{align}, const char **@var{errmsg}, int *@var{err})
+
+Add a section to @var{simple_object}.  @var{name} is the name of the
+new section.  @var{align} is the required alignment expressed as the
+number of required low-order 0 bits (e.g., 2 for alignment to a 32-bit
+boundary).
+
+The section is created as containing data, readable, not writable, not
+executable, not loaded at runtime.  The section is not written to the
+file until @code{simple_object_write_to_file} is called.
+
+On error this returns @code{NULL}, sets @code{*@var{errmsg}} to an
+error message, and sets @code{*@var{err}} to an errno value or
+@code{0} if there is no relevant errno.
+
+@end deftypefn
+
+@deftypefn Extension {const char *} simple_object_write_add_data (simple_object_write *@var{simple_object}, simple_object_write_section *@var{section}, const void *@var{buffer}, size_t @var{size}, int @var{copy}, int *@var{err})
+
+Add data @var{buffer}/@var{size} to @var{section} in
+@var{simple_object}.  If @var{copy} is non-zero, the data will be
+copied into memory if necessary.  If @var{copy} is zero, @var{buffer}
+must persist until @code{simple_object_write_to_file} is called.  is
+released.
+
+On success this returns @code{NULL}.  On error this returns an error
+message, and sets @code{*@var{err}} to an errno value or 0 if there is
+no relevant erro.
+
+@end deftypefn
+
+@deftypefn Extension {const char *} simple_object_write_to_file (simple_object_write *@var{simple_object}, int @var{descriptor}, int *@var{err})
+
+Write the complete object file to @var{descriptor}, an open file
+descriptor.  This writes out all the data accumulated by calls to
+@code{simple_object_write_create_section} and
+@var{simple_object_write_add_data}.
+
+This returns @code{NULL} on success.  On error this returns an error
+message and sets @code{*@var{err}} to an errno value or @code{0} if
+there is no relevant errno.
+
+@end deftypefn
+
+@deftypefn Extension {void} simple_object_release_write (simple_object_write *@var{simple_object})
+
+Release all resources associated with @var{simple_object}.
+
+@end deftypefn
Index: libiberty/simple-object.c
===================================================================
--- libiberty/simple-object.c	(revision 0)
+++ libiberty/simple-object.c	(revision 0)
@@ -0,0 +1,423 @@
+/* simple-object.c -- simple routines to read and write object files.
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+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, 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, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "libiberty.h"
+#include "simple-object.h"
+
+#include <errno.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#include "simple-object-common.h"
+
+/* The known object file formats.  */
+
+static const struct simple_object_functions * const format_functions[] =
+{
+  &simple_object_elf_functions,
+  &simple_object_mach_o_functions,
+  &simple_object_coff_functions
+};
+
+/* Read data from a file using the simple_object error reporting
+   conventions.  */
+
+int
+simple_object_internal_read (int descriptor, off_t offset,
+			     unsigned char *buffer, size_t size,
+			     const char **errmsg, int *err)
+{
+  ssize_t got;
+
+  if (lseek (descriptor, offset, SEEK_SET) < 0)
+    {
+      *errmsg = "lseek";
+      *err = errno;
+      return 0;
+    }
+
+  got = read (descriptor, buffer, size);
+  if (got < 0)
+    {
+      *errmsg = "read";
+      *err = errno;
+      return 0;
+    }
+
+  if ((size_t) got < size)
+    {
+      *errmsg = "file too short";
+      *err = 0;
+      return 0;
+    }
+
+  return 1;
+}
+
+/* Write data to a file using the simple_object error reporting
+   conventions.  */
+
+int
+simple_object_internal_write (int descriptor, off_t offset,
+			      const unsigned char *buffer, size_t size,
+			      const char **errmsg, int *err)
+{
+  ssize_t wrote;
+
+  if (lseek (descriptor, offset, SEEK_SET) < 0)
+    {
+      *errmsg = "lseek";
+      *err = errno;
+      return 0;
+    }
+
+  wrote = write (descriptor, buffer, size);
+  if (wrote < 0)
+    {
+      *errmsg = "write";
+      *err = errno;
+      return 0;
+    }
+
+  if ((size_t) wrote < size)
+    {
+      *errmsg = "short write";
+      *err = 0;
+      return 0;
+    }
+
+  return 1;
+}
+
+/* Open for read.  */
+
+simple_object_read *
+simple_object_start_read (int descriptor, off_t offset,
+			  const char *segment_name, const char **errmsg,
+			  int *err)
+{
+  unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN];
+  size_t len, i;
+
+  if (!simple_object_internal_read (descriptor, offset, header,
+				    SIMPLE_OBJECT_MATCH_HEADER_LEN,
+				    errmsg, err))
+    return NULL;
+
+  len = sizeof (format_functions) / sizeof (format_functions[0]);
+  for (i = 0; i < len; ++i)
+    {
+      void *data;
+
+      data = format_functions[i]->match (header, descriptor, offset,
+					 segment_name, errmsg, err);
+      if (data != NULL)
+	{
+	  simple_object_read *ret;
+
+	  ret = XNEW (simple_object_read);
+	  ret->descriptor = descriptor;
+	  ret->offset = offset;
+	  ret->functions = format_functions[i];
+	  ret->data = data;
+	  return ret;
+	}
+    }
+
+  *errmsg = "file not recognized";
+  *err = 0;
+  return NULL;
+}
+
+/* Find all sections.  */
+
+const char *
+simple_object_find_sections (simple_object_read *sobj,
+			     int (*pfn) (void *, const char *, off_t, off_t),
+			     void *data,
+			     int *err)
+{
+  return sobj->functions->find_sections (sobj, pfn, data, err);
+}
+
+/* Internal data passed to find_one_section.  */
+
+struct find_one_section_data
+{
+  /* The section we are looking for.  */
+  const char *name;
+  /* Where to store the section offset.  */
+  off_t *offset;
+  /* Where to store the section length.  */
+  off_t *length;
+  /* Set if the name is found.  */
+  int found;
+};
+
+/* Internal function passed to find_sections.  */
+
+static int
+find_one_section (void *data, const char *name, off_t offset, off_t length)
+{
+  struct find_one_section_data *fosd = (struct find_one_section_data *) data;
+
+  if (strcmp (name, fosd->name) != 0)
+    return 1;
+
+  *fosd->offset = offset;
+  *fosd->length = length;
+  fosd->found = 1;
+
+  /* Stop iteration.  */
+  return 0;
+}
+
+/* Find a section.  */
+
+int
+simple_object_find_section (simple_object_read *sobj, const char *name,
+			    off_t *offset, off_t *length,
+			    const char **errmsg, int *err)
+{
+  struct find_one_section_data fosd;
+
+  fosd.name = name;
+  fosd.offset = offset;
+  fosd.length = length;
+  fosd.found = 0;
+
+  *errmsg = simple_object_find_sections (sobj, find_one_section,
+					 (void *) &fosd, err);
+  if (*errmsg != NULL)
+    return 0;
+  if (!fosd.found)
+    return 0;
+  return 1;
+}
+
+/* Fetch attributes.  */
+
+simple_object_attributes *
+simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
+				int *err)
+{
+  void *data;
+  simple_object_attributes *ret;
+
+  data = sobj->functions->fetch_attributes (sobj, errmsg, err);
+  if (data == NULL)
+    return NULL;
+  ret = XNEW (simple_object_attributes);
+  ret->functions = sobj->functions;
+  ret->data = data;
+  return ret;
+}
+
+/* Release an simple_object_read.  */
+
+void
+simple_object_release_read (simple_object_read *sobj)
+{
+  sobj->functions->release_read (sobj->data);
+  XDELETE (sobj);
+}
+
+/* Compare attributes.  */
+
+const char *
+simple_object_attributes_compare (simple_object_attributes *attrs1,
+				  simple_object_attributes *attrs2,
+				  int *err)
+{
+  if (attrs1->functions != attrs2->functions)
+    {
+      *err = 0;
+      return "different object file format";
+    }
+  return attrs1->functions->attributes_compare (attrs1->data, attrs2->data,
+						err);
+}
+
+/* Release an attributes structure.  */
+
+void
+simple_object_release_attributes (simple_object_attributes *attrs)
+{
+  attrs->functions->release_attributes (attrs->data);
+  XDELETE (attrs);
+}
+
+/* Start creating an object file.  */
+
+simple_object_write *
+simple_object_start_write (simple_object_attributes *attrs,
+			   const char *segment_name, const char **errmsg,
+			   int *err)
+{
+  void *data;
+  simple_object_write *ret;
+
+  data = attrs->functions->start_write (attrs->data, errmsg, err);
+  if (data == NULL)
+    return NULL;
+  ret = XNEW (simple_object_write);
+  ret->functions = attrs->functions;
+  ret->segment_name = xstrdup (segment_name);
+  ret->sections = NULL;
+  ret->last_section = NULL;
+  ret->data = data;
+  return ret;
+}
+
+/* Start creating a section.  */
+
+simple_object_write_section *
+simple_object_write_create_section (simple_object_write *sobj, const char *name,
+				    unsigned int align,
+				    const char **errmsg ATTRIBUTE_UNUSED,
+				    int *err ATTRIBUTE_UNUSED)
+{
+  simple_object_write_section *ret;
+
+  ret = XNEW (simple_object_write_section);
+  ret->next = NULL;
+  ret->name = xstrdup (name);
+  ret->align = align;
+  ret->buffers = NULL;
+  ret->last_buffer = NULL;
+
+  if (sobj->last_section == NULL)
+    {
+      sobj->sections = ret;
+      sobj->last_section = ret;
+    }
+  else
+    {
+      sobj->last_section->next = ret;
+      sobj->last_section = ret;
+    }
+
+  return ret;
+}
+
+/* Add data to a section.  */
+
+const char *
+simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED,
+			      simple_object_write_section *section,
+			      const void *buffer,
+			      size_t size, int copy,
+			      int *err ATTRIBUTE_UNUSED)
+{
+  struct simple_object_write_section_buffer *wsb;
+
+  wsb = XNEW (struct simple_object_write_section_buffer);
+  wsb->next = NULL;
+  wsb->size = size;
+
+  if (!copy)
+    {
+      wsb->buffer = buffer;
+      wsb->free_buffer = NULL;
+    }
+  else
+    {
+      wsb->free_buffer = (void *) XNEWVEC (char, size);
+      memcpy (wsb->free_buffer, buffer, size);
+      wsb->buffer = wsb->free_buffer;
+    }
+
+  if (section->last_buffer == NULL)
+    {
+      section->buffers = wsb;
+      section->last_buffer = wsb;
+    }
+  else
+    {
+      section->last_buffer->next = wsb;
+      section->last_buffer = wsb;
+    }
+
+  return NULL;
+}
+
+/* Write the complete object file.  */
+
+const char *
+simple_object_write_to_file (simple_object_write *sobj, int descriptor,
+			     int *err)
+{
+  return sobj->functions->write_to_file (sobj, descriptor, err);
+}
+
+/* Release an simple_object_write.  */
+
+void
+simple_object_release_write (simple_object_write *sobj)
+{
+  simple_object_write_section *section;
+
+  free (sobj->segment_name);
+
+  section = sobj->sections;
+  while (section != NULL)
+    {
+      struct simple_object_write_section_buffer *buffer;
+      simple_object_write_section *next_section;
+
+      buffer = section->buffers;
+      while (buffer != NULL)
+	{
+	  struct simple_object_write_section_buffer *next_buffer;
+
+	  if (buffer->free_buffer != NULL)
+	    XDELETEVEC (buffer->free_buffer);
+	  next_buffer = buffer->next;
+	  XDELETE (buffer);
+	  buffer = next_buffer;
+	}
+
+      next_section = section->next;
+      free (section->name);
+      XDELETE (section);
+      section = next_section;
+    }
+
+  sobj->functions->release_write (sobj->data);
+  XDELETE (sobj);
+}
Index: gcc/lto/lto-object.c
===================================================================
--- gcc/lto/lto-object.c	(revision 0)
+++ gcc/lto/lto-object.c	(revision 0)
@@ -0,0 +1,376 @@
+/* LTO routines to use object files.
+   Copyright 2010 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Google.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic-core.h"
+#include "toplev.h"
+#include "lto.h"
+#include "tm.h"
+#include "lto-streamer.h"
+#include "libiberty.h"
+#include "simple-object.h"
+
+/* Handle opening elf files on hosts, such as Windows, that may use
+   text file handling that will break binary access.  */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+/* Segment name for LTO sections.  This is only used for Mach-O.
+   FIXME: This needs to be kept in sync with darwin.c.  */
+
+#define LTO_SEGMENT_NAME "__GNU_LTO"
+
+/* An LTO file wrapped around an simple_object.  */
+
+struct lto_simple_object
+{
+  /* The base information.  */
+  lto_file base;
+
+  /* The system file descriptor.  */
+  int fd;
+
+  /* The simple_object if we are reading the file.  */
+  simple_object_read *sobj_r;
+
+  /* The simple_object if we are writing the file.  */
+  simple_object_write *sobj_w;
+
+  /* The currently active section.  */
+  simple_object_write_section *section;
+};
+
+/* Saved simple_object attributes.  FIXME: Once set, this is never
+   cleared.  */
+
+static simple_object_attributes *saved_attributes;
+
+/* Initialize FILE, an LTO file object for FILENAME.  */
+
+static void
+lto_file_init (lto_file *file, const char *filename, off_t offset)
+{
+  file->filename = filename;
+  file->offset = offset;
+}
+
+/* Open the file FILENAME.  It WRITABLE is true, the file is opened
+   for write and, if necessary, created.  Otherwise, the file is
+   opened for reading.  Returns the opened file.  */
+
+lto_file *
+lto_obj_file_open (const char *filename, bool writable)
+{
+  const char *offset_p;
+  long loffset;
+  int consumed;
+  char *fname;
+  off_t offset;
+  struct lto_simple_object *lo;
+  const char *errmsg;
+  int err;
+
+  offset_p = strrchr (filename, '@');
+  if (offset_p != NULL
+      && offset_p != filename
+      && sscanf (offset_p, "@%li%n", &loffset, &consumed) >= 1
+      && strlen (offset_p) == (unsigned int) consumed)
+    {
+      fname = XNEWVEC (char, offset_p - filename + 1);
+      memcpy (fname, filename, offset_p - filename);
+      fname[offset_p - filename] = '\0';
+      offset = (off_t) loffset;
+    }
+  else
+    {
+      fname = xstrdup (filename);
+      offset = 0;
+    }
+
+  lo = XCNEW (struct lto_simple_object);
+  lto_file_init ((lto_file *) lo, fname, offset);
+
+  lo->fd = open (fname,
+		 (writable
+		  ? O_WRONLY | O_CREAT | O_BINARY
+		  : O_RDONLY | O_BINARY),
+		 0666);
+  if (lo->fd == -1)
+    {
+      error ("open %s failed: %s", fname, xstrerror (errno));
+      goto fail;
+    }
+
+  if (!writable)
+    {
+      simple_object_attributes *attrs;
+
+      lo->sobj_r = simple_object_start_read (lo->fd, offset, LTO_SEGMENT_NAME,
+					     &errmsg, &err);
+      if (lo->sobj_r == NULL)
+	goto fail_errmsg;
+
+      attrs = simple_object_fetch_attributes (lo->sobj_r, &errmsg, &err);
+      if (attrs == NULL)
+	goto fail_errmsg;
+
+      if (saved_attributes == NULL)
+	saved_attributes = attrs;
+      else
+	{
+	  errmsg = simple_object_attributes_compare (saved_attributes, attrs,
+						     &err);
+	  if (errmsg != NULL)
+	    goto fail_errmsg;
+	}
+    }
+  else
+    {
+      gcc_assert (saved_attributes != NULL);
+      lo->sobj_w = simple_object_start_write (saved_attributes,
+					      LTO_SEGMENT_NAME,
+					      &errmsg, &err);
+      if (lo->sobj_w == NULL)
+	goto fail_errmsg;
+    }
+
+  return &lo->base;
+
+ fail_errmsg:
+  if (err == 0)
+    error ("%s: %s", fname, errmsg);
+  else
+    error ("%s: %s: %s", fname, errmsg, xstrerror (err));
+					 
+ fail:
+  if (lo != NULL)
+    lto_obj_file_close ((lto_file *) lo);
+  return NULL;
+}
+
+/* Close FILE.  If FILE was opened for writing, it is written out
+   now.  */
+
+void
+lto_obj_file_close (lto_file *file)
+{
+  struct lto_simple_object *lo = (struct lto_simple_object *) file;
+
+  if (lo->sobj_r != NULL)
+    simple_object_release_read (lo->sobj_r);
+  else if (lo->sobj_w != NULL)
+    {
+      const char *errmsg;
+      int err;
+
+      gcc_assert (lo->base.offset == 0);
+
+      errmsg = simple_object_write_to_file (lo->sobj_w, lo->fd, &err);
+      if (errmsg != NULL)
+	{
+	  if (err == 0)
+	    fatal_error ("%s", errmsg);
+	  else
+	    fatal_error ("%s: %s", errmsg, xstrerror (err));
+	}
+
+      simple_object_release_write (lo->sobj_w);
+    }
+
+  if (lo->fd != -1)
+    {
+      if (close (lo->fd) < 0)
+	fatal_error ("close: %s", xstrerror (errno));
+    }
+}
+
+/* This is passed to lto_obj_add_section.  */
+
+struct lto_obj_add_section_data
+{
+  /* The hash table of sections.  */
+  htab_t section_hash_table;
+  /* The offset of this file.  */
+  off_t base_offset;
+};
+
+/* This is called for each section in the file.  */
+
+static int
+lto_obj_add_section (void *data, const char *name, off_t offset,
+		     off_t length)
+{
+  struct lto_obj_add_section_data *loasd =
+    (struct lto_obj_add_section_data *) data;
+  htab_t section_hash_table = (htab_t) loasd->section_hash_table;
+  char *new_name;
+  struct lto_section_slot s_slot;
+  void **slot;
+
+  if (strncmp (name, LTO_SECTION_NAME_PREFIX,
+	       strlen (LTO_SECTION_NAME_PREFIX)) != 0)
+    return 1;
+
+  new_name = xstrdup (name);
+  s_slot.name = new_name;
+  slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
+  if (*slot == NULL)
+    {
+      struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
+
+      new_slot->name = new_name;
+      new_slot->start = loasd->base_offset + offset;
+      new_slot->len = length;
+      *slot = new_slot;
+    }
+  else
+    {
+      error ("two or more sections for %s", new_name);
+      return 0;
+    }
+
+  return 1;
+}
+
+/* Build a hash table whose key is the section name and whose data is
+   the start and size of each section in the .o file.  */
+
+htab_t
+lto_obj_build_section_table (lto_file *lto_file)
+{
+  struct lto_simple_object *lo = (struct lto_simple_object *) lto_file;
+  htab_t section_hash_table;
+  struct lto_obj_add_section_data loasd;
+  const char *errmsg;
+  int err;
+
+  section_hash_table = lto_obj_create_section_hash_table ();
+
+  gcc_assert (lo->sobj_r != NULL && lo->sobj_w == NULL);
+  loasd.section_hash_table = section_hash_table;
+  loasd.base_offset = lo->base.offset;
+  errmsg = simple_object_find_sections (lo->sobj_r, lto_obj_add_section,
+					&loasd, &err);
+  if (errmsg != NULL)
+    {
+      if (err == 0)
+	error ("%s", errmsg);
+      else
+	error ("%s: %s", errmsg, xstrerror (err));
+      htab_delete (section_hash_table);
+      return NULL;
+    }
+
+  return section_hash_table;
+}
+
+/* The current output file.  */
+
+static lto_file *current_out_file;
+
+/* Set the current output file.  Return the old one.  */
+
+lto_file *
+lto_set_current_out_file (lto_file *file)
+{
+  lto_file *old_file;
+
+  old_file = current_out_file;
+  current_out_file = file;
+  return old_file;
+}
+
+/* Return the current output file.  */
+
+lto_file *
+lto_get_current_out_file (void)
+{
+  return current_out_file;
+}
+
+/* Begin writing a new section named NAME in the current output
+   file.  */
+
+void
+lto_obj_begin_section (const char *name)
+{
+  struct lto_simple_object *lo;
+  int align;
+  const char *errmsg;
+  int err;
+
+  lo = (struct lto_simple_object *) current_out_file;
+  gcc_assert (lo != NULL
+	      && lo->sobj_r == NULL
+	      && lo->sobj_w != NULL
+	      && lo->section == NULL);
+
+  align = exact_log2 (POINTER_SIZE / BITS_PER_UNIT);
+  lo->section = simple_object_write_create_section (lo->sobj_w, name, align,
+						    &errmsg, &err);
+  if (lo->section == NULL)
+    {
+      if (err == 0)
+	fatal_error ("%s", errmsg);
+      else
+	fatal_error ("%s: %s", errmsg, xstrerror (errno));
+    }
+}
+
+/* Add data to a section.  BLOCK is a pointer to memory containing
+   DATA.  */
+
+void
+lto_obj_append_data (const void *data, size_t len, void *block)
+{
+  struct lto_simple_object *lo;
+  const char *errmsg;
+  int err;
+
+  lo = (struct lto_simple_object *) current_out_file;
+  gcc_assert (lo != NULL && lo->section != NULL);
+
+  errmsg = simple_object_write_add_data (lo->sobj_w, lo->section, data, len,
+					 1, &err);
+  if (errmsg != NULL)
+    {
+      if (err == 0)
+	fatal_error ("%s", errmsg);
+      else
+	fatal_error ("%s: %s", errmsg, xstrerror (errno));
+    }
+
+  free (block);
+}
+
+/* Stop writing to the current output section.  */
+
+void
+lto_obj_end_section (void)
+{
+  struct lto_simple_object *lo;
+
+  lo = (struct lto_simple_object *) current_out_file;
+  gcc_assert (lo != NULL && lo->section != NULL);
+  lo->section = NULL;
+}
Index: gcc/lto/lto-elf.c
===================================================================
--- gcc/lto/lto-elf.c	(revision 166080)
+++ gcc/lto/lto-elf.c	(working copy)
@@ -1,817 +0,0 @@
-/* LTO routines for ELF object files.
-   Copyright 2009, 2010 Free Software Foundation, Inc.
-   Contributed by CodeSourcery, Inc.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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 GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "diagnostic-core.h"
-#include "toplev.h"
-#include <gelf.h>
-#include "lto.h"
-#include "tm.h"
-#include "libiberty.h"
-#include "ggc.h"
-#include "lto-streamer.h"
-
-/* Cater to hosts with half-backed <elf.h> file like HP-UX.  */
-#ifndef EM_SPARC
-# define EM_SPARC 2
-#endif
-
-#ifndef EM_SPARC32PLUS
-# define EM_SPARC32PLUS 18
-#endif
-
-#ifndef ELFOSABI_NONE
-# define ELFOSABI_NONE 0
-#endif
-
-#ifndef ELFOSABI_LINUX
-# define ELFOSABI_LINUX 3
-#endif
-
-#ifndef SHN_XINDEX
-# define SHN_XINDEX 0xffff
-#endif
-
-
-/* Handle opening elf files on hosts, such as Windows, that may use 
-   text file handling that will break binary access.  */
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-
-/* Initialize FILE, an LTO file object for FILENAME.  */
-static void
-lto_file_init (lto_file *file, const char *filename, off_t offset)
-{
-  file->filename = filename;
-  file->offset = offset;
-}
-
-/* An ELF file.  */
-struct lto_elf_file 
-{
-  /* The base information.  */
-  lto_file base;
-
-  /* The system file descriptor for the file.  */
-  int fd;
-
-  /* The libelf descriptor for the file.  */
-  Elf *elf;
-
-  /* Section number of string table used for section names.  */
-  size_t sec_strtab;
-
-  /* Writable file members.  */
-
-  /* The currently active section.  */
-  Elf_Scn *scn;
-
-  /* The output stream for section header names.  */
-  struct lto_output_stream *shstrtab_stream;
-
-  /* Linked list of data which must be freed *after* the file has been
-     closed.  This is an annoying limitation of libelf.  */
-  struct lto_char_ptr_base *data;
-};
-typedef struct lto_elf_file lto_elf_file;
-
-/* Stores executable header attributes which must be shared by all ELF files.
-   This is used for validating input files and populating output files.  */
-static struct {
-  bool initialized;
-  /* 32 or 64 bits?  */
-  size_t bits;
-  unsigned char elf_ident[EI_NIDENT];
-  Elf64_Half elf_machine;
-} cached_file_attrs;
-
-
-/* Return the section header for SECTION.  The return value is never
-   NULL.  Call lto_elf_free_shdr to release the memory allocated.  */
-
-static Elf64_Shdr *
-lto_elf_get_shdr (Elf_Scn *section)
-{
-  Elf64_Shdr *shdr;
-
-  switch (cached_file_attrs.bits)
-    {
-    case 32:
-      {
-	Elf32_Shdr *shdr32;
-
-	/* Read the 32-bit section header.  */
-	shdr32 = elf32_getshdr (section);
-	if (!shdr32)
-	  fatal_error ("could not read section header: %s", elf_errmsg (0));
-
-	/* Transform it into a 64-bit section header.  */
-	shdr = XNEW (Elf64_Shdr);
-	shdr->sh_name = shdr32->sh_name;
-	shdr->sh_type = shdr32->sh_type;
-	shdr->sh_flags = shdr32->sh_flags;
-	shdr->sh_addr = shdr32->sh_addr;
-	shdr->sh_offset = shdr32->sh_offset;
-	shdr->sh_size = shdr32->sh_size;
-	shdr->sh_link = shdr32->sh_link;
-	shdr->sh_info = shdr32->sh_info;
-	shdr->sh_addralign = shdr32->sh_addralign;
-	shdr->sh_entsize  = shdr32->sh_entsize;
-	break;
-      }
-      break;
-
-    case 64:
-      shdr = elf64_getshdr (section);
-      if (!shdr)
-	fatal_error ("could not read section header: %s", elf_errmsg (0));
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  return shdr;
-}
-
-/* Free SHDR, previously allocated by lto_elf_get_shdr.  */
-static void
-lto_elf_free_shdr (Elf64_Shdr *shdr)
-{
-  if (cached_file_attrs.bits != 64)
-    free (shdr);
-}
-
-/* Build a hash table whose key is the section names and whose data is
-   the start and size of each section in the .o file.  */
-
-htab_t
-lto_obj_build_section_table (lto_file *lto_file) 
-{
-  lto_elf_file *elf_file = (lto_elf_file *)lto_file;
-  htab_t section_hash_table;
-  Elf_Scn *section;
-  size_t base_offset;
-
-  section_hash_table = lto_obj_create_section_hash_table ();
-
-  base_offset = elf_getbase (elf_file->elf);
-  /* We are reasonably sure that elf_getbase does not fail at this
-     point.  So assume that we run into the incompatibility with
-     the FreeBSD libelf implementation that has a non-working
-     elf_getbase for non-archive members in which case the offset
-     should be zero.  */
-  if (base_offset == (size_t)-1)
-    base_offset = 0;
-  for (section = elf_getscn (elf_file->elf, 0);
-       section;
-       section = elf_nextscn (elf_file->elf, section)) 
-    {
-      Elf64_Shdr *shdr;
-      const char *name;
-      size_t offset;
-      char *new_name;
-      void **slot;
-      struct lto_section_slot s_slot;
-
-      /* Get the name of this section.  */
-      shdr = lto_elf_get_shdr (section);
-      offset = shdr->sh_name;
-      name = elf_strptr (elf_file->elf, 
-			 elf_file->sec_strtab,
-			 offset);
-
-      /* Only put lto stuff into the symtab.  */
-      if (strncmp (name, LTO_SECTION_NAME_PREFIX, 
-		   strlen (LTO_SECTION_NAME_PREFIX)) != 0)
-	{
-	  lto_elf_free_shdr (shdr);
-	  continue;
-	}
-
-      new_name = XNEWVEC (char, strlen (name) + 1);
-      strcpy (new_name, name);
-      s_slot.name = new_name;
-      slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
-      if (*slot == NULL)
-	{
-	  struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
-
-	  new_slot->name = new_name;
-	  /* The offset into the file for this section.  */
-	  new_slot->start = base_offset + shdr->sh_offset;
-	  new_slot->len = shdr->sh_size;
-	  *slot = new_slot;
-	}
-      else
-	{
-	  error ("two or more sections for %s:", new_name);
-	  return NULL;
-	}
-
-      lto_elf_free_shdr (shdr);
-    }
-
-  return section_hash_table;
-}
-
-
-/* Initialize the section header of section SCN.  SH_NAME is the section name
-   as an index into the section header string table.  SH_TYPE is the section
-   type, an SHT_* macro from libelf headers.  */
-
-#define DEFINE_INIT_SHDR(BITS)					      \
-static void							      \
-init_shdr##BITS (Elf_Scn *scn, size_t sh_name, size_t sh_type)	      \
-{								      \
-  Elf##BITS##_Shdr *shdr;					      \
-								      \
-  shdr = elf##BITS##_getshdr (scn);				      \
-  if (!shdr)							      \
-    {								      \
-      if (BITS == 32)						      \
-	fatal_error ("elf32_getshdr() failed: %s", elf_errmsg (-1));  \
-      else							      \
-	fatal_error ("elf64_getshdr() failed: %s", elf_errmsg (-1));  \
-    }								      \
-								      \
-  shdr->sh_name = sh_name;					      \
-  shdr->sh_type = sh_type;					      \
-  shdr->sh_addralign = POINTER_SIZE / BITS_PER_UNIT;		      \
-  shdr->sh_flags = 0;						      \
-  shdr->sh_entsize = 0;						      \
-}
-
-DEFINE_INIT_SHDR (32)
-DEFINE_INIT_SHDR (64)
-
-static bool first_data_block;
-
-/* Begin a new ELF section named NAME with type TYPE in the current output
-   file.  TYPE is an SHT_* macro from the libelf headers.  */
-
-static void
-lto_elf_begin_section_with_type (const char *name, size_t type)
-{
-  lto_elf_file *file;
-  Elf_Scn *scn;
-  size_t sh_name;
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_elf_file *) lto_get_current_out_file (),
-  gcc_assert (file);
-  gcc_assert (file->elf);
-  gcc_assert (!file->scn);
-
-  /* Create a new section.  */
-  scn = elf_newscn (file->elf);
-  if (!scn)
-    fatal_error ("could not create a new ELF section: %s", elf_errmsg (-1));
-  file->scn = scn;
-
-  /* Add a string table entry and record the offset.  */
-  gcc_assert (file->shstrtab_stream);
-  sh_name = file->shstrtab_stream->total_size;
-  lto_output_data_stream (file->shstrtab_stream, name, strlen (name) + 1);
-
-  /* Initialize the section header.  */
-  switch (cached_file_attrs.bits)
-    {
-    case 32:
-      init_shdr32 (scn, sh_name, type);
-      break;
-
-    case 64:
-      init_shdr64 (scn, sh_name, type);
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  first_data_block = true;
-}
-
-
-/* Begin a new ELF section named NAME in the current output file.  */
-
-void
-lto_obj_begin_section (const char *name)
-{
-  lto_elf_begin_section_with_type (name, SHT_PROGBITS);
-}
-
-
-/* Append DATA of length LEN to the current output section.  BASE is a pointer
-   to the output page containing DATA.  It is freed once the output file has
-   been written.  */
-
-void
-lto_obj_append_data (const void *data, size_t len, void *block)
-{
-  lto_elf_file *file;
-  Elf_Data *elf_data;
-  struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block;
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_elf_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  elf_data = elf_newdata (file->scn);
-  if (!elf_data)
-    fatal_error ("could not append data to ELF section: %s", elf_errmsg (-1));
-
-  if (first_data_block)
-    {
-      elf_data->d_align = POINTER_SIZE / BITS_PER_UNIT;
-      first_data_block = false;
-    }
-  else
-    elf_data->d_align = 1;
-  elf_data->d_buf = CONST_CAST (void *, data);
-  elf_data->d_off = 0LL;
-  elf_data->d_size = len;
-  elf_data->d_type = ELF_T_BYTE;
-  elf_data->d_version = EV_CURRENT;
-
-  base->ptr = (char *)file->data;
-  file->data = base;
-}
-
-
-/* End the current output section.  This just does some assertion checking
-   and sets the current output file's scn member to NULL.  */
-
-void
-lto_obj_end_section (void)
-{
-  lto_elf_file *file;
-
-  /* Grab the current output file and validate some basic assertions.  */
-  file = (lto_elf_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  file->scn = NULL;
-}
-
-
-/* Return true if ELF_MACHINE is compatible with the cached value of the
-   architecture and possibly update the latter.  Return false otherwise.
-
-   Note: if you want to add more EM_* cases, you'll need to provide the
-   corresponding definitions at the beginning of the file.  */
-
-static bool
-is_compatible_architecture (Elf64_Half elf_machine)
-{
-  if (cached_file_attrs.elf_machine == elf_machine)
-    return true;
-
-  switch (cached_file_attrs.elf_machine)
-    {
-    case EM_SPARC:
-      if (elf_machine == EM_SPARC32PLUS)
-	{
-	  cached_file_attrs.elf_machine = elf_machine;
-	  return true;
-	}
-      break;
-
-    case EM_SPARC32PLUS:
-      if (elf_machine == EM_SPARC)
-	return true;
-      break;
-
-    default:
-      break;
-    }
-
-  return false;
-}
-
-
-/* Validate's ELF_FILE's executable header and, if cached_file_attrs is
-   uninitialized, caches the architecture.  */
-
-#define DEFINE_VALIDATE_EHDR(BITS)				\
-static bool							\
-validate_ehdr##BITS (lto_elf_file *elf_file)			\
-{								\
-  Elf##BITS##_Ehdr *elf_header;					\
-								\
-  elf_header = elf##BITS##_getehdr (elf_file->elf);		\
-  if (!elf_header)						\
-    {								\
-      error ("could not read ELF header: %s", elf_errmsg (0));	\
-      return false;						\
-    }								\
-								\
-  if (elf_header->e_type != ET_REL)				\
-    {								\
-      error ("not a relocatable ELF object file");		\
-      return false;						\
-    }								\
-								\
-  if (!cached_file_attrs.initialized)				\
-    cached_file_attrs.elf_machine = elf_header->e_machine;	\
-  else if (!is_compatible_architecture (elf_header->e_machine))	\
-    {								\
-      error ("inconsistent file architecture detected");	\
-      return false;						\
-    }								\
-								\
-  return true;							\
-}
-
-DEFINE_VALIDATE_EHDR (32)
-DEFINE_VALIDATE_EHDR (64)
-
-
-#ifndef HAVE_ELF_GETSHDRSTRNDX
-/* elf_getshdrstrndx replacement for systems that lack it, but provide
-   either the gABI conformant or Solaris 2 variant of elf_getshstrndx
-   instead.  */
-
-static int
-elf_getshdrstrndx (Elf *elf, size_t *dst)
-{
-#ifdef HAVE_ELF_GETSHSTRNDX_GABI
-  return elf_getshstrndx (elf, dst);
-#else
-  return elf_getshstrndx (elf, dst) ? 0 : -1;
-#endif
-}
-#endif
-
-/* Validate's ELF_FILE's executable header and, if cached_file_attrs is
-   uninitialized, caches the results.  Also records the section header string
-   table's section index.  Returns true on success or false on failure.  */
-
-static bool
-validate_file (lto_elf_file *elf_file)
-{
-  const char *elf_ident;
-
-  /* Some aspects of the libelf API are dependent on whether the
-     object file is a 32-bit or 64-bit file.  Determine which kind of
-     file this is now.  */
-  elf_ident = elf_getident (elf_file->elf, NULL);
-  if (!elf_ident)
-    {
-      error ("could not read ELF identification information: %s",
-	      elf_errmsg (0));
-      return false;
-    }
-
-  if (!cached_file_attrs.initialized)
-    {
-      switch (elf_ident[EI_CLASS])
-	{
-	case ELFCLASS32:
-	  cached_file_attrs.bits = 32;
-	  break;
-
-	case ELFCLASS64:
-	  cached_file_attrs.bits = 64;
-	  break;
-
-	default:
-	  error ("unsupported ELF file class");
-	  return false;
-	}
-
-      memcpy (cached_file_attrs.elf_ident, elf_ident,
-	      sizeof cached_file_attrs.elf_ident);
-    }
-  else
-    {
-      char elf_ident_buf[EI_NIDENT];
-
-      memcpy (elf_ident_buf, elf_ident, sizeof elf_ident_buf);
-
-      if (elf_ident_buf[EI_OSABI] != cached_file_attrs.elf_ident[EI_OSABI])
-	{
-	  /* Allow mixing ELFOSABI_NONE with ELFOSABI_LINUX, with the result
-	     ELFOSABI_LINUX.  */
-	  if (elf_ident_buf[EI_OSABI] == ELFOSABI_NONE
-	      && cached_file_attrs.elf_ident[EI_OSABI] == ELFOSABI_LINUX)
-	    elf_ident_buf[EI_OSABI] = cached_file_attrs.elf_ident[EI_OSABI];
-	  else if (elf_ident_buf[EI_OSABI] == ELFOSABI_LINUX
-		   && cached_file_attrs.elf_ident[EI_OSABI] == ELFOSABI_NONE)
-	    cached_file_attrs.elf_ident[EI_OSABI] = elf_ident_buf[EI_OSABI];
-	}
-
-      if (memcmp (elf_ident_buf, cached_file_attrs.elf_ident,
-		  sizeof cached_file_attrs.elf_ident))
-	{
-	  error ("incompatible ELF identification");
-	  return false;
-	}
-    }
-
-  /* Check that the input file is a relocatable object file with the correct
-     architecture.  */
-  switch (cached_file_attrs.bits)
-    {
-    case 32:
-      if (!validate_ehdr32 (elf_file))
-	return false;
-      break;
-
-    case 64:
-      if (!validate_ehdr64 (elf_file))
-	return false;
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
-  /* Read the string table used for section header names.  */
-  if (elf_getshdrstrndx (elf_file->elf, &elf_file->sec_strtab) == -1)
-    {
-      error ("could not locate ELF string table: %s", elf_errmsg (0));
-      return false;
-    }
-
-  cached_file_attrs.initialized = true;
-  return true;
-}
-
-
-/* Helper functions used by init_ehdr.  Initialize ELF_FILE's executable
-   header using cached data from previously read files.  */
-
-#define DEFINE_INIT_EHDR(BITS)					      \
-static void							      \
-init_ehdr##BITS (lto_elf_file *elf_file)			      \
-{								      \
-  Elf##BITS##_Ehdr *ehdr;					      \
-								      \
-  gcc_assert (cached_file_attrs.bits);				      \
-								      \
-  ehdr = elf##BITS##_newehdr (elf_file->elf);			      \
-  if (!ehdr)							      \
-    {								      \
-      if (BITS == 32)						      \
-	fatal_error ("elf32_newehdr() failed: %s", elf_errmsg (-1));  \
-      else							      \
-	fatal_error ("elf64_newehdr() failed: %s", elf_errmsg (-1));  \
-    }								      \
-								      \
-  memcpy (ehdr->e_ident, cached_file_attrs.elf_ident,		      \
-	  sizeof cached_file_attrs.elf_ident);			      \
-  ehdr->e_type = ET_REL;					      \
-  ehdr->e_version = EV_CURRENT;					      \
-  ehdr->e_machine = cached_file_attrs.elf_machine;		      \
-}
-
-DEFINE_INIT_EHDR (32)
-DEFINE_INIT_EHDR (64)
-
-
-/* Initialize ELF_FILE's executable header using cached data from previously
-   read files.  */
-
-static void
-init_ehdr (lto_elf_file *elf_file)
-{
-  switch (cached_file_attrs.bits)
-    {
-    case 32:
-      init_ehdr32 (elf_file);
-      break;
-
-    case 64:
-      init_ehdr64 (elf_file);
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Open ELF file FILENAME.  If WRITABLE is true, the file is opened for write
-   and, if necessary, created.  Otherwise, the file is opened for reading.
-   Returns the opened file.  */
-
-lto_file *
-lto_obj_file_open (const char *filename, bool writable)
-{
-  lto_elf_file *elf_file;
-  lto_file *result = NULL;
-  off_t offset;
-  long loffset;
-  off_t header_offset;
-  const char *offset_p;
-  char *fname;
-  int consumed;
-
-  offset_p = strrchr (filename, '@');
-  if (offset_p
-      && offset_p != filename
-      && sscanf (offset_p, "@%li%n", &loffset, &consumed) >= 1
-      && strlen (offset_p) == (unsigned int)consumed)
-    {
-      fname = (char *) xmalloc (offset_p - filename + 1);
-      memcpy (fname, filename, offset_p - filename);
-      fname[offset_p - filename] = '\0';
-      offset = (off_t)loffset;
-      /* elf_rand expects the offset to point to the ar header, not the
-         object itself. Subtract the size of the ar header (60 bytes).
-         We don't uses sizeof (struct ar_hd) to avoid including ar.h */
-      header_offset = offset - 60;
-    }
-  else
-    {
-      fname = xstrdup (filename);
-      offset = 0;
-      header_offset = 0;
-    }
-
-  /* Set up.  */
-  elf_file = XCNEW (lto_elf_file);
-  result = (lto_file *) elf_file;
-  lto_file_init (result, fname, offset);
-  elf_file->fd = -1;
-
-  /* Open the file.  */
-  elf_file->fd = open (fname, writable ? O_WRONLY|O_CREAT|O_BINARY 
-				       : O_RDONLY|O_BINARY, 0666);
-  if (elf_file->fd == -1)
-    {
-      error ("could not open file %s", fname);
-      goto fail;
-    }
-
-  /* Initialize the ELF library.  */
-  if (elf_version (EV_CURRENT) == EV_NONE)
-    {
-      error ("ELF library is older than that used when building GCC");
-      goto fail;
-    }
-
-  /* Open the ELF file descriptor.  */
-  elf_file->elf = elf_begin (elf_file->fd, writable ? ELF_C_WRITE : ELF_C_READ,
-			     NULL);
-  if (!elf_file->elf)
-    {
-      error ("could not open %s as an ELF file: %s", fname, elf_errmsg (0));
-      goto fail;
-    }
-
-  if (offset != 0)
-    {
-      Elf *e;
-      off_t t = elf_rand (elf_file->elf, header_offset);
-      if (t != header_offset)
-        {
-          error ("could not seek in archive");
-          goto fail;
-        }
-
-      e = elf_begin (elf_file->fd, ELF_C_READ, elf_file->elf);
-      if (e == NULL)
-        {
-          error("could not find archive member");
-          goto fail;
-        }
-      elf_end (elf_file->elf);
-      elf_file->elf = e;
-    }
-
-  if (writable)
-    {
-      init_ehdr (elf_file);
-      elf_file->shstrtab_stream = XCNEW (struct lto_output_stream);
-      /* Output an empty string to the section header table.  This becomes the
-	 name of the initial NULL section.  */
-      lto_output_1_stream (elf_file->shstrtab_stream, '\0');
-    }
-  else
-    if (!validate_file (elf_file))
-      goto fail;
-
-  return result;
-
- fail:
-  if (result)
-    lto_obj_file_close (result);
-  return NULL;
-}
-
-
-/* Close ELF file FILE and clean up any associated data structures.  If FILE
-   was opened for writing, the file's ELF data is written at this time, and
-   any cached data buffers are freed.  */
-
-void
-lto_obj_file_close (lto_file *file)
-{
-  lto_elf_file *elf_file = (lto_elf_file *) file;
-  struct lto_char_ptr_base *cur, *tmp;
-
-  /* Write the ELF section header string table.  */
-  if (elf_file->shstrtab_stream)
-    {
-      size_t strtab;
-      GElf_Ehdr *ehdr_p, ehdr_buf;
-      lto_file *old_file = lto_set_current_out_file (file);
-
-      lto_elf_begin_section_with_type (".shstrtab", SHT_STRTAB);
-      ehdr_p = gelf_getehdr (elf_file->elf, &ehdr_buf);
-      if (ehdr_p == NULL)
-	fatal_error ("gelf_getehdr() failed: %s", elf_errmsg (-1));
-      strtab = elf_ndxscn (elf_file->scn);
-      if (strtab < SHN_LORESERVE)
-	ehdr_p->e_shstrndx = strtab;
-      else
-	{
-	  GElf_Shdr *shdr_p, shdr_buf;
-	  Elf_Scn *scn_p = elf_getscn (elf_file->elf, 0);
-	  if (scn_p == NULL)
-	    fatal_error ("elf_getscn() failed: %s", elf_errmsg (-1));
-	  shdr_p = gelf_getshdr (scn_p, &shdr_buf);
-	  if (shdr_p == NULL)
-	    fatal_error ("gelf_getshdr() failed: %s", elf_errmsg (-1));
-	  shdr_p->sh_link = strtab;
-	  if (gelf_update_shdr (scn_p, shdr_p) == 0)
-	    fatal_error ("gelf_update_shdr() failed: %s", elf_errmsg (-1));
-	  ehdr_p->e_shstrndx = SHN_XINDEX;
-	}
-      if (gelf_update_ehdr (elf_file->elf, ehdr_p) == 0)
-	fatal_error ("gelf_update_ehdr() failed: %s", elf_errmsg (-1));
-      lto_write_stream (elf_file->shstrtab_stream);
-      lto_obj_end_section ();
-
-      lto_set_current_out_file (old_file);
-      free (elf_file->shstrtab_stream);
-
-      if (elf_update (elf_file->elf, ELF_C_WRITE) < 0)
-	fatal_error ("elf_update() failed: %s", elf_errmsg (-1));
-    }
-
-  if (elf_file->elf)
-    elf_end (elf_file->elf);
-  if (elf_file->fd != -1)
-    close (elf_file->fd);
-
-  /* Free any ELF data buffers.  */
-  cur = elf_file->data;
-  while (cur)
-    {
-      tmp = cur;
-      cur = (struct lto_char_ptr_base *) cur->ptr;
-      free (tmp);
-    }
-
-  free (file);
-}
-
-
-/* The current output file.  */
-static lto_file *current_out_file;
-
-
-/* Sets the current output file to FILE.  Returns the old output file or
-   NULL.  */
-
-lto_file *
-lto_set_current_out_file (lto_file *file)
-{
-  lto_file *old_file = current_out_file;
-  current_out_file = file;
-  return old_file;
-}
-
-
-/* Returns the current output file.  */
-
-lto_file *
-lto_get_current_out_file (void)
-{
-  return current_out_file;
-}
Index: gcc/lto/lto-coff.c
===================================================================
--- gcc/lto/lto-coff.c	(revision 166080)
+++ gcc/lto/lto-coff.c	(working copy)
@@ -1,817 +0,0 @@
-/* LTO routines for COFF object files.
-   Copyright 2009, 2010 Free Software Foundation, Inc.
-   Contributed by Dave Korn.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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 GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "diagnostic-core.h"
-#include "toplev.h"
-#include "lto.h"
-#include "tm.h"
-#include "libiberty.h"
-#include "ggc.h"
-#include "lto-streamer.h"
-#include "lto/lto-coff.h"
-
-
-/* Rather than implementing a libcoff to match libelf, or attempting to
-   integrate libbfd into GCC, this file is a self-contained (and very
-   minimal) COFF format object file reader/writer.  The generated files
-   will contain a COFF header, a number of COFF section headers, the 
-   section data itself, and a trailing string table for section names.  */
-
-/* Handle opening elf files on hosts, such as Windows, that may use 
-   text file handling that will break binary access.  */
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-/* Known header magics for validation, as an array.  */
-
-static const unsigned int coff_machine_array[] = COFF_KNOWN_MACHINES;
-
-/* Number of valid entries (no sentinel) in array.  */
-
-#define NUM_COFF_KNOWN_MACHINES	\
-	(sizeof (coff_machine_array) / sizeof (coff_machine_array[0]))
-
-/* Cached object file header.  */
-
-static Coff_header cached_coff_hdr;
-
-/* Flag to indicate if we have read and cached any header yet.  */
-
-static bool cached_coff_hdr_valid = false;
-
-/* The current output file.  */
-
-static lto_file *current_out_file;
-
-
-/* Sets the current output file to FILE.  Returns the old output file or
-   NULL.  */
-
-lto_file *
-lto_set_current_out_file (lto_file *file)
-{
-  lto_file *old_file = current_out_file;
-  current_out_file = file;
-  return old_file;
-}
-
-
-/* Returns the current output file.  */
-
-lto_file *
-lto_get_current_out_file (void)
-{
-  return current_out_file;
-}
-
-
-/* COFF section structure constructor.  */
-
-static lto_coff_section *
-coff_newsection (lto_coff_file *file, const char *name, size_t type)
-{
-  lto_coff_section *ptr, **chain_ptr_ptr;
-
-  ptr = XCNEW (lto_coff_section);
-  ptr->name = name;
-  ptr->type = type;
-
-  chain_ptr_ptr = &file->section_chain;
-  while (*chain_ptr_ptr)
-    chain_ptr_ptr = &(*chain_ptr_ptr)->next;
-  *chain_ptr_ptr = ptr;
-
-  return ptr;
-}
-
-
-/* COFF section data block structure constructor.  */
-
-static lto_coff_data *
-coff_newdata (lto_coff_section *sec)
-{
-  lto_coff_data *ptr, **chain_ptr_ptr;
-
-  ptr = XCNEW (lto_coff_data);
-
-  chain_ptr_ptr = &sec->data_chain;
-  while (*chain_ptr_ptr)
-    chain_ptr_ptr = &(*chain_ptr_ptr)->next;
-  *chain_ptr_ptr = ptr;
-
-  return ptr;
-}
-
-
-/* Initialize FILE, an LTO file object for FILENAME.  */
-
-static void
-lto_file_init (lto_file *file, const char *filename, off_t offset)
-{
-  file->filename = filename;
-  file->offset = offset;
-}
-
-/* Build a hash table whose key is the section names and whose data is
-   the start and size of each section in the .o file.  */
-
-htab_t
-lto_obj_build_section_table (lto_file *lto_file) 
-{
-  lto_coff_file *coff_file = (lto_coff_file *)lto_file;
-  lto_coff_section *sec;
-  htab_t section_hash_table;
-  ssize_t strtab_size;
-  char *strtab;
-
-  section_hash_table = lto_obj_create_section_hash_table ();
-
-  /* Seek to start of string table.  */
-  if (coff_file->strtab_offs != lseek (coff_file->fd,
-		coff_file->base.offset + coff_file->strtab_offs, SEEK_SET))
-    {
-      error ("altered or invalid COFF object file");
-      return section_hash_table;
-    }
-
-  strtab_size = coff_file->file_size - coff_file->strtab_offs;
-  strtab = XNEWVEC (char, strtab_size);
-  if (read (coff_file->fd, strtab, strtab_size) != strtab_size)
-    {
-      error ("invalid COFF object file string table");
-      return section_hash_table;
-    }
-
-  /* Scan sections looking at names.  */
-  COFF_FOR_ALL_SECTIONS(coff_file, sec)
-    {
-      struct lto_section_slot s_slot;
-      void **slot;
-      char *new_name;
-      int stringoffset;
-      char *name = (char *) &sec->coffsec.Name[0];
-
-      /* Skip dummy string section if by any chance we see it.  */
-      if (sec->type == 1)
-	continue;
-
-      if (name[0] == '/')
-	{
-	  if (1 != sscanf (&name[1], "%d", &stringoffset)
-		|| stringoffset < 0 || stringoffset >= strtab_size)
-	    {
-	      error ("invalid COFF section name string");
-	      continue;
-	    }
-	  name = strtab + stringoffset;
-	}
-      else
-	{
-	  /* If we cared about the VirtualSize field, we couldn't
-	     crudely trash it like this to guarantee nul-termination
-	     of the Name field.  But we don't, so we do.  */
-	  name[8] = 0;
-	}
-      if (strncmp (name, LTO_SECTION_NAME_PREFIX,
-			strlen (LTO_SECTION_NAME_PREFIX)) != 0)
-	  continue;
-
-      new_name = XNEWVEC (char, strlen (name) + 1);
-      strcpy (new_name, name);
-      s_slot.name = new_name;
-      slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
-      if (*slot == NULL)
-	{
-	  struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
-
-	  new_slot->name = new_name;
-	  /* The offset into the file for this section.  */
-	  new_slot->start = coff_file->base.offset
-			+ COFF_GET(&sec->coffsec,PointerToRawData);
-	  new_slot->len = COFF_GET(&sec->coffsec,SizeOfRawData);
-	  *slot = new_slot;
-	}
-      else
-	{
-	  error ("two or more sections for %s:", new_name);
-	  return NULL;
-	}
-    }
-
-  free (strtab);
-  return section_hash_table;
-}
-
-
-/* Begin a new COFF section named NAME with type TYPE in the current output
-   file.  TYPE is an SHT_* macro from the libelf headers.  */
-
-static void
-lto_coff_begin_section_with_type (const char *name, size_t type)
-{
-  lto_coff_file *file;
-  size_t sh_name;
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_coff_file *) lto_get_current_out_file (),
-  gcc_assert (file);
-  gcc_assert (!file->scn);
-
-  /* Create a new section.  */
-  file->scn = coff_newsection (file, name, type);
-  if (!file->scn)
-    fatal_error ("could not create a new COFF section: %m");
-
-  /* Add a string table entry and record the offset.  */
-  gcc_assert (file->shstrtab_stream);
-  sh_name = file->shstrtab_stream->total_size;
-  lto_output_data_stream (file->shstrtab_stream, name, strlen (name) + 1);
-
-  /* Initialize the section header.  */
-  file->scn->strtab_offs = sh_name;
-}
-
-
-/* Begin a new COFF section named NAME in the current output file.  */
-
-void
-lto_obj_begin_section (const char *name)
-{
-  lto_coff_begin_section_with_type (name, 0);
-}
-
-
-/* Append DATA of length LEN to the current output section.  BASE is a pointer
-   to the output page containing DATA.  It is freed once the output file has
-   been written.  */
-
-void
-lto_obj_append_data (const void *data, size_t len, void *block)
-{
-  lto_coff_file *file;
-  lto_coff_data *coff_data;
-  struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block;
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_coff_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  coff_data = coff_newdata (file->scn);
-  if (!coff_data)
-    fatal_error ("could not append data to COFF section: %m");
-
-  coff_data->d_buf = CONST_CAST (void *, data);
-  coff_data->d_size = len;
-
-  /* Chain all data blocks (from all sections) on one singly-linked
-     list for freeing en masse after the file is closed.  */
-  base->ptr = (char *)file->data;
-  file->data = base;
-}
-
-
-/* End the current output section.  This just does some assertion checking
-   and sets the current output file's scn member to NULL.  */
-
-void
-lto_obj_end_section (void)
-{
-  lto_coff_file *file;
-
-  /* Grab the current output file and validate some basic assertions.  */
-  file = (lto_coff_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  file->scn = NULL;
-}
-
-
-/* Validate's COFF_FILE's executable header and, if cached_coff_hdr is
-   uninitialized, caches the results.  Also records the section header string
-   table's section index.  Returns true on success or false on failure.  */
-
-static bool
-validate_file (lto_coff_file *coff_file)
-{
-  size_t n, secnum;
-  unsigned int numsections, secheaderssize, numsyms;
-  off_t sectionsstart, symbolsstart, stringsstart;
-  unsigned int mach, charact;
-
-  /* Read and sanity check the raw header.  */
-  n = read (coff_file->fd, &coff_file->coffhdr, sizeof (coff_file->coffhdr));
-  if (n != sizeof (coff_file->coffhdr))
-    {
-      error ("not a COFF object file");
-      return false;
-    }
-
-  mach = COFF_GET(&coff_file->coffhdr, Machine);
-  for (n = 0; n < NUM_COFF_KNOWN_MACHINES; n++)
-    if (mach == coff_machine_array[n])
-      break;
-  if (n == NUM_COFF_KNOWN_MACHINES)
-    {
-      error ("not a recognized COFF object file");
-      return false;
-    }
-
-  charact = COFF_GET(&coff_file->coffhdr, Characteristics);
-  if (COFF_NOT_CHARACTERISTICS & charact)
-    {
-      /* DLL, EXE or SYS file.  */
-      error ("not a relocatable COFF object file");
-      return false;
-    }
-
-  if (mach != IMAGE_FILE_MACHINE_AMD64
-      && COFF_CHARACTERISTICS != (COFF_CHARACTERISTICS & charact))
-    {
-      /* ECOFF/XCOFF support not implemented.  */
-      error ("not a 32-bit COFF object file");
-      return false;
-    }
-
-  /* It validated OK, so cached it if we don't already have one.  */
-  if (!cached_coff_hdr_valid)
-    {
-      cached_coff_hdr_valid = true;
-      memcpy (&cached_coff_hdr, &coff_file->coffhdr, sizeof (cached_coff_hdr));
-    }
-
-  if (mach != COFF_GET(&cached_coff_hdr, Machine))
-    {
-      error ("inconsistent file architecture detected");
-      return false;
-    }
-
-  /* Read section headers and string table? */
-
-  numsections = COFF_GET(&coff_file->coffhdr, NumberOfSections);
-  secheaderssize = numsections * sizeof (Coff_section);
-  sectionsstart = sizeof (Coff_header) + secheaderssize;
-  symbolsstart = COFF_GET(&coff_file->coffhdr, PointerToSymbolTable);
-  numsyms = COFF_GET(&coff_file->coffhdr, NumberOfSymbols);
-  stringsstart = (symbolsstart + COFF_SYMBOL_SIZE * numsyms);
-
-#define CVOFFSETTTED(x) (coff_file->base.offset + (x))
-
-  if (numsections <= 0 || symbolsstart <= 0 || numsyms <= 0
-	|| (CVOFFSETTTED(sectionsstart) >= coff_file->file_size)
-	|| (CVOFFSETTTED(symbolsstart) >= coff_file->file_size)
-	|| (CVOFFSETTTED(stringsstart) >= coff_file->file_size))
-    {
-      error ("not a valid COFF object file");
-      return false;
-    }
-
-#undef CVOFFSETTTED
-
-  /* Record start of string table.  */
-  coff_file->strtab_offs = stringsstart;
-
-  /* Validate section table entries.  */
-  for (secnum = 0; secnum < numsections; secnum++)
-    {
-      Coff_section coffsec;
-      lto_coff_section *ltosec;
-      off_t size_raw, offs_raw, offs_relocs, offs_lines;
-      off_t num_relocs, num_lines;
-
-      n = read (coff_file->fd, &coffsec, sizeof (coffsec));
-      if (n != sizeof (coffsec))
-	{
-	  error ("short/missing COFF section table");
-	  return false;
-	}
-
-      size_raw = COFF_GET(&coffsec, SizeOfRawData);
-      offs_raw = COFF_GET(&coffsec, PointerToRawData);
-      offs_relocs = COFF_GET(&coffsec, PointerToRelocations);
-      offs_lines = COFF_GET(&coffsec, PointerToLinenumbers);
-      num_relocs = COFF_GET(&coffsec, NumberOfRelocations);
-      num_lines = COFF_GET(&coffsec, NumberOfLinenumbers);
-
-      if (size_raw < 0 || num_relocs < 0 || num_lines < 0
-	|| (size_raw
-	  && ((COFF_GET(&coffsec, Characteristics)
-	      & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
-	    ? (offs_raw != 0)
-	    : (offs_raw < sectionsstart || offs_raw >= coff_file->file_size)))
-	|| (num_relocs
-	  && (offs_relocs < sectionsstart
-	    || offs_relocs >= coff_file->file_size))
-	|| (num_lines
-	  && (offs_lines < sectionsstart
-	    || offs_lines >= coff_file->file_size)))
-	{
-	  error ("invalid COFF section table");
-	  return false;
-	}
-
-      /* Looks ok, so record its details.  We don't read the 
-         string table or set up names yet; we'll do that when
-	 we build the hash table.  */
-      ltosec = coff_newsection (coff_file, NULL, 0);
-      memcpy (&ltosec->coffsec, &coffsec, sizeof (ltosec->coffsec));
-    }
-
-  return true;
-}
-
-/* Initialize COFF_FILE's executable header using cached data from previously
-   read files.  */
-
-static void
-init_coffhdr (lto_coff_file *coff_file)
-{
-  gcc_assert (cached_coff_hdr_valid);
-  memset (&coff_file->coffhdr, 0, sizeof (coff_file->coffhdr));
-  COFF_PUT(&coff_file->coffhdr, Machine, COFF_GET(&cached_coff_hdr, Machine));
-  COFF_PUT(&coff_file->coffhdr, Characteristics, COFF_GET(&cached_coff_hdr, Characteristics));
-}
-
-/* Open COFF file FILENAME.  If WRITABLE is true, the file is opened for write
-   and, if necessary, created.  Otherwise, the file is opened for reading.
-   Returns the opened file.  */
-
-lto_file *
-lto_obj_file_open (const char *filename, bool writable)
-{
-  lto_coff_file *coff_file;
-  lto_file *result = NULL;
-  off_t offset;
-  const char *offset_p;
-  char *fname;
-  struct stat statbuf;
-
-  offset_p = strchr (filename, '@');
-  if (!offset_p)
-    {
-      fname = xstrdup (filename);
-      offset = 0;
-    }
-  else
-    {
-      /* The file started with '@' is a file containing command line
-	 options.  Stop if it doesn't exist.  */
-      if (offset_p == filename)
-	fatal_error ("command line option file '%s' does not exist",
-		     filename);
-
-      fname = (char *) xmalloc (offset_p - filename + 1);
-      memcpy (fname, filename, offset_p - filename);
-      fname[offset_p - filename] = '\0';
-      offset_p += 3; /* skip the @0x */
-      offset = lto_parse_hex (offset_p);
-    }
-
-  /* Set up.  */
-  coff_file = XCNEW (lto_coff_file);
-  result = (lto_file *) coff_file;
-  lto_file_init (result, fname, offset);
-  coff_file->fd = -1;
-
-  /* Open the file.  */
-  coff_file->fd = open (fname,
-    O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666);
-
-  if (coff_file->fd == -1)
-    {
-      error ("could not open file %s", fname);
-      goto fail;
-    }
-
-  if (stat (fname, &statbuf) < 0)
-    {
-      error ("could not stat file %s", fname);
-      goto fail;
-    }
-
-  coff_file->file_size = statbuf.st_size;
-
-  if (offset != 0)
-    {
-      char ar_tail[12];
-      int size;
-
-      /* Surely not?  */
-      gcc_assert (!writable);
-
-      /* Seek to offset, or error.  */
-      if (lseek (coff_file->fd, offset, SEEK_SET) != (ssize_t) offset)
-	{
-	  error ("could not find archive member @0x%lx", (long) offset);
-	  goto fail;
-	}
-
-      /* Now seek back 12 chars and read the tail of the AR header to
-         find the length of the member file.  */
-      if (lseek (coff_file->fd, -12, SEEK_CUR) < 0
-	  || read (coff_file->fd, ar_tail, 12) != 12
-	  || lseek (coff_file->fd, 0, SEEK_CUR) != (ssize_t) offset
-	  || ar_tail[10] != '`' || ar_tail[11] != '\n')
-	{
-	  error ("could not find archive header @0x%lx", (long) offset);
-	  goto fail;
-	}
-
-      ar_tail[11] = 0;
-      if (sscanf (ar_tail, "%d", &size) != 1)
-	{
-	  error ("invalid archive header @0x%lx", (long) offset);
-	  goto fail;
-	}
-      coff_file->file_size = size;
-    }
-
-  if (writable)
-    {
-      init_coffhdr (coff_file);
-      coff_file->shstrtab_stream = XCNEW (struct lto_output_stream);
-    }
-  else
-    if (!validate_file (coff_file))
-      goto fail;
-
-  return result;
-
- fail:
-  if (result)
-    lto_obj_file_close (result);
-  return NULL;
-}
-
-
-/* Close COFF file FILE and clean up any associated data structures.  If FILE
-   was opened for writing, the file's COFF data is written at this time, and
-   any cached data buffers are freed.  Return TRUE if there was an error.  */
-
-static bool
-coff_write_object_file (lto_coff_file *coff_file)
-{
-  lto_coff_section *cursec, *stringsec;
-  lto_coff_data *data;
-  size_t fileoffset, numsections, totalsecsize, numsyms, stringssize;
-  bool write_err = false;
-  int secnum;
-
-  /* Infer whether this file was opened for reading or writing from the
-     presence or absense of an initialised stream for the string table;
-     do nothing if it was opened for reading.  */
-  if (!coff_file->shstrtab_stream)
-    return false;
-  else
-    {
-      /* Write the COFF string table into a dummy new section that
-	 we will not write a header for.  */
-      lto_file *old_file = lto_set_current_out_file (&coff_file->base);
-      /* This recursively feeds in the data to a new section.  */
-      lto_coff_begin_section_with_type (".strtab", 1);
-      lto_write_stream (coff_file->shstrtab_stream);
-      lto_obj_end_section ();
-      lto_set_current_out_file (old_file);
-      free (coff_file->shstrtab_stream);
-    }
-
-  /* Layout the file.  Count sections (not dummy string section) and calculate
-     data size for all of them.  */
-  numsections = 0;
-  totalsecsize = 0;
-  stringssize = 0;
-  stringsec = NULL;
-  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
-    {
-      lto_coff_data *data;
-      size_t cursecsize;
-      cursecsize = 0;
-      COFF_FOR_ALL_DATA(cursec,data)
-	cursecsize += data->d_size;
-      if (cursec->type == 0)
-	{
-	  ++numsections;
-	  totalsecsize += COFF_ALIGN(cursecsize);
-#if COFF_ALIGNMENT > 1
-	  cursec->pad_needed = COFF_ALIGN(cursecsize) - cursecsize;
-#endif
-	}
-      else
-        {
-	  stringssize = cursecsize;
-	  stringsec = cursec;
-	}
-      COFF_PUT(&cursec->coffsec, SizeOfRawData, cursecsize);
-    }
-
-  /* There is a file symbol and a section symbol per section,
-     and each of these has a single auxiliary symbol following.  */
-  numsyms = 2 * (1 + numsections);
-
-  /* Great!  Now we have enough info to fill out the file header.  */
-  COFF_PUT(&coff_file->coffhdr, NumberOfSections, numsections);
-  COFF_PUT(&coff_file->coffhdr, NumberOfSymbols, numsyms);
-  COFF_PUT(&coff_file->coffhdr, PointerToSymbolTable, sizeof (Coff_header)
-		+ numsections * sizeof (Coff_section) + totalsecsize);
-  /* The remaining members were initialised to zero or copied from
-     a cached header, so we leave them alone here.  */
-
-  /* Now position all the sections, and fill out their headers.  */
-  fileoffset = sizeof (Coff_header) + numsections * sizeof (Coff_section);
-  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
-    {
-      /* Skip dummy string section.  */
-      if (cursec->type == 1)
-	continue;
-      COFF_PUT(&cursec->coffsec, PointerToRawData, fileoffset);
-      fileoffset += COFF_ALIGN (COFF_GET(&cursec->coffsec, SizeOfRawData));
-      COFF_PUT(&cursec->coffsec, Characteristics, COFF_SECTION_CHARACTERISTICS);
-      snprintf ((char *)&cursec->coffsec.Name[0], 8, "/%d", cursec->strtab_offs + 4);
-    }
-
-  /* We can write the data now.  As there's no way to indicate an error return
-     from this hook, error handling is limited to not wasting our time doing
-     any more writes in the event that any one fails.  */
-
-  /* Write the COFF header.  */
-  write_err = (write (coff_file->fd, &coff_file->coffhdr,
-		sizeof (coff_file->coffhdr)) != sizeof (coff_file->coffhdr));
-
-  /* Write the COFF section headers.  */
-  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
-    if (cursec->type == 1)	/* Skip dummy string section.  */
-	continue;
-    else if (!write_err)
-      write_err = (write (coff_file->fd, &cursec->coffsec,
-		sizeof (cursec->coffsec)) != sizeof (cursec->coffsec));
-    else
-      break;
-
-  /* Write the COFF sections.  */
-  COFF_FOR_ALL_SECTIONS(coff_file, cursec)
-    {
-#if COFF_ALIGNMENT > 1
-      static const char padzeros[COFF_ALIGNMENT] = { 0 };
-#endif
-      /* Skip dummy string section.  */
-      if (cursec->type == 1)
-	continue;
-      COFF_FOR_ALL_DATA(cursec, data)
-	if (!write_err)
-	  write_err = (write (coff_file->fd, data->d_buf, data->d_size)
-		!= data->d_size);
-	else
-	  break;
-#if COFF_ALIGNMENT > 1
-      if (!write_err && cursec->pad_needed)
-	write_err = (write (coff_file->fd, padzeros, cursec->pad_needed)
-		!= cursec->pad_needed);
-#endif
-    }
-
-  /* Write the COFF symbol table.  */
-  if (!write_err)
-    {
-      union
-	{
-	  Coff_symbol sym;
-	  Coff_aux_sym_file file;
-	  Coff_aux_sym_section sec;
-	} symbols[2];
-      memset (&symbols[0], 0, sizeof (symbols));
-      strcpy ((char *) &symbols[0].sym.Name[0], ".file");
-      COFF_PUT(&symbols[0].sym, SectionNumber, IMAGE_SYM_DEBUG);
-      COFF_PUT(&symbols[0].sym, Type, IMAGE_SYM_TYPE);
-      symbols[0].sym.StorageClass[0] = IMAGE_SYM_CLASS_FILE;
-      symbols[0].sym.NumberOfAuxSymbols[0] = 1;
-      snprintf ((char *)symbols[1].file.FileName,
-		sizeof (symbols[1].file.FileName),
-		"%s", lbasename (coff_file->base.filename));
-      write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
-		!= (2 * COFF_SYMBOL_SIZE));
-
-      /* Set up constant parts for section sym loop.  */
-      memset (&symbols[0], 0, sizeof (symbols));
-      COFF_PUT(&symbols[0].sym, Type, IMAGE_SYM_TYPE);
-      symbols[0].sym.StorageClass[0] = IMAGE_SYM_CLASS_STATIC;
-      symbols[0].sym.NumberOfAuxSymbols[0] = 1;
-
-      secnum = 1;
-      if (!write_err)
-	COFF_FOR_ALL_SECTIONS(coff_file, cursec)
-	  {
-	    /* Skip dummy string section.  */
-	    if (cursec->type == 1)
-	      continue;
-	    /* Reuse section name string for section symbol name.  */
-	    COFF_PUT_NDXSZ(&symbols[0].sym, Name, 0, 0, 4);
-	    COFF_PUT_NDXSZ(&symbols[0].sym, Name, cursec->strtab_offs + 4, 4, 4);
-	    COFF_PUT(&symbols[0].sym, SectionNumber, secnum++);
-	    COFF_PUT(&symbols[1].sec, Length,
-			COFF_GET(&cursec->coffsec, SizeOfRawData));
-	    if (!write_err)
-	      write_err = (write (coff_file->fd, &symbols[0], sizeof (symbols))
-			!= (2 * COFF_SYMBOL_SIZE));
-	    else
-	      break;
-	  }
-    }
-
-  /* Write the COFF string table.  */
-  if (!write_err)
-    {
-      unsigned char outlen[4];
-      COFF_PUT4(outlen, stringssize + 4);
-      if (!write_err)
-	write_err = (write (coff_file->fd, outlen, 4) != 4);
-      if (stringsec)
-	{
-	  COFF_FOR_ALL_DATA(stringsec, data)
-	    if (!write_err)
-	      write_err = (write (coff_file->fd, data->d_buf, data->d_size)
-			   != data->d_size);
-	    else
-	      break;
-	}
-    }
-
-  return write_err;
-}
-
-/* Close COFF file FILE and clean up any associated data structures.  If FILE
-   was opened for writing, the file's COFF data is written at this time, and
-   any cached data buffers are freed.  */
-
-void
-lto_obj_file_close (lto_file *file)
-{
-  lto_coff_file *coff_file = (lto_coff_file *) file;
-  struct lto_char_ptr_base *cur, *tmp;
-  lto_coff_section *cursec, *nextsec;
-  bool write_err = false;
-
-  /* Write the COFF string table into a dummy new section that
-     we will not write a header for.  */
-  if (coff_file->shstrtab_stream)
-    coff_write_object_file (coff_file);
-
-  /* Close the file, we're done.  */
-  if (coff_file->fd != -1)
-    close (coff_file->fd);
-
-  /* Free any data buffers.  */
-  cur = coff_file->data;
-  while (cur)
-    {
-      tmp = cur;
-      cur = (struct lto_char_ptr_base *) cur->ptr;
-      free (tmp);
-    }
-
-  /* Free any sections and their data chains.  */
-  cursec = coff_file->section_chain;
-  while (cursec)
-    {
-      lto_coff_data *curdata, *nextdata;
-      nextsec = cursec->next;
-      curdata = cursec->data_chain;
-      while (curdata)
-	{
-	  nextdata = curdata->next;
-	  free (curdata);
-	  curdata = nextdata;
-	}
-      free (cursec);
-      cursec = nextsec;
-    }
-
-  free (file);
-
-  /* If there was an error, mention it.  */
-  if (write_err)
-    error ("I/O error writing COFF output file");
-}
-
Index: gcc/lto/lto-coff.h
===================================================================
--- gcc/lto/lto-coff.h	(revision 166080)
+++ gcc/lto/lto-coff.h	(working copy)
@@ -1,408 +0,0 @@
-/* LTO routines for COFF object files.
-   Copyright 2009 Free Software Foundation, Inc.
-   Contributed by Dave Korn.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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 GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#ifndef LTO_COFF_H
-#define LTO_COFF_H
-
-/* Rather than implementing a libcoff to match libelf, or attempting to
-   integrate libbfd into GCC, this file is a self-contained (and very
-   minimal) COFF format object file reader/writer.  The generated files
-   will contain a COFF header, a number of COFF section headers, the 
-   section data itself, and a trailing string table for section names.  */
-
-/* Alignment of sections in a COFF object file.
-
-   The LTO writer uses zlib compression on the data that it streams into
-   LTO sections in the output object file.  Because these streams don't
-   have any embedded size information, the section in the object file must
-   be exactly sized to the data emitted; any trailing padding bytes will
-   be interpreted as partial and/or corrupt compressed data.
-
-   This is easy enough to do on COFF targets (with binutils 2.20.1 or
-   above) because we can specify 1-byte alignment for the LTO sections.
-   They are then emitted precisely-sized and byte-packed into the object
-   and the reader is happy when it parses them later.  This is currently
-   implemented in the x86/windows backed in i386_pe_asm_named_section()
-   in config/i386/winnt.c by detecting the LTO section name prefix, 
-
-   That would be sufficient, but for one thing.  At the start of the LTO
-   data is a header struct with (currently) a couple of version numbers and
-   some type info; see struct lto_header in lto-streamer.h.  If the sections
-   are byte-packed, this header will not necessarily be correctly-aligned
-   when it is read back into memory.
-
-   On x86 targets, which are currently the only LTO-COFF targets, misaligned
-   memory accesses aren't problematic (okay, inefficient, but not worth
-   worrying about two half-word memory reads per section in the context of
-   everything else the compiler has to do at the time!), but RISC targets may
-   fail on trying to access the header struct.  In this case, it will be
-   necessary to enable (preferably in a target-dependent fashion, but a few
-   bytes of padding are hardly an important issue if it comes down to it) the
-   COFF_ALIGNMENT macros below.
-
-   As currently implemented, this will emit padding to the necessary number
-   of bytes after each LTO section.  These bytes will constitute 'gaps' in
-   the object file structure, as they won't be covered by any section header.
-   This hasn't yet been tested, because no such RISC LTO-COFF target yet
-   exists.  If it causes problems further down the toolchain, it will be
-   necessary to adapt the code to emit additional section headers for these
-   padding bytes, but the odds are that it will "just work".
-
-  */
-
-#if 0
-#define COFF_ALIGNMENT	 (4)
-#define COFF_ALIGNMENTM1 (COFF_ALIGNMENT - 1)
-#define COFF_ALIGN(x)	 (((x) + COFF_ALIGNMENTM1) & ~COFF_ALIGNMENTM1)
-#else
-#define COFF_ALIGNMENT	 (1)
-#define COFF_ALIGN(x)	 (x)
-#endif
-
-/* COFF header machine codes.  */
-
-#define IMAGE_FILE_MACHINE_I386	(0x014c)
-#define IMAGE_FILE_MACHINE_AMD64 (0x8664)
-
-/* Known header magics for validation, as an array initialiser.  */
-
-#define COFF_KNOWN_MACHINES \
-  { IMAGE_FILE_MACHINE_I386, \
-    IMAGE_FILE_MACHINE_AMD64/*, ... add more here when working.  */ }
-
-/* COFF object file header, section and symbol flags and types.  These are
-   currently specific to PE-COFF, which is the only LTO-COFF format at the
-   time of writing.  Maintainers adding support for new COFF formats will
-   need to make these into target macros of some kind.  */
-
-/* COFF header characteristics.  */
-
-#define IMAGE_FILE_EXECUTABLE_IMAGE	(1 << 1)
-#define IMAGE_FILE_32BIT_MACHINE	(1 << 8)
-#define IMAGE_FILE_SYSTEM		(1 << 12)
-#define IMAGE_FILE_DLL			(1 << 13)
-
-/* Desired characteristics (for validation).  */
-
-#define COFF_CHARACTERISTICS \
-  (IMAGE_FILE_32BIT_MACHINE)
-
-/* Unwanted characteristics (for validation).  */
-
-#define COFF_NOT_CHARACTERISTICS \
-  (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL)
-
-/* Section flags.  LTO emits byte-aligned read-only loadable data sections.  */
-
-#define IMAGE_SCN_CNT_INITIALIZED_DATA	 (1 << 6)
-#define IMAGE_SCN_CNT_UNINITIALIZED_DATA (1 << 7)
-#define IMAGE_SCN_ALIGN_1BYTES		 (0x1 << 20)
-#define IMAGE_SCN_MEM_DISCARDABLE	 (1 << 25)
-#define	IMAGE_SCN_MEM_SHARED		 (1 << 28)
-#define IMAGE_SCN_MEM_READ		 (1 << 30)
-
-#define COFF_SECTION_CHARACTERISTICS \
-  (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_1BYTES | \
-  IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ)
-
-/* Symbol-related constants.  */
-
-#define IMAGE_SYM_DEBUG		(-2)
-#define IMAGE_SYM_TYPE_NULL	(0)
-#define IMAGE_SYM_DTYPE_NULL	(0)
-#define IMAGE_SYM_CLASS_STATIC	(3)
-#define IMAGE_SYM_CLASS_FILE	(103)
-
-#define IMAGE_SYM_TYPE \
-  ((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL)
-
-/* Size of a COFF symbol in bytes.  */
-
-#define COFF_SYMBOL_SIZE	(18)
-
-/* On-disk file structures.  */
-
-struct Coff_header
-{
-  unsigned char Machine[2];
-  unsigned char NumberOfSections[2];
-  unsigned char TimeDateStamp[4];
-  unsigned char PointerToSymbolTable[4];
-  unsigned char NumberOfSymbols[4];
-  unsigned char SizeOfOptionalHeader[2];
-  unsigned char Characteristics[2];
-};
-typedef struct Coff_header Coff_header;
-
-struct Coff_section
-{
-  unsigned char Name[8];
-  unsigned char VirtualSize[4];
-  unsigned char VirtualAddress[4];
-  unsigned char SizeOfRawData[4];
-  unsigned char PointerToRawData[4];
-  unsigned char PointerToRelocations[4];
-  unsigned char PointerToLinenumbers[4];
-  unsigned char NumberOfRelocations[2];
-  unsigned char NumberOfLinenumbers[2];
-  unsigned char Characteristics[4];
-};
-typedef struct Coff_section Coff_section;
-
-struct Coff_symbol
-{
-  unsigned char Name[8];
-  unsigned char Value[4];
-  unsigned char SectionNumber[2];
-  unsigned char Type[2];
-  unsigned char StorageClass[1];
-  unsigned char NumberOfAuxSymbols[1];
-};
-typedef struct Coff_symbol Coff_symbol;
-
-struct Coff_aux_sym_file
-{
-  unsigned char FileName[18];
-};
-typedef struct Coff_aux_sym_file Coff_aux_sym_file;
-
-struct Coff_aux_sym_section
-{
-  unsigned char Length[4];
-  unsigned char NumberOfRelocations[2];
-  unsigned char NumberOfLineNumbers[2];
-  unsigned char Checksum[4];
-  unsigned char Number[2];
-  unsigned char Selection[1];
-  unsigned char Unused[3];
-};
-typedef struct Coff_aux_sym_section Coff_aux_sym_section;
-
-/* Accessor macros for the above structures.  */
-
-#define COFF_GET(struc,memb) \
-  ((COFFENDIAN ? get_be : get_le) (&(struc)->memb[0], sizeof ((struc)->memb)))
-
-#define COFF_PUT(struc,memb,val) \
-  ((COFFENDIAN ? put_be : put_le) (&(struc)->memb[0], sizeof ((struc)->memb), val))
-
-#define COFF_PUT_NDXSZ(struc,memb,val,ndx,sz) \
-  ((COFFENDIAN ? put_be : put_le) (&(struc)->memb[ndx], sz, val))
-
-/* In-memory file structures.  */
-
-/* Forward declared structs.  */
-
-struct lto_coff_data;
-struct lto_coff_section;
-struct lto_coff_file;
-
-/* Section data in output files is made of these.  */
-
-struct lto_coff_data
-{
-  /* Pointer to data block.  */
-  void *d_buf;
-
-  /* Size of data block.  */
-  ssize_t d_size;
-
-  /* Next data block for this section.  */
-  struct lto_coff_data *next;
-};
-typedef struct lto_coff_data lto_coff_data;
-
-/* This struct tracks the data for a section.  */
-
-struct lto_coff_section
-{
-  /* Singly-linked list of section's data blocks.  */
-  lto_coff_data *data_chain;
-
-  /* Offset in string table of name.  */
-  size_t strtab_offs;
-
-  /* Section type: 0 = real, 1 = dummy.  */
-  size_t type;
-
-  /* Section name.  */
-  const char *name;
-
-#if COFF_ALIGNMENT > 1
-  /* Number of trailing padding bytes needed.  */
-  ssize_t pad_needed;
-#endif
-
-  /* Raw section header data.  */
-  Coff_section coffsec;
-
-  /* Next section for this file.  */
-  struct lto_coff_section *next;
-};
-typedef struct lto_coff_section lto_coff_section;
-
-/* A COFF file.  */
-
-struct lto_coff_file 
-{
-  /* The base information.  */
-  lto_file base;
-
-  /* Common file members:  */
-
-  /* The system file descriptor for the file.  */
-  int fd;
-
-  /* The file's overall header.  */
-  Coff_header coffhdr;
-
-  /* All sections in a singly-linked list.  */
-  lto_coff_section *section_chain;
-
-  /* Readable file members:  */
-
-  /* File total size.  */
-  off_t file_size;
-
-  /* String table file offset, relative to base.offset.  */
-  off_t strtab_offs;
-
-  /* Writable file members:  */
-
-  /* The currently active section.  */
-  lto_coff_section *scn;
-
-  /* The output stream for section header names.  */
-  struct lto_output_stream *shstrtab_stream;
-
-  /* Linked list of data which must be freed *after* the file has been
-     closed.  This is an annoying limitation of libelf.  Which has been
-     faithfully reproduced here.  */
-  struct lto_char_ptr_base *data;
-};
-typedef struct lto_coff_file lto_coff_file;
-
-/* Data hunk iterator.  */
-
-#define COFF_FOR_ALL_DATA(sec,var) \
-  for (var = sec->data_chain; var; var = var->next)
-
-/* Section list iterator.  */
-
-#define COFF_FOR_ALL_SECTIONS(file,var) \
-  for (var = file->section_chain; var; var = var->next)
-
-/* Very simple endian-ness layer.  */
-
-#ifndef COFFENDIAN
-#define COFFENDIAN (BYTES_BIG_ENDIAN)
-#endif
-
-static inline unsigned int
-get_2_le (const unsigned char *ptr)
-{
-  return ptr[0] | (ptr[1] << 8);
-}
-
-static inline unsigned int
-get_4_le (const unsigned char *ptr)
-{
-  return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
-}
-
-static inline unsigned int
-get_2_be (const unsigned char *ptr)
-{
-  return ptr[1] | (ptr[0] << 8);
-}
-
-static inline unsigned int
-get_4_be (const unsigned char *ptr)
-{
-  return ptr[3] | (ptr[2] << 8) | (ptr[1] << 16) | (ptr[0] << 24);
-}
-
-static inline unsigned int
-get_be (const unsigned char *ptr, size_t size)
-{
-  gcc_assert (size == 4 || size == 2);
-  return (size == 2) ? get_2_be (ptr) : get_4_be (ptr);
-}
-
-static inline unsigned int
-get_le (const unsigned char *ptr, size_t size)
-{
-  gcc_assert (size == 4 || size == 2);
-  return (size == 2) ? get_2_le (ptr) : get_4_le (ptr);
-}
-
-static inline void
-put_2_le (unsigned char *ptr, unsigned int data)
-{
-  ptr[0] = data & 0xff;
-  ptr[1] = (data >> 8) & 0xff;
-}
-
-static inline void
-put_4_le (unsigned char *ptr, unsigned int data)
-{
-  ptr[0] = data & 0xff;
-  ptr[1] = (data >> 8) & 0xff;
-  ptr[2] = (data >> 16) & 0xff;
-  ptr[3] = (data >> 24) & 0xff;
-}
-
-static inline void
-put_2_be (unsigned char *ptr, unsigned int data)
-{
-  ptr[1] = data & 0xff;
-  ptr[0] = (data >> 8) & 0xff;
-}
-
-static inline void
-put_4_be (unsigned char *ptr, unsigned int data)
-{
-  ptr[3] = data & 0xff;
-  ptr[2] = (data >> 8) & 0xff;
-  ptr[1] = (data >> 16) & 0xff;
-  ptr[0] = (data >> 24) & 0xff;
-}
-
-static inline void
-put_le (unsigned char *ptr, size_t size, unsigned int data)
-{
-  gcc_assert (size == 4 || size == 2);
-  (void) (size == 2 ? put_2_le : put_4_le) (ptr, data);
-}
-
-static inline void
-put_be (unsigned char *ptr, size_t size, unsigned int data)
-{
-  gcc_assert (size == 4 || size == 2);
-  (void) (size == 2 ? put_2_be : put_4_be) (ptr, data);
-}
-
-/* We use this for putting the string table size.  */
-
-#define COFF_PUT4(ptr, data) \
-  ((COFFENDIAN ? put_4_be : put_4_le) (ptr, data))
-
-
-#endif /* LTO_COFF_H */
Index: gcc/lto/Make-lang.in
===================================================================
--- gcc/lto/Make-lang.in	(revision 166080)
+++ gcc/lto/Make-lang.in	(working copy)
@@ -23,7 +23,7 @@
 # The name of the LTO compiler.
 LTO_EXE = lto1$(exeext)
 # The LTO-specific object files inclued in $(LTO_EXE).
-LTO_OBJS = lto/lto-lang.o lto/lto.o lto/$(LTO_BINARY_READER).o attribs.o
+LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-object.o attribs.o
 LTO_H = lto/lto.h $(HASHTAB_H)
 LINKER_PLUGIN_API_H = $(srcdir)/../include/plugin-api.h
 LTO_TREE_H = lto/lto-tree.h $(LINKER_PLUGIN_API_H)
@@ -73,7 +73,7 @@ lto-warn = $(STRICT_WARN)
 
 $(LTO_EXE): $(LTO_OBJS) $(BACKEND) $(LIBDEPS)
 	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
-		$(LTO_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS) $(LTO_USE_LIBELF)
+		$(LTO_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS)
 
 # Dependencies
 lto/lto-lang.o: lto/lto-lang.c $(CONFIG_H) coretypes.h debug.h \
@@ -81,19 +81,14 @@ lto/lto-lang.o: lto/lto-lang.c $(CONFIG_
 	$(TARGET_H) $(LTO_H) $(GIMPLE_H) gtype-lto.h gt-lto-lto-lang.h \
 	$(EXPR_H)
 lto/lto.o: lto/lto.c $(CONFIG_H) $(SYSTEM_H) coretypes.h opts.h \
-	toplev.h $(TREE_H) $(DIAGNOSTIC_CORE_H) $(TM_H) $(LIBIBERTY_H) \
+	toplev.h $(TREE_H) $(DIAGNOSTIC_CORE_H) $(TM_H) \
 	$(CGRAPH_H) $(GGC_H) tree-ssa-operands.h $(TREE_PASS_H) \
 	langhooks.h $(VEC_H) $(BITMAP_H) pointer-set.h $(IPA_PROP_H) \
 	$(COMMON_H) debug.h $(TIMEVAR_H) $(GIMPLE_H) $(LTO_H) $(LTO_TREE_H) \
 	$(LTO_TAGS_H) $(LTO_STREAMER_H) $(SPLAY_TREE_H) gt-lto-lto.h $(PARAMS_H)
-lto/lto-elf.o: lto/lto-elf.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
-	toplev.h $(LTO_H) $(TM_H) $(LIBIBERTY_H) $(GGC_H) $(LTO_STREAMER_H)
-lto/lto-coff.o: lto/lto-coff.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
-	toplev.h $(LTO_H) $(TM_H) $(LIBIBERTY_H) $(GGC_H) $(LTO_STREAMER_H) \
-	lto/lto-coff.h
-lto/lto-macho.o: lto/lto-macho.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
-	toplev.h $(LTO_H) $(TM_H) $(LIBIBERTY_H) $(GGC_H) $(LTO_STREAMER_H) \
-	lto/lto-macho.h lto/lto-endian.h
+lto/lto-object.o: lto/lto-object.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+	$(DIAGNOSTIC_CORE_H) $(TOPLEV_H) $(LTO_H) $(TM_H) $(LTO_STREAMER_H) \
+	../include/simple-object.h
 
 # LTO testing is done as part of C/C++/Fortran etc. testing.
 check-lto:
Index: gcc/lto/lto-macho.c
===================================================================
--- gcc/lto/lto-macho.c	(revision 166080)
+++ gcc/lto/lto-macho.c	(working copy)
@@ -1,948 +0,0 @@
-/* LTO routines for Mach-O object files.
-   Copyright 2010 Free Software Foundation, Inc.
-   Contributed by Steven Bosscher.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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 GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "diagnostic-core.h"
-#include "toplev.h"
-#include "lto.h"
-#include "tm.h"
-#include "libiberty.h"
-#include "lto-streamer.h"
-#include "lto/lto-endian.h"
-#include "lto/lto-macho.h"
-
-/* Rather than implementing a libmacho to match libelf, or attempting to
-   integrate libbfd into GCC, this file is a self-contained (and very
-   minimal) Mach-O format object file reader/writer.  The generated files
-   will contain a Mach-O header, a number of Mach-O load commands an
-   section headers, the  section data itself, and a trailing string table
-   for section names.  */
-
-/* This needs to be kept in sync with darwin.c.  Better yet, lto-macho.c
-   and lto-macho.h should be moved to config/, and likewise for lto-coff.*
-   and lto-elf.*.  */
-
-/* Segment name for LTO sections.  */
-#define LTO_SEGMENT_NAME "__GNU_LTO"
-
-/* Section name for LTO section names section.  */
-#define LTO_NAMES_SECTION "__section_names"
-
-/* Handle opening elf files on hosts, such as Windows, that may use 
-   text file handling that will break binary access.  */
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-/* Cached object file header.  We use a header_64 for this, since all
-   the fields we need are in there, in the same position as header_32.  */
-mach_o_header_64 cached_mach_o_header;
-uint32_t cached_mach_o_magic;
-
-/* The current output file.  */
-static lto_file *current_out_file;
-
-
-/* Is this a 32-bits or 64-bits Mach-O object file?  */
-static int
-mach_o_word_size (void)
-{
-  gcc_assert (cached_mach_o_magic != 0);
-  return (cached_mach_o_magic == MACH_O_MH_MAGIC_64
-	  || cached_mach_o_magic == MACH_O_MH_CIGAM_64) ? 64 : 32;
-}
-
-/* Sets the current output file to FILE.  Returns the old output file or
-   NULL.  */
-
-lto_file *
-lto_set_current_out_file (lto_file *file)
-{
-  lto_file *old_file = current_out_file;
-  current_out_file = file;
-  return old_file;
-}
-
-
-/* Returns the current output file.  */
-
-lto_file *
-lto_get_current_out_file (void)
-{
-  return current_out_file;
-}
-
-/* Mach-O section structure constructor.  */
-
-static lto_mach_o_section
-mach_o_new_section (lto_mach_o_file *mach_o_file, const char *name)
-{
-  lto_mach_o_section ptr;
-
-  /* FIXME We could allocate these things on an obstack.  */
-  ptr = XCNEW (struct lto_mach_o_section_d);
-  if (name)
-    {
-      if (strncmp (name, LTO_SECTION_NAME_PREFIX,
-		   strlen(LTO_SECTION_NAME_PREFIX)) != 0)
-	sorry ("not implemented: Mach-O writer for non-LTO sections");
-      ptr->name = xstrdup (name);
-    }
-
-  VEC_safe_push (lto_mach_o_section, heap, mach_o_file->section_vec, ptr);
-
-  return ptr;
-}
-
-/* Mach-O section data block structure constructor.  */
-
-static lto_mach_o_data
-mach_o_new_data (lto_mach_o_section sec)
-{
-  lto_mach_o_data ptr, *chain_ptr_ptr;
-
-  /* FIXME We could allocate these things on an obstack.  */
-  ptr = XCNEW (struct lto_mach_o_data_d);
-
-  chain_ptr_ptr = &sec->data_chain;
-  while (*chain_ptr_ptr)
-    chain_ptr_ptr = &(*chain_ptr_ptr)->next;
-  *chain_ptr_ptr = ptr;
-
-  return ptr;
-}
-
-/* Initialize FILE, an LTO file object for FILENAME.  Offset is the
-   offset into FILE where the object is located (e.g. in an archive).  */
-
-static void
-lto_file_init (lto_file *file, const char *filename, off_t offset)
-{
-  file->filename = filename;
-  file->offset = offset;
-}
-
-/* Build a hash table whose key is the section names and whose data is
-   the start and size of each section in the .o file.  */
-
-htab_t
-lto_obj_build_section_table (lto_file *lto_file) 
-{
-  lto_mach_o_file *mach_o_file = (lto_mach_o_file *)lto_file;
-  lto_mach_o_section sec;
-  htab_t section_hash_table;
-  off_t strtab_offs;
-  ssize_t strtab_size;
-  char *strtab = NULL;
-  int i;
-
-  section_hash_table = lto_obj_create_section_hash_table ();
-
-  /* Seek the string table.  */
-  /* FIXME The segment name should be in darwin.h, but can we include it
-     here in this file?  */
-  for (i = 0;
-       VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    {
-      if (strncmp (sec->u.section.segname, "__GNU_LTO", 16) != 0)
-	continue;
-      if (strncmp (sec->u.section.sectname, "__section_names", 16) == 0)
-        break;
-    }
-  if (! sec)
-    {
-      error ("invalid Mach-O LTO object file: no __section_names section found");
-      goto done;
-    }
-  mach_o_file->section_names_section = sec;
-
-  if (mach_o_word_size () == 64)
-    {
-      strtab_offs = (off_t) get_uint32 (&sec->u.section_64.offset[0]);
-      strtab_size = (size_t) get_uint64 (&sec->u.section_64.size[0]);
-    }
-  else
-    {
-      strtab_offs = (off_t) get_uint32 (&sec->u.section_32.offset[0]);
-      strtab_size = (size_t) get_uint32 (&sec->u.section_32.size[0]);
-    }
-
-  /* Seek to start of string table.  */
-  if (strtab_offs != lseek (mach_o_file->fd,
-			    mach_o_file->base.offset + strtab_offs,
-			    SEEK_SET))
-    {
-      error ("altered or invalid Mach-O object file");
-      goto done;
-    }
-
-  strtab = XNEWVEC (char, strtab_size);
-  if (read (mach_o_file->fd, strtab, strtab_size) != strtab_size)
-    {
-      error ("invalid Mach-O LTO object file __section_names section");
-      goto done;
-    }
-
-  /* Scan sections looking at names.  */
-  for (i = 0;
-       VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    {
-      struct lto_section_slot s_slot;
-      void **slot;
-      char *new_name;
-      unsigned long stringoffset;
-      char name[17];
-
-      /* Ignore non-LTO sections.  Also ignore the __section_names section
-	 which does not need renaming.  */
-      if (strncmp (sec->u.section.segname, "__GNU_LTO", 16) != 0)
-	continue;
-      if (sec == mach_o_file->section_names_section)
-        continue;
-
-      /* Try to extract the offset of the real name for this section from
-	 __section_names.  */
-      memcpy (&name[0], sec->u.section.sectname, 16);
-      name[16] = '\0';
-      if (name[0] != '_' || name[1] != '_'
-	  || sscanf (&name[2], "%08lX", &stringoffset) != 1
-	  || strtab_size < (ssize_t) stringoffset)
-	{
-	  error ("invalid Mach-O LTO section name string: %s", name);
-	  continue;
-	}
-
-      new_name = XNEWVEC (char, strlen (strtab + stringoffset) + 1);
-      strcpy (new_name, strtab + stringoffset);
-      s_slot.name = new_name;
-      slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
-      if (*slot == NULL)
-	{
-	  struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
-
-	  new_slot->name = new_name;
-	  if (mach_o_word_size() == 64)
-	    {
-	      new_slot->start =
-		(intptr_t) get_uint32 (&sec->u.section_64.offset[0]);
-	      new_slot->len =
-		(size_t) get_uint64 (&sec->u.section_64.size[0]);
-	    }
-	  else
-	    {
-	      new_slot->start =
-		(intptr_t) get_uint32 (&sec->u.section_32.offset[0]);
-	      new_slot->len =
-		(size_t) get_uint32 (&sec->u.section_32.size[0]);
-	    }
-
-	  *slot = new_slot;
-	}
-      else
-	{
-	  error ("two or more sections for %s:", new_name);
-	  goto done;
-	}
-    }
-
- done:
-  if (strtab)
-    free (strtab);
-  return section_hash_table;
-}
-
-
-/* Begin a new Mach-O section named NAME in the current output file.  */
-
-void
-lto_obj_begin_section (const char *name)
-{
-  lto_mach_o_file *file;
-
-  if (strncmp (name, LTO_SECTION_NAME_PREFIX,
-	       strlen(LTO_SECTION_NAME_PREFIX)) != 0)
-    sorry ("not implemented: Mach-O writer for non-LTO sections");
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_mach_o_file *) lto_get_current_out_file (),
-  gcc_assert (file && file->writable && !file->scn);
-
-  /* Create a new section.  */
-  file->scn = mach_o_new_section (file, name);
-  if (!file->scn)
-    fatal_error ("could not create a new Mach-O section: %m");
-}
-
-
-/* Append DATA of length LEN to the current output section.  BASE is a pointer
-   to the output page containing DATA.  It is freed once the output file has
-   been written.  */
-
-void
-lto_obj_append_data (const void *data, size_t len, void *block)
-{
-  lto_mach_o_file *file;
-  lto_mach_o_data mach_o_data;
-  struct lto_char_ptr_base *base = (struct lto_char_ptr_base *) block;
-
-  /* Grab the current output file and do some basic assertion checking.  */
-  file = (lto_mach_o_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  mach_o_data = mach_o_new_data (file->scn);
-  if (!mach_o_data)
-    fatal_error ("could not append data to Mach-O section: %m");
-
-  mach_o_data->d_buf = CONST_CAST (void *, data);
-  mach_o_data->d_size = len;
-
-  /* Chain all data blocks (from all sections) on one singly-linked
-     list for freeing en masse after the file is closed.  */
-  base->ptr = (char *)file->data;
-  file->data = base;
-}
-
-
-/* End the current output section.  This just does some assertion checking
-   and sets the current output file's scn member to NULL.  */
-
-void
-lto_obj_end_section (void)
-{
-  lto_mach_o_file *file;
-
-  /* Grab the current output file and validate some basic assertions.  */
-  file = (lto_mach_o_file *) lto_get_current_out_file ();
-  gcc_assert (file);
-  gcc_assert (file->scn);
-
-  file->scn = NULL;
-}
-
-
-/* Read a Mach-O header from MACH_O_FILE and validate it.
-   The file descriptor in MACH_O_FILE points at the start of the file.
-   If cached_mach_o_header is uninitialized, caches the results.
-   On succes, returns true and moves file pointer to the start of the
-   load commands.  On failure, returns false.  */
-
-static bool
-validate_mach_o_header (lto_mach_o_file *mach_o_file)
-{
-  ssize_t i, n;
-  unsigned char magic[4];
-  uint32_t cputype;
-  off_t startpos;
-
-  /* Known header magics for validation, as an array.  */
-  static const unsigned int mach_o_known_formats[] = {
-    MACH_O_MH_MAGIC,
-    MACH_O_MH_CIGAM,
-    MACH_O_MH_MAGIC_64,
-    MACH_O_MH_CIGAM_64,
-  };
-#define MACH_O_NUM_KNOWN_FORMATS \
-  ((ssize_t) ARRAY_SIZE (mach_o_known_formats))
-
-  startpos = lseek (mach_o_file->fd, 0, SEEK_CUR);
-  if (read (mach_o_file->fd, &magic, sizeof (magic)) != 4
-      || lseek (mach_o_file->fd, -4, SEEK_CUR) != startpos)
-    {
-      error ("cannot read file %s", mach_o_file->base.filename);
-      return false;
-    }
-
-  for (i = 0; i < MACH_O_NUM_KNOWN_FORMATS; ++i)
-    if (get_uint32 (&magic[0]) == mach_o_known_formats[i])
-      break;
-  if (i == MACH_O_NUM_KNOWN_FORMATS)
-    goto not_for_target;
-
-  /* Check the endian-ness.  */
-  if (BYTES_BIG_ENDIAN && magic[0] != 0xfe)
-    goto not_for_target;
-
-  /* Set or check cached magic number.  */
-  if (cached_mach_o_magic == 0)
-    cached_mach_o_magic = get_uint32 (&magic[0]);
-  else if (cached_mach_o_magic != get_uint32 (&magic[0]))
-    goto not_for_target;
- 
-  n = mach_o_word_size () == 64
-      ? sizeof (mach_o_header_64) : sizeof (mach_o_header_32);
-  if (read (mach_o_file->fd, &mach_o_file->u.header, n) != n)
-    goto not_for_target;
-
-  /* Is this a supported CPU?  */
-  /* ??? Would be nice to validate the exact target architecture.  */
-  cputype = get_uint32 (&mach_o_file->u.header.cputype[0]);
-  if (cputype == MACH_O_CPU_TYPE_I386
-      || cputype == MACH_O_CPU_TYPE_POWERPC)
-    {
-      if (mach_o_word_size () != 32)
-        goto not_for_target;
-    }
-  else if (cputype == MACH_O_CPU_TYPE_X86_64
-	   || cputype == MACH_O_CPU_TYPE_POWERPC_64)
-    {
-      if (mach_o_word_size () != 64)
-        goto not_for_target;
-    }
-
-  /* Is this an MH_OBJECT file?  */
-  if (get_uint32 (&mach_o_file->u.header.filetype[0]) != MACH_O_MH_OBJECT)
-    error ("Mach-O file %s is not an MH_OBJECT file",
-	   mach_o_file->base.filename);
-
-  /* Save the header for future use.  */
-  memcpy (&cached_mach_o_header, &mach_o_file->u.header,
-	  sizeof (cached_mach_o_header));
-
-  return true;
-
- not_for_target:
-  error ("file %s is not a Mach-O object file for target",
-	 mach_o_file->base.filename);
-  return false;
-}
-
-
-/* Read a Mach-O LC_SEGMENT command (32 bits) from MACH_O_FILE and
-   validate it.
-   The file descriptor in MACH_O_FILE points at the start of the load
-   command.  On sucess, returns true and advances the file pointer
-   past the end of the load command.  On failure, returns false.  */
-
-static bool
-validate_mach_o_segment_command_32 (lto_mach_o_file *mach_o_file)
-{
-  mach_o_segment_command_32 seg_cmd_32;
-  unsigned int i;
-  ssize_t n;
-  off_t startpos;
-
-  /* Fields we're interested in.  */
-  uint32_t cmd;
-  uint32_t cmdsize;
-  uint32_t nsects;
-
-  startpos = lseek (mach_o_file->fd, 0, SEEK_CUR);
-
-  n = sizeof (mach_o_segment_command_32);
-  if (read (mach_o_file->fd, (void *) &seg_cmd_32, n) != n)
-    goto fail;
-
-  cmd = get_uint32 (&seg_cmd_32.cmd[0]);
-  cmdsize = get_uint32 (&seg_cmd_32.cmdsize[0]);
-  nsects = get_uint32 (&seg_cmd_32.nsects[0]);
-  gcc_assert (cmd == MACH_O_LC_SEGMENT);
-
-  /* Validate section table entries.  */
-  for (i = 0; i < nsects; i++)
-    {
-      mach_o_section_32 sec_32;
-      lto_mach_o_section ltosec;
-
-      n = sizeof (mach_o_section_32);
-      if (read (mach_o_file->fd, &sec_32, n) != n)
-	goto fail;
-
-      /* ??? Perform some checks.  */
-
-      /* Looks ok, so record its details.  We don't read the 
-         string table or set up names yet; we'll do that when
-	 we build the hash table.  */
-      ltosec = mach_o_new_section (mach_o_file, NULL);
-      memcpy (&ltosec->u.section_32, &sec_32, sizeof (sec_32));
-    }
-
-  if (lseek (mach_o_file->fd, 0, SEEK_CUR) != startpos + cmdsize)
-    goto fail;
-
-  return true;
-
- fail:
-  error ("could not read LC_SEGMENT command in Mach-O file %s",
-	 mach_o_file->base.filename);
-  return false;
-}
-
-
-/* Read a Mach-O LC_SEGMENT_64 command from MACH_O_FILE and validate it.
-   The file descriptor in MACH_O_FILE points at the start of the load
-   command.  On sucess, returns true and advances the file pointer
-   past the end of the load command.  On failure, returns false.  */
-
-static bool
-validate_mach_o_segment_command_64 (lto_mach_o_file *mach_o_file)
-{
-  mach_o_segment_command_64 seg_cmd_64;
-  unsigned int i;
-  ssize_t n;
-  off_t startpos;
-
-  /* Fields we're interested in.  */
-  uint32_t cmd;
-  uint32_t cmdsize;
-  uint32_t nsects;
-
-  startpos = lseek (mach_o_file->fd, 0, SEEK_CUR);
-
-  n = sizeof (mach_o_segment_command_64);
-  if (read (mach_o_file->fd, (void *) &seg_cmd_64, n) != n)
-    goto fail;
-
-  cmd = get_uint32 (&seg_cmd_64.cmd[0]);
-  cmdsize = get_uint32 (&seg_cmd_64.cmdsize[0]);
-  nsects = get_uint32 (&seg_cmd_64.nsects[0]);
-  gcc_assert (cmd == MACH_O_LC_SEGMENT_64);
-
-  /* Validate section table entries.  */
-  for (i = 0; i < nsects; i++)
-    {
-      mach_o_section_64 sec_64;
-      lto_mach_o_section ltosec;
-
-      n = sizeof (mach_o_section_64);
-      if (read (mach_o_file->fd, &sec_64, n) != n)
-	goto fail;
-
-      /* ??? Perform some checks.  */
-
-      /* Looks ok, so record its details.  We don't read the 
-         string table or set up names yet; we'll do that when
-	 we build the hash table.  */
-      ltosec = mach_o_new_section (mach_o_file, NULL);
-      memcpy (&ltosec->u.section_64, &sec_64, sizeof (sec_64));
-    }
-
-  if (lseek (mach_o_file->fd, 0, SEEK_CUR) != startpos + cmdsize)
-    goto fail;
-
-  return true;
-
- fail:
-  error ("could not read LC_SEGMENT_64 command in Mach-O file %s",
-	 mach_o_file->base.filename);
-  return false;
-}
-
-/* Read a Mach-O load commands from MACH_O_FILE and validate it.
-   The file descriptor in MACH_O_FILE points at the start of the load
-   command.  On sucess, returns true and advances the file pointer
-   past the end of the load command.  On failure, returns false.  */
-
-static bool
-validate_mach_o_load_command (lto_mach_o_file *mach_o_file)
-{
-  mach_o_load_command load_command;
-  uint32_t cmd;
-  uint32_t cmdsize;
-  ssize_t n;
-
-  n = sizeof (load_command);
-  if (read (mach_o_file->fd, &load_command, n) != n)
-    {
-      error ("could not read load commands in Mach-O file %s",
-	     mach_o_file->base.filename);
-      return false;
-    }
-  lseek (mach_o_file->fd, -1 * (off_t) sizeof (load_command), SEEK_CUR);
-
-  cmd = get_uint32 (&load_command.cmd[0]);
-  cmdsize = get_uint32 (&load_command.cmdsize[0]);
-  switch (cmd)
-    {
-    case MACH_O_LC_SEGMENT:
-      return validate_mach_o_segment_command_32 (mach_o_file);
-    case MACH_O_LC_SEGMENT_64:
-      return validate_mach_o_segment_command_64 (mach_o_file);
-
-    default:
-      /* Just skip over it.  */
-      lseek (mach_o_file->fd, cmdsize, SEEK_CUR);
-      return true;
-    }
-}
-
-/* Validate's MACH_O_FILE's executable header and, if cached_mach_o_header is
-   uninitialized, caches the results.  Also records the section header string
-   table's section index.  Returns true on success, false on failure.  */
-
-static bool
-validate_file (lto_mach_o_file *mach_o_file)
-{
-  uint32_t i, ncmds;
-
-  /* Read and sanity check the raw header.  */
-  if (! validate_mach_o_header (mach_o_file))
-    return false;
-
-  ncmds = get_uint32 (&mach_o_file->u.header.ncmds[0]);
-  for (i = 0; i < ncmds; ++i)
-    if (! validate_mach_o_load_command (mach_o_file))
-      return false;
-
-  return true;
-}
-
-/* Initialize MACH_O_FILE's executable header using cached data from previously
-   read files.  */
-
-static void
-init_mach_o_header (lto_mach_o_file *mach_o_file)
-{
-  gcc_assert (cached_mach_o_magic != 0);
-  memcpy (&mach_o_file->u.header,
-	  &cached_mach_o_header,
-	  sizeof (mach_o_file->u.header));
-  put_uint32 (&mach_o_file->u.header.ncmds[0], 0);
-  put_uint32 (&mach_o_file->u.header.sizeofcmds[0], 0);
-}
-
-/* Open Mach-O file FILENAME.  If WRITABLE is true, the file is opened for write
-   and, if necessary, created.  Otherwise, the file is opened for reading.
-   Returns the opened file.  */
-
-lto_file *
-lto_obj_file_open (const char *filename, bool writable)
-{
-  lto_mach_o_file *mach_o_file;
-  lto_file *result = NULL;
-  off_t offset;
-  const char *offset_p;
-  char *fname;
-  struct stat statbuf;
-
-  offset_p = strchr (filename, '@');
-  if (!offset_p)
-    {
-      fname = xstrdup (filename);
-      offset = 0;
-    }
-  else
-    {
-      /* The file started with '@' is a file containing command line
-	 options.  Stop if it doesn't exist.  */
-      if (offset_p == filename)
-	fatal_error ("command line option file '%s' does not exist",
-		     filename);
-
-      fname = (char *) xmalloc (offset_p - filename + 1);
-      memcpy (fname, filename, offset_p - filename);
-      fname[offset_p - filename] = '\0';
-      offset_p += 3; /* skip the @0x */
-      offset = lto_parse_hex (offset_p);
-    }
-
-  /* Set up.  */
-  mach_o_file = XCNEW (lto_mach_o_file);
-  result = (lto_file *) mach_o_file;
-  lto_file_init (result, fname, offset);
-  mach_o_file->fd = -1;
-  mach_o_file->writable = writable;
-
-  /* Open the file.  */
-  mach_o_file->fd = open (fname,
-    O_BINARY | (writable ? O_WRONLY | O_CREAT | O_TRUNC : O_RDONLY), 0666);
-
-  if (mach_o_file->fd == -1)
-    {
-      error ("could not open file %s", fname);
-      goto fail;
-    }
-
-  if (stat (fname, &statbuf) < 0)
-    {
-      error ("could not stat file %s", fname);
-      goto fail;
-    }
-
-  mach_o_file->file_size = statbuf.st_size;
-
-  /* If the object is in an archive, get it out.  */
-  if (offset != 0)
-    {
-      char ar_tail[12];
-      int size;
-
-      /* Surely not?  */
-      gcc_assert (!writable);
-
-      /* Seek to offset, or error.  */
-      if (lseek (mach_o_file->fd, offset, SEEK_SET) != (ssize_t) offset)
-	{
-	  error ("could not find archive member @0x%lx", (long) offset);
-	  goto fail;
-	}
-
-      /* Now seek back 12 chars and read the tail of the AR header to
-         find the length of the member file.  */
-      if (lseek (mach_o_file->fd, -12, SEEK_CUR) < 0
-	  || read (mach_o_file->fd, ar_tail, 12) != 12
-	  || lseek (mach_o_file->fd, 0, SEEK_CUR) != (ssize_t) offset
-	  || ar_tail[10] != '`' || ar_tail[11] != '\n')
-	{
-	  error ("could not find archive header @0x%lx", (long) offset);
-	  goto fail;
-	}
-
-      ar_tail[11] = 0;
-      if (sscanf (ar_tail, "%d", &size) != 1)
-	{
-	  error ("invalid archive header @0x%lx", (long) offset);
-	  goto fail;
-	}
-      mach_o_file->file_size = size;
-    }
-
-  if (writable)
-    {
-      init_mach_o_header (mach_o_file);
-    }
-  else
-    if (! validate_file (mach_o_file))
-      goto fail;
-
-  return result;
-
- fail:
-  if (result)
-    lto_obj_file_close (result);
-  return NULL;
-}
-
-
-/* Write the data in MACH_O_FILE to a real Mach-O binary object.
-   We write a header, a segment load command, and section data.  */
-
-static bool
-mach_o_write_object_file (lto_mach_o_file *mach_o_file)
-{
-  lto_mach_o_section sec, snsec;
-  lto_mach_o_data snsec_data;
-  ssize_t hdrsize, cmdsize, secsize;
-  size_t num_sections, snsec_size, total_sec_size;
-  unsigned int sec_offs, strtab_offs;
-  int i;
-  bool write_err = false;
-
-  /* The number of sections we will write is the number of sections added by
-     the streamer, plus 1 for the section names section.  */
-  num_sections = VEC_length (lto_mach_o_section, mach_o_file->section_vec) + 1;
-
-  /* Calculate the size of the basic data structures on disk.  */
-  if (mach_o_word_size () == 64)
-    {
-      hdrsize = sizeof (mach_o_header_64);
-      secsize = sizeof (mach_o_section_64);
-      cmdsize = sizeof (mach_o_segment_command_64) + num_sections * secsize;
-    }
-  else
-    {
-      hdrsize = sizeof (mach_o_header_32);
-      secsize = sizeof (mach_o_section_32);
-      cmdsize = sizeof (mach_o_segment_command_32) + num_sections * secsize;
-    }
- 
-  /* Allocate the section names section.  */
-  snsec_size = 0;
-  for (i = 0;
-       VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    snsec_size += strlen (sec->name) + 1;
-  snsec = mach_o_new_section (mach_o_file, NULL);
-  snsec->name = LTO_NAMES_SECTION;
-  snsec_data = mach_o_new_data (snsec);
-  snsec_data->d_buf = XCNEWVEC (char, snsec_size);
-  snsec_data->d_size = snsec_size;
-
-  /* Position all the sections, and fill out their headers.  */
-  sec_offs = hdrsize + cmdsize;
-  strtab_offs = 0;
-  total_sec_size = 0;
-  for (i = 0;
-       VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    {
-      lto_mach_o_data data;
-      size_t data_size;
-      /* Put the section and segment names.  Add the section name to the
-         section names section (unless, of course, this *is* the section
-	 names section).  */
-      if (sec == snsec)
-	snprintf (sec->u.section.sectname, 16, "%s", LTO_NAMES_SECTION);
-      else
-	{
-	  sprintf (sec->u.section.sectname, "__%08X", strtab_offs);
-	  memcpy ((char *) snsec_data->d_buf + strtab_offs, sec->name, strlen (sec->name));
-	}
-      memcpy (&sec->u.section.segname[0],
-	      LTO_SEGMENT_NAME, strlen (LTO_SEGMENT_NAME));
-
-      /* Add layout and attributes.  */
-      for (data = sec->data_chain, data_size = 0; data; data = data->next)
-	data_size += data->d_size;
-      if (mach_o_word_size () == 64)
-	{
-	  put_uint64 (&sec->u.section_64.addr[0], total_sec_size); 
-	  put_uint64 (&sec->u.section_64.size[0], data_size); 
-	  put_uint32 (&sec->u.section_64.offset[0], sec_offs); 
-	  put_uint32 (&sec->u.section_64.flags[0], MACH_O_S_ATTR_DEBUG);
-	}
-      else
-	{
-	  put_uint32 (&sec->u.section_64.addr[0], total_sec_size); 
-	  put_uint32 (&sec->u.section_32.size[0], data_size); 
-	  put_uint32 (&sec->u.section_32.offset[0], sec_offs); 
-	  put_uint32 (&sec->u.section_32.flags[0], MACH_O_S_ATTR_DEBUG);
-	}
-
-      sec_offs += data_size;
-      total_sec_size += data_size;
-      strtab_offs += strlen (sec->name) + 1;
-    }
-
-  /* We can write the data now.  As there's no way to indicate an error return
-     from this hook, error handling is limited to not wasting our time doing
-     any more writes in the event that any one fails.  */
-
-  /* Write the header.  */
-  put_uint32 (&mach_o_file->u.header.ncmds[0], 1);
-  put_uint32 (&mach_o_file->u.header.sizeofcmds[0], cmdsize);
-  write_err = (write (mach_o_file->fd,
-		      &mach_o_file->u.header, hdrsize) != hdrsize);
-  /* Write the segment load command.  */
-  if (mach_o_word_size () == 64)
-    {
-      mach_o_segment_command_64 lc;
-      ssize_t lc_size = sizeof (lc);
-      memset (&lc, 0, lc_size);
-      put_uint32 (&lc.cmd[0], MACH_O_LC_SEGMENT_64);
-      put_uint32 (&lc.cmdsize[0], cmdsize);
-      put_uint64 (&lc.fileoff[0], hdrsize + cmdsize);
-      put_uint64 (&lc.filesize[0], total_sec_size);
-      put_uint32 (&lc.nsects[0], num_sections);
-      write_err = (write (mach_o_file->fd, &lc, lc_size) != lc_size);
-    }
-  else
-    {
-      mach_o_segment_command_32 lc;
-      ssize_t lc_size = sizeof (lc);
-      memset (&lc, 0, lc_size);
-      put_uint32 (&lc.cmd[0], MACH_O_LC_SEGMENT);
-      put_uint32 (&lc.cmdsize[0], cmdsize);
-      put_uint32 (&lc.fileoff[0], hdrsize + cmdsize);
-      put_uint32 (&lc.filesize[0], total_sec_size);
-      put_uint32 (&lc.nsects[0], num_sections);
-      write_err = (write (mach_o_file->fd, &lc, lc_size) != lc_size);
-    }
-  for (i = 0;
-       !write_err
-       && VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    write_err = (write (mach_o_file->fd,
-			&sec->u.section, secsize) != secsize);
-
-  gcc_assert (lseek (mach_o_file->fd, 0, SEEK_CUR) == hdrsize + cmdsize);
-
-  /* Write the section data.  */
-  for (i = 0;
-       !write_err
-       && VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    {
-      lto_mach_o_data data;
-
-      for (data = sec->data_chain; data; data = data->next)
-	{
-	  if (!write_err)
-	    write_err = (write (mach_o_file->fd, data->d_buf, data->d_size)
-			 != data->d_size);
-	  else
-	    break;
-	}
-    }
-
-  return !write_err;
-}
-
-/* Close Mach-O file FILE and clean up any associated data structures.  If FILE
-   was opened for writing, the file's Mach-O data is written at this time.  Any
-   cached data buffers are freed.  */
-
-void
-lto_obj_file_close (lto_file *file)
-{
-  lto_mach_o_file *mach_o_file = (lto_mach_o_file *) file;
-  struct lto_char_ptr_base *cur, *tmp;
-  lto_mach_o_section sec;
-  bool write_err = false;
-  int i;
-
-  /* If this file is open for writing, write a Mach-O object file.  */
-  if (mach_o_file->writable)
-    {
-      if (! mach_o_write_object_file (mach_o_file))
-        fatal_error ("cannot write Mach-O object file");
-    }
-
-  /* Close the file, we're done.  */
-  if (mach_o_file->fd != -1)
-    close (mach_o_file->fd);
-
-  /* Free any data buffers.  */
-  cur = mach_o_file->data;
-  while (cur)
-    {
-      tmp = cur;
-      cur = (struct lto_char_ptr_base *) cur->ptr;
-      free (tmp);
-    }
-
-  /* Free any sections and their data chains.  */
-  for (i = 0;
-       VEC_iterate (lto_mach_o_section, mach_o_file->section_vec, i, sec);
-       i++)
-    {
-      lto_mach_o_data curdata, nextdata;
-      curdata = sec->data_chain;
-      while (curdata)
-	{
-	  nextdata = curdata->next;
-	  free (curdata);
-	  curdata = nextdata;
-	}
-      free (sec);
-    }
-  VEC_free (lto_mach_o_section, heap, mach_o_file->section_vec);
-
-  free (file);
-
-  /* If there was an error, mention it.  */
-  if (write_err)
-    error ("I/O error writing Mach-O output file");
-}
-
Index: gcc/lto/lto-macho.h
===================================================================
--- gcc/lto/lto-macho.h	(revision 166080)
+++ gcc/lto/lto-macho.h	(working copy)
@@ -1,251 +0,0 @@
-/* LTO routines for Mach-O object files.
-   Copyright 2010 Free Software Foundation, Inc.
-   Contributed by Steven Bosscher.
-
-This file is part of GCC.
-
-GCC 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 3, or (at your option) any later
-version.
-
-GCC 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 GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#ifndef LTO_MACH_O_H
-#define LTO_MACH_O_H
-
-/* On-disk file structures.  */
-
-/* Mach-O header (32 bits version).  */
-struct mach_o_header_32
-{
-  unsigned char magic[4];	/* Magic number.  */
-  unsigned char cputype[4];	/* CPU that this object is for.  */
-  unsigned char cpusubtype[4];	/* CPU subtype.  */
-  unsigned char filetype[4];	/* Type of file.  */
-  unsigned char ncmds[4];	/* Number of load commands.  */
-  unsigned char sizeofcmds[4];	/* Total size of load commands.  */
-  unsigned char flags[4];	/* Flags for special featues.  */
-};
-typedef struct mach_o_header_32 mach_o_header_32;
-
-/* Mach-O header (64 bits version).  */
-struct mach_o_header_64
-{
-  unsigned char magic[4];	/* Magic number.  */
-  unsigned char cputype[4];	/* CPU that this object is for.  */
-  unsigned char cpusubtype[4];	/* CPU subtype.  */
-  unsigned char filetype[4];	/* Type of file.  */
-  unsigned char ncmds[4];	/* Number of load commands.  */
-  unsigned char sizeofcmds[4];	/* Total size of load commands.  */
-  unsigned char flags[4];	/* Flags for special featues.  */
-  unsigned char reserved[4];	/* Reserved.  Duh.  */
-};
-typedef struct mach_o_header_64 mach_o_header_64;
-
-/* Magic number.  */
-#define MACH_O_MH_MAGIC			0xfeedface
-#define MACH_O_MH_CIGAM			0xcefaedfe
-#define MACH_O_MH_MAGIC_64		0xfeedfacf
-#define MACH_O_MH_CIGAM_64		0xcffaedfe
-
-/* Supported CPU types.  */
-#define MACH_O_CPU_TYPE_I386		7
-#define MACH_O_CPU_TYPE_X86_64		7 + 0x1000000
-#define MACH_O_CPU_TYPE_POWERPC		18
-#define MACH_O_CPU_TYPE_POWERPC_64	18 + 0x1000000
-
-/* Supported file types.  */
-#define MACH_O_MH_OBJECT		0x01
-
-/* Mach-O load command data structure.  */
-struct mach_o_load_command
-{
-  unsigned char cmd[4];		/* The type of load command.  */
-  unsigned char cmdsize[4];	/* Size in bytes of load command data structure.  */
-};
-typedef struct mach_o_load_command mach_o_load_command;
-
-/* Supported load commands.  We support only the segment load commands.  */
-#define MACH_O_LC_SEGMENT		0x01
-#define MACH_O_LC_SEGMENT_64		0x19
-
-/* LC_SEGMENT load command.  */
-struct mach_o_segment_command_32
-{
-  unsigned char cmd[4];		/* The type of load command (LC_SEGMENT).  */
-  unsigned char cmdsize[4];	/* Size in bytes of load command data structure.  */
-  unsigned char segname[16];	/* Name of this segment.  */
-  unsigned char vmaddr[4];	/* Virtual memory address of this segment.  */
-  unsigned char vmsize[4];	/* Size there, in bytes.  */
-  unsigned char fileoff[4];	/* Offset in bytes of the data to be mapped.  */
-  unsigned char filesize[4];	/* Size in bytes on disk.  */
-  unsigned char maxprot[4];	/* Maximum permitted vmem protection.  */
-  unsigned char initprot[4];	/* Initial vmem protection.  */
-  unsigned char nsects[4];	/* Number of sections in this segment.  */
-  unsigned char flags[4];	/* Flags that affect the loading.  */
-};
-typedef struct mach_o_segment_command_32 mach_o_segment_command_32;
-
-/* LC_SEGMENT_64 load command.  Only nsects matters for us, really.  */
-struct mach_o_segment_command_64
-{
-  unsigned char cmd[4];		/* The type of load command (LC_SEGMENT_64).  */
-  unsigned char cmdsize[4];	/* Size in bytes of load command data structure.  */
-  unsigned char segname[16];	/* Name of this segment.  */
-  unsigned char vmaddr[8];	/* Virtual memory address of this segment.  */
-  unsigned char vmsize[8];	/* Size there, in bytes.  */
-  unsigned char fileoff[8];	/* Offset in bytes of the data to be mapped.  */
-  unsigned char filesize[8];	/* Size in bytes on disk.  */
-  unsigned char maxprot[4];	/* Maximum permitted vmem protection.  */
-  unsigned char initprot[4];	/* Initial vmem protection.  */
-  unsigned char nsects[4];	/* Number of sections in this segment.  */
-  unsigned char flags[4];	/* Flags that affect the loading.  */
-};
-typedef struct mach_o_segment_command_64 mach_o_segment_command_64;
-
-/* A Mach-O 32-bits section.  */
-struct mach_o_section_32
-{
-  unsigned char sectname[16];	/* Section name.  */
-  unsigned char segname[16];	/* Segment that the section belongs to.  */
-  unsigned char addr[4];	/* Address of this section in memory.  */
-  unsigned char size[4];	/* Size in bytes of this section.  */
-  unsigned char offset[4];	/* File offset of this section.  */
-  unsigned char align[4];	/* log2 of this section's alignment.  */
-  unsigned char reloff[4];	/* File offset of this section's relocs.  */
-  unsigned char nreloc[4];	/* Number of relocs for this section.  */
-  unsigned char flags[4];	/* Section flags/attributes.  */
-  unsigned char reserved1[4];
-  unsigned char reserved2[4];
-};
-typedef struct mach_o_section_32 mach_o_section_32;
-
-/* A Mach-O 64-bits section.  */
-struct mach_o_section_64
-{
-  unsigned char sectname[16];	/* Section name.  */
-  unsigned char segname[16];	/* Segment that the section belongs to.  */
-  unsigned char addr[8];	/* Address of this section in memory.  */
-  unsigned char size[8];	/* Size in bytes of this section.  */
-  unsigned char offset[4];	/* File offset of this section.  */
-  unsigned char align[4];	/* log2 of this section's alignment.  */
-  unsigned char reloff[4];	/* File offset of this section's relocs.  */
-  unsigned char nreloc[4];	/* Number of relocs for this section.  */
-  unsigned char flags[4];	/* Section flags/attributes.  */
-  unsigned char reserved1[4];
-  unsigned char reserved2[4];
-  unsigned char reserved3[4];
-};
-typedef struct mach_o_section_64 mach_o_section_64;
-
-/* Flags for Mach-O sections.  LTO sections are marked with S_ATTR_DEBUG
-   to instruct the linker to ignore the sections.  */
-#define MACH_O_S_ATTR_DEBUG			0x02000000
-
-/* In-memory file structures.  */
-
-/* Section data in output files is made of these.  */
-struct lto_mach_o_data_d
-{
-  /* Pointer to data block.  */
-  void *d_buf;
-
-  /* Size of data block.  */
-  ssize_t d_size;
-
-  /* Next data block for this section.  */
-  struct lto_mach_o_data_d *next;
-};
-typedef struct lto_mach_o_data_d *lto_mach_o_data;
-
-/* This struct tracks the data for a section.  */
-struct lto_mach_o_section_d
-{
-  /* Singly-linked list of section's data blocks.  */
-  lto_mach_o_data data_chain;
-
-  /* Offset in string table of the section name.  */
-  size_t strtab_offs;
-
-  /* Section name.  */
-  const char *name;
-
-  /* Number of trailing padding bytes needed.  */
-  ssize_t pad_needed;
-
-  /* Raw section header data.  */
-  size_t section_size;
-  union {
-    struct {
-      char sectname[16];
-      char segname[16];
-    } section;
-    mach_o_section_32 section_32;
-    mach_o_section_64 section_64;
-  } u;
-
-  /* Next section for this file.  */
-  struct lto_mach_o_section_d *next;
-};
-typedef struct lto_mach_o_section_d *lto_mach_o_section;
-DEF_VEC_P (lto_mach_o_section);
-DEF_VEC_ALLOC_P (lto_mach_o_section, heap);
-
-/* A Mach-O file.  */
-struct lto_mach_o_file_d
-{
-  /* The base information.  */
-  lto_file base;
-
-  /* Common file members:  */
-
-  /* The system file descriptor for the file.  */
-  int fd;
-
-  /* The file's overall header.  */
-  union {
-    /* We make use here of the fact that section_32 and section_64
-       have the same layout (except for section_64.reserved3).  We
-       read the struct of proper size, but only address the first
-       member of this union.  */
-    mach_o_header_64 header;
-    mach_o_header_32 header_32;
-    mach_o_header_64 header_64;
-  } u;
-
-  /* All sections in a varray.  */
-  VEC(lto_mach_o_section, heap) *section_vec;
-
-  /* Readable file members:  */
-
-  /* File total size.  */
-  off_t file_size;
-
-  /* True if this file is open for writing.  */
-  bool writable;
-
-  /* Section containing the __section_names section.  */
-  lto_mach_o_section section_names_section;
-
-  /* Writable file members:  */
-
-  /* The currently active section.  */
-  lto_mach_o_section scn;
-
-  /* Linked list of data which must be freed *after* the file has been
-     closed.  This is an annoying limitation of libelf.  Which has been
-     faithfully reproduced here.  */
-  struct lto_char_ptr_base *data;
-};
-typedef struct lto_mach_o_file_d lto_mach_o_file;
-
-#endif /* LTO_MACH_O_H */
-
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(revision 166080)
+++ gcc/configure.ac	(working copy)
@@ -975,22 +975,6 @@ AC_CHECK_FUNCS(times clock kill getrlimi
 	gettimeofday mbstowcs wcswidth mmap mincore setlocale \
 	gcc_UNLOCKED_FUNCS)
 
-save_CPPFLAGS="$CPPFLAGS"
-save_LIBS="$LIBS"
-LIBS="$LIBS $LIBELFLIBS"
-AC_CHECK_FUNCS(elf_getshdrstrndx,,
-  [AC_CHECK_FUNCS(elf_getshstrndx,
-    [AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdlib.h>
-#include <libelf.h>
-int main()
-{
-  return elf_getshstrndx (NULL, 0) == 0;
-}]])], AC_DEFINE(HAVE_ELF_GETSHSTRNDX_GABI, 1,
-        [Define if elf_getshstrndx has gABI conformant return values.]))])]
-  )
-LIBS="$save_LIBS"
-CPPFLAGS="$save_CPPFLAGS"
-
 if test x$ac_cv_func_mbstowcs = xyes; then
   AC_CACHE_CHECK(whether mbstowcs works, gcc_cv_func_mbstowcs_works,
 [    AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdlib.h>
@@ -4461,17 +4445,6 @@ changequote([,])dnl
 		    AC_DEFINE(ENABLE_LTO, 1, [Define to enable LTO support.])
 		    enable_lto=yes
 		    AC_SUBST(enable_lto)
-		    # LTO needs to speak the platform's object file format, and has a
-		    # number of implementations of the required binary file access APIs.
-		    # ELF is the most common, and default.  We only link libelf if ELF
-		    # is indeed the selected format.
-		    LTO_BINARY_READER=${lto_binary_reader}
-		    LTO_USE_LIBELF=-lelf
-		    if test "x$lto_binary_reader" != "xlto-elf" ; then
-		      LTO_USE_LIBELF=
-		    fi
-		    AC_SUBST(LTO_BINARY_READER)
-		    AC_SUBST(LTO_USE_LIBELF)
 		    ;;
 		*) ;;
 	esac
@@ -4644,12 +4617,6 @@ if test "x${CLOOGLIBS}" != "x" ; then 
    AC_DEFINE(HAVE_cloog, 1, [Define if cloog is in use.])
 fi
 
-AC_ARG_VAR(LIBELFLIBS,[How to link libelf])
-AC_ARG_VAR(LIBELFINC,[How to find libelf include files])
-if test "x${LIBELFLIBS}" != "x" ; then 
-   AC_DEFINE(HAVE_libelf, 1, [Define if libelf is in use.])
-fi
-
 # Check for plugin support
 AC_ARG_ENABLE(plugin,
 [  --enable-plugin         enable plugin support],
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 166080)
+++ gcc/config.gcc	(working copy)
@@ -219,8 +219,6 @@ default_gnu_indirect_function=no
 target_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
-# Selects the object file format reader/writer used by LTO.
-lto_binary_reader=lto-elf
 
 # Don't carry these over build->host->target.  Please.
 xm_file=
@@ -1159,14 +1157,12 @@ i[34567]86-*-darwin*)
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
 	extra_options="${extra_options} i386/darwin.opt"
-	lto_binary_reader=lto-macho
 	;;
 x86_64-*-darwin*)
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
 	tm_file="${tm_file} ${cpu_type}/darwin64.h"
 	extra_options="${extra_options} i386/darwin.opt"
-	lto_binary_reader=lto-macho
 	;;
 i[34567]86-*-elf*)
 	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
@@ -1421,7 +1417,6 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
 		thread_file='posix'
 	fi
 	use_gcc_stdint=wrap
-	lto_binary_reader=lto-coff
 	;;
 i[34567]86-*-mingw* | x86_64-*-mingw*)
 	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h"
@@ -1494,7 +1489,6 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
 	cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
 	default_use_cxa_atexit=yes
 	use_gcc_stdint=wrap
-	lto_binary_reader=lto-coff
 	case ${enable_threads} in
 	  "" | yes | win32)	  thread_file='win32'
 	  tmake_file="${tmake_file} i386/t-gthr-win32"
@@ -2004,7 +1998,6 @@ powerpc-*-darwin*)
 	    ;;
 	esac
 	tmake_file="${tmake_file} t-slibgcc-darwin"
-	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc64-*-darwin*)
@@ -2012,7 +2005,6 @@ powerpc64-*-darwin*)
 	extra_parts="crt2.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin"
 	tm_file="${tm_file} ${cpu_type}/darwin8.h ${cpu_type}/darwin64.h"
-	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc*-*-freebsd*)
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 166080)
+++ gcc/Makefile.in	(working copy)
@@ -319,17 +319,9 @@ PPLINC = @PPLINC@
 CLOOGLIBS = @CLOOGLIBS@
 CLOOGINC = @CLOOGINC@
 
-# How to find libelf
-LIBELFLIBS = @LIBELFLIBS@
-LIBELFINC = @LIBELFINC@
-
 # Set to 'yes' if the LTO front end is enabled.
 enable_lto = @enable_lto@
 
-# Set according to LTO object file format.
-LTO_BINARY_READER = @LTO_BINARY_READER@
-LTO_USE_LIBELF = @LTO_USE_LIBELF@
-
 # Compiler and flags needed for plugin support
 ifneq ($(ENABLE_BUILD_WITH_CXX),yes)
 PLUGINCC = @CC@
@@ -1032,7 +1024,7 @@ BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
 LIBS = @LIBS@ $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBIBERTY) $(LIBDECNUMBER) \
 	$(HOST_LIBS)
 BACKENDLIBS = $(CLOOGLIBS) $(PPLLIBS) $(GMPLIBS) $(PLUGINLIBS) $(HOST_LIBS) \
-	$(ZLIB) $(LIBELFLIBS)
+	$(ZLIB)
 # Any system libraries needed just for GNAT.
 SYSLIBS = @GNAT_LIBEXC@
 
@@ -1063,7 +1055,7 @@ BUILD_ERRORS = build/errors.o
 INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
 	   -I$(srcdir)/../include @INCINTL@ \
 	   $(CPPINC) $(GMPINC) $(DECNUMINC) \
-	   $(PPLINC) $(CLOOGINC) $(LIBELFINC)
+	   $(PPLINC) $(CLOOGINC)
 
 .c.o:
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
Index: configure.ac
===================================================================
--- configure.ac	(revision 166080)
+++ configure.ac	(working copy)
@@ -1647,174 +1647,7 @@ AC_SUBST(clooginc)
 AC_ARG_ENABLE(lto,
 [  --enable-lto            enable link time optimization support],
 enable_lto=$enableval,
-enable_lto=yes; default_enable_lto=yes)
-
-
-ACX_ELF_TARGET_IFELSE([if test x"$enable_lto" = x"yes" ; then
-  # Make sure that libelf.h and gelf.h are available.
-  AC_ARG_WITH(libelf, [  --with-libelf=PATH       Specify prefix directory for the installed libelf package
-                          Equivalent to --with-libelf-include=PATH/include
-                          plus --with-libelf-lib=PATH/lib])
-
-  AC_ARG_WITH(libelf_include, [  --with-libelf-include=PATH Specify directory for installed libelf include files])
-
-  AC_ARG_WITH(libelf_lib, [  --with-libelf-lib=PATH   Specify the directory for the installed libelf library])
-
-  saved_CFLAGS="$CFLAGS"
-  saved_CPPFLAGS="$CPPFLAGS"
-  saved_LIBS="$LIBS"
-
-  case $with_libelf in 
-    "")
-      libelflibs="-lelf"
-      libelfinc="-I/usr/include/libelf"
-      ;;
-    *)
-      libelflibs="-L$with_libelf/lib -lelf"
-      libelfinc="-I$with_libelf/include -I$with_libelf/include/libelf"
-      LIBS="$libelflibs $LIBS"
-      ;;
-  esac
-
-  if test "x$with_libelf_include" != x; then
-    libelfinc="-I$with_libelf_include"
-  fi
-
-  if test "x$with_libelf_lib" != x; then
-    libelflibs="-L$with_libelf_lib -lelf"
-    LIBS="$libelflibs $LIBS"
-  fi
-
-  if test "x$with_libelf$with_libelf_include$with_libelf_lib" = x \
-     && test -d ${srcdir}/libelf; then
-    libelflibs='-L$$r/$(HOST_SUBDIR)/libelf/lib -lelf '
-    libelfinc='-D__LIBELF_INTERNAL__ -I$$r/$(HOST_SUBDIR)/libelf/lib -I$$s/libelf/lib'
-    LIBS="$libelflibs $LIBS"
-
- else
-
-  CFLAGS="$CFLAGS $libelfinc"
-  CPPFLAGS="$CPPFLAGS $libelfinc"
-  LIBS="$LIBS $libelflibs"
-
-  AC_CHECK_HEADERS(libelf.h, [have_libelf_h=yes])
-  AC_CHECK_HEADERS(gelf.h, [have_gelf_h=yes])
-
-  AC_CHECK_HEADERS(libelf/libelf.h, [have_libelf_libelf_h=yes])
-  AC_CHECK_HEADERS(libelf/gelf.h, [have_libelf_gelf_h=yes])
-
-  # If we couldn't find libelf.h and the user forced it, emit an error.
-  if test x"$have_libelf_h" != x"yes" \
-     && test x"$have_libelf_libelf_h" != x"yes" ; then
-    if test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([LTO support requires libelf.h or libelf/libelf.h.])
-    else
-      enable_lto=no
-      libelflibs=
-      libelfinc=
-    fi
-  fi
-
-  # If we couldn't find gelf.h and the user forced it, emit an error.
-  if test x"$have_gelf_h" != x"yes" \
-     && test x"$have_libelf_gelf_h" != x"yes" ; then
-    if test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([LTO support requires gelf.h or libelf/gelf.h.])
-    else
-      enable_lto=no
-      libelflibs=
-      libelfinc=
-    fi
-  fi
-
-  # Check that the detected libelf has the functions we need.  We cannot
-  # rely on just detecting the headers since they do not include 
-  # versioning information.  Add functions, if needed.
-  if test x"$enable_lto" = x"yes" ; then
-    AC_MSG_CHECKING([for the correct version of libelf])
-    AC_TRY_LINK(
-      [#include <libelf.h>],[
-      elf_errmsg (0);
-      elf_getscn (0, 0);
-      elf_nextscn (0, 0);
-      elf_strptr (0, 0, 0);
-      elf_getident (0, 0);
-      elf_begin (0, 0, 0);
-      elf_ndxscn (0);
-      elf_end (0);
-      ],
-      [AC_MSG_RESULT([yes]);],
-      [AC_MSG_RESULT([no]); enable_lto=no; libelflibs= ; libelfinc= ]
-    )
-
-    # Check for elf_getshdrstrndx or elf_getshstrndx.  The latter's flavor
-    # is determined in gcc/configure.ac.
-    if test x"$enable_lto" = x"yes" ; then
-      AC_MSG_CHECKING([for elf_getshdrstrndx])
-      AC_TRY_LINK(
-        [#include <libelf.h>],[
-	elf_getshdrstrndx (0, 0);
-        ],
-        [AC_MSG_RESULT([yes]);],
-        [AC_MSG_RESULT([no]);
-	 AC_MSG_CHECKING([for elf_getshstrndx])
-         AC_TRY_LINK(
-           [#include <libelf.h>],[
-	   elf_getshstrndx (0, 0);
-           ],
-           [AC_MSG_RESULT([yes]);],
-           [AC_MSG_RESULT([no]); enable_lto=no; libelflibs= ; libelfinc= ]
-         )]
-      )
-    fi
-
-    # If we couldn't enable LTO and the user forced it, emit an error.
-    if test x"$enable_lto" = x"no" \
-       && test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([To enable LTO, GCC requires libelf v0.8.12+.
-Try the --with-libelf, --with-libelf-include and --with-libelf-lib options
-to specify its location.])
-    fi
-  fi
-
-  CFLAGS="$saved_CFLAGS"
-  CPPFLAGS="$saved_CPPFLAGS"
-  LIBS="$saved_LIBS"
-
- fi
-
-  # Flags needed for libelf.
-  AC_SUBST(libelflibs)
-  AC_SUBST(libelfinc)
-  # ELF platforms build the lto-plugin when GOLD is in use.
-  build_lto_plugin=${ENABLE_GOLD}
-fi],[if test x"$default_enable_lto" = x"yes" ; then
-    case $target in
-      *-apple-darwin* | *-cygwin* | *-mingw*) ;;
-      # On other non-ELF platforms, LTO must be explicitly enabled.
-      *) enable_lto=no ;;
-    esac
-  else
-  # Apart from ELF platforms, only Windows and Darwin support LTO so far.
-  # It would also be nice to check the binutils support, but we don't
-  # have gcc_GAS_CHECK_FEATURE available here.  For now, we'll just
-  # warn during gcc/ subconfigure; unless you're bootstrapping with
-  # -flto it won't be needed until after installation anyway.
-    case $target in
-      *-cygwin* | *-mingw* | *-apple-darwin*) ;;
-      *) if test x"$enable_lto" = x"yes"; then
-	AC_MSG_ERROR([LTO support is not enabled for this target.])
-        fi
-      ;;
-    esac
-  fi
-  # Among non-ELF, only Windows platforms support the lto-plugin so far.
-  case $target in
-    *-cygwin* | *-mingw*) build_lto_plugin=yes ;;
-    *) ;;
-  esac
-  default_enable_lto=no])
-
+enable_lto=yes)
 
 # By default, C is the only stage 1 language.
 stage1_languages=,c,
Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 166080)
+++ gcc/doc/install.texi	(working copy)
@@ -355,17 +355,6 @@ not installed in your default library se
 
 Necessary to build libgcj, the GCJ runtime.
 
-@item libelf version 0.8.12 (or later)
-
-Necessary to build link-time optimization (LTO) support.  It can be
-downloaded from @uref{http://www.mr511.de/software/libelf-0.8.12.tar.gz},
-though it is commonly available in several systems.  The version in
-IRIX 6.5 doesn't work since it lacks @file{gelf.h}.  The version in
-Solaris 2 does work.
-
-The @option{--with-libelf} configure option should be used if libelf is
-not installed in your default library search patch.
-
 @end table
 
 @heading Tools/packages necessary for modifying GCC
@@ -1650,20 +1639,9 @@ default for a native toolchain with an a
 GLIBC 2.11 or above, otherwise disabled.
 
 @item --enable-lto
+@itemx --disable-lto
 Enable support for link-time optimization (LTO).  This is enabled by
-default if a working libelf implementation is found (see
-@option{--with-libelf}).
-
-@item --with-libelf=@var{pathname}
-@itemx --with-libelf-include=@var{pathname}
-@itemx --with-libelf-lib=@var{pathname}
-If you do not have libelf installed in a standard location and you
-want to enable support for link-time optimization (LTO), you can
-explicitly specify the directory where libelf is installed
-(@samp{--with-libelf=@var{libelfinstalldir}}).  The
-@option{--with-libelf=@var{libelfinstalldir}} option is shorthand for
-@option{--with-libelf-include=@var{libelfinstalldir}/include}
-@option{--with-libelf-lib=@var{libelfinstalldir}/lib}.
+default, and may be disabled using @option{--disable-lto}.
 
 @item --enable-gold
 Enable support for using @command{gold} as the linker.  If gold support is

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

* Re: Discussion about merging Go frontend
  2010-11-01 18:23                   ` Ian Lance Taylor
@ 2010-11-02 10:51                     ` Paolo Bonzini
  2010-11-02 11:01                       ` Paolo Bonzini
  0 siblings, 1 reply; 68+ messages in thread
From: Paolo Bonzini @ 2010-11-02 10:51 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: Tom Tromey, Dave Korn, Andi Kleen, Andrew Pinski, Mark Mitchell,
	gcc, gcc-patches

On 11/01/2010 07:17 PM, Ian Lance Taylor wrote:
> Tom Tromey<tromey@redhat.com>  writes:
>
>>>>>>> "Ian" == Ian Lance Taylor<iant@google.com>  writes:
>>
>> Ian>  This patch puts the code in libiberty, but it could equally well go in
>> Ian>  gcc.  Anybody want to make an argument one way or another?
>>
>> Ian>  +extern const char *
>> Ian>  +objfile_attributes_compare (objfile_attributes *attrs1,
>>
>> GDB already uses the name "objfile" for one of its modules.
>> I don't think we have any name clashes with this patch right now, but I
>> would prefer to avoid the eventual confusion.
>> So, if this is in libiberty, could it please have a different name?
>
> Sure.
>
> Any suggestions?

readobj/objread?

Paolo

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

* Re: Discussion about merging Go frontend
  2010-11-02 10:51                     ` Paolo Bonzini
@ 2010-11-02 11:01                       ` Paolo Bonzini
  0 siblings, 0 replies; 68+ messages in thread
From: Paolo Bonzini @ 2010-11-02 11:01 UTC (permalink / raw)
  Cc: Ian Lance Taylor, Tom Tromey, Dave Korn, Andi Kleen,
	Andrew Pinski, Mark Mitchell, gcc, gcc-patches

On 11/02/2010 11:50 AM, Paolo Bonzini wrote:
> On 11/01/2010 07:17 PM, Ian Lance Taylor wrote:
>> Tom Tromey<tromey@redhat.com> writes:
>>
>>> Ian> This patch puts the code in libiberty, but it could equally well
>>> go in
>>> Ian> gcc. Anybody want to make an argument one way or another?
>>>
>>> Ian> +extern const char *
>>> Ian> +objfile_attributes_compare (objfile_attributes *attrs1,
>>>
>>> GDB already uses the name "objfile" for one of its modules.
>>> I don't think we have any name clashes with this patch right now, but I
>>> would prefer to avoid the eventual confusion.
>>> So, if this is in libiberty, could it please have a different name?
>>
>> Sure.
>>
>> Any suggestions?
>
> readobj/objread?

This obviously meant objread/objwrite. :)

Paolo

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

* Re: Discussion about merging Go frontend
  2010-11-01 22:30                   ` Ian Lance Taylor
@ 2010-11-02 15:06                     ` Ian Lance Taylor
  2010-11-02 17:58                       ` H.J. Lu
  2010-11-02 23:00                       ` Discussion about merging Go frontend Dave Korn
  2010-11-02 17:43                     ` H.J. Lu
  1 sibling, 2 replies; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-02 15:06 UTC (permalink / raw)
  To: gcc-patches

I have committed the simple-object (nee objfile) patches to libiberty,
include, gcc/lto and gcc top level.  Thanks to Dave Korn and Iain Sandoe
for testing and fixes for the COFF and Mach-O support.

I have not yet committed the top level configury patches or the gcc/doc
patch, pending the commit of Dave's patch to remove the use of libelf
from lto-plugin.

Please let me know about any problems.

Ian

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

* Re: Discussion about merging Go frontend
  2010-10-30 16:31                 ` Dave Korn
  2010-10-30 20:02                   ` [PATCH] Enable linker plugin for windows [was Re: Discussion about merging Go frontend] Dave Korn
@ 2010-11-02 15:12                   ` Ian Lance Taylor
  2010-11-02 22:22                     ` Dave Korn
  1 sibling, 1 reply; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-02 15:12 UTC (permalink / raw)
  To: Dave Korn; +Cc: gcc-patches

Dave Korn <dave.korn.cygwin@gmail.com> writes:

> +# Trying to get this information from gcc's config is tricky.
> +case $target in
> +  x86_64*-mingw*)
> +    SYM_STYLE=-DSYM_STYLE=ss_none
> +    ;;
> +  *-cygwin* | i?86*-mingw* )
> +    SYM_STYLE=-DSYM_STYLE=ss_win32
> +    ;;
> +  *)
> +    SYM_STYLE=-DSYM_STYLE=ss_none
> +    ;;
>  esac
> -
> -AC_SUBST(LTO_FORMAT)
> +AC_SUBST(SYM_STYLE)

It would seem more natural to use AC_DEFINE here.  Any reason not to do
that?


> +  else if (!strncmp (option, "-sym-style=", sizeof ("-sym-style=") - 1))
> +    {
> +      switch (option[sizeof ("-sym-style=")])
> +	{
> +	case 'w':
> +	  sym_style = ss_win32;
> +	  break;
> +	case 'u':
> +	  sym_style = ss_uscore;
> +	  break;
> +	default:
> +	  sym_style = ss_none;
> +	  break;
> +	}
> +    }

This looks wrong, because sizeof ("-sym-style=") will be 1 too large in
the switch clause.

And of course this code now has to use simple_object rather than
objfile.

Ian

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

* Re: Discussion about merging Go frontend
  2010-11-01 22:30                   ` Ian Lance Taylor
  2010-11-02 15:06                     ` Ian Lance Taylor
@ 2010-11-02 17:43                     ` H.J. Lu
  2010-11-02 18:01                       ` Ian Lance Taylor
  1 sibling, 1 reply; 68+ messages in thread
From: H.J. Lu @ 2010-11-02 17:43 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Tom Tromey, gcc-patches

On Mon, Nov 1, 2010 at 3:27 PM, Ian Lance Taylor <iant@google.com> wrote:
> Tom Tromey <tromey@redhat.com> writes:
>
>> GDB already uses the name "objfile" for one of its modules.
>> I don't think we have any name clashes with this patch right now, but I
>> would prefer to avoid the eventual confusion.
>> So, if this is in libiberty, could it please have a different name?
>
> OK, I renamed objfile to simple_object.
>
> This is the current patch, incorporating all suggestions so far.  There
> are still reportedly problems with the Mach-O code.
>
> Ian
>
>
> ChangeLog:
>
> 2010-11-01  Ian Lance Taylor  <iant@google.com>
>
>        * configure.ac: Don't set default_enable_lto.  Remove libelf tests.
>        * configure: Rebuild.
>
> include/ChangeLog:
>
> 2010-11-01  Ian Lance Taylor  <iant@google.com>
>
>        * simple-object.h: New file.
>
> libiberty/ChangeLog:
>
> 2010-11-01  Ian Lance Taylor  <iant@google.com>
>
>        * simple-object.c: New file.
>        * simple-object-common.h: New file.
>        * simple-object-elf.c: New file.
>        * simple-object-mach-o.c: New file.
>        * simple-object-coff.c: New file.
>        * simple-object.txh: New file.
>        * configure.ac: Add AC_TYPE_SSIZE_T.
>        * Makefile.in: Rebuild dependencies.
>        (CFILES): Add simple-object.c, simple-object-coff,
>        simple-object-elf.c, and simple-object-mach-o.c.
>        (REQUIRED_OFILES): Add corresponding object files.
>        * configure: Rebuild.
>        * config.in: Rebuild.
>        * functions.texi: Rebuild.
>
> gcc/ChangeLog:
>
> 2010-11-01  Ian Lance Taylor  <iant@google.com>
>
>        * configure.ac: Remove elf_getshdrstrndx test.  Don't substitute
>        LTO_BINARY_READER or LTO_USE_LIBELF.  Remove LIBELFLIBS and
>        LIBELFINC.  Remove HAVE_libelf.
>        * gcc/config.gcc: Don't set lto_binary_reader.
>        * gcc/Makefile.in (LIBELFLIBS, LIBELFINC): Remove variables.
>        (LTO_BINARY_READER, LTO_USE_LIBELF): Remove variables.
>        (LIBS): Remove $(LIBELFLIBS).
>        (INCLUDES): Remove $(LIBELFINC).
>        * doc/install.texi (Prerequisites): Remove libelf paragraphs.
>        (Configuration): Mention --disable-lto.  Remove --with-libelf
>        paragraph.
>        * configure: Rebuild.
>        * config.in: Rebuild.
>
> gcc/lto/ChangeLog:
>
> 2010-11-01  Ian Lance Taylor  <iant@google.com>
>
>        * lto-object.c: New file.
>        * lto-elf.c: Remove file.
>        * lto-macho.c: Remove file.
>        * lto-macho.h: Remove file.
>        * lto-coff.c: Remove file.
>        * lto-coff.h: Remove file.
>        * Make-lang.in (LTO_OBJS): Change lto/$(LTO_BINARY_READER).o to
>        lto/lto-object.o.
>        ($(LTO_EXE)): Remove $(LTO_USE_LIBELF)
>        (lto/lto-objfile.o): New target.
>        (lto/lto-elf.o, lto/lto-coff.o, lto/lto-macho.o): Remove targets.
>        (lto/lto.o): Remove $(LIBIBERTY_H).
>
>
>

This patch breaks gcc on Linux:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46273

-- 
H.J.

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

* Re: Discussion about merging Go frontend
  2010-11-02 15:06                     ` Ian Lance Taylor
@ 2010-11-02 17:58                       ` H.J. Lu
  2010-11-02 22:51                         ` Dave Korn
  2010-11-02 23:00                       ` Discussion about merging Go frontend Dave Korn
  1 sibling, 1 reply; 68+ messages in thread
From: H.J. Lu @ 2010-11-02 17:58 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

On Tue, Nov 2, 2010 at 7:56 AM, Ian Lance Taylor <iant@google.com> wrote:
> I have committed the simple-object (nee objfile) patches to libiberty,
> include, gcc/lto and gcc top level.  Thanks to Dave Korn and Iain Sandoe
> for testing and fixes for the COFF and Mach-O support.
>
> I have not yet committed the top level configury patches or the gcc/doc
> patch, pending the commit of Dave's patch to remove the use of libelf
> from lto-plugin.
>
> Please let me know about any problems.
>

GCC won't build any more since lto-plugin hasn't been converted:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46273

It is quite frustrating.

-- 
H.J.

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

* Re: Discussion about merging Go frontend
  2010-11-02 17:43                     ` H.J. Lu
@ 2010-11-02 18:01                       ` Ian Lance Taylor
  2010-11-02 18:06                         ` H.J. Lu
  0 siblings, 1 reply; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-02 18:01 UTC (permalink / raw)
  To: H.J. Lu; +Cc: gcc-patches

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

"H.J. Lu" <hjl.tools@gmail.com> writes:

> This patch breaks gcc on Linux:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46273

Sorry about that.  I did not test with the LTO plugin.

I have reverted the relevant portion of the patch, until Dave's patch
updating the lto plugin has been committed.

Ian


2010-11-02  Ian Lance Taylor  <iant@google.com>

	PR lto/46273
	* config.gcc: Revert last patch: set lto_binary_reader.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: config.gcc --]
[-- Type: text/x-diff, Size: 2031 bytes --]

Index: config.gcc
===================================================================
--- config.gcc	(revision 166189)
+++ config.gcc	(working copy)
@@ -219,6 +219,8 @@ default_gnu_indirect_function=no
 target_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
+# Selects the object file format reader/writer used by LTO.
+lto_binary_reader=lto-elf
 
 # Don't carry these over build->host->target.  Please.
 xm_file=
@@ -1158,11 +1160,13 @@ i[34567]86-*-darwin*)
 	# support.
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
+	lto_binary_reader=lto-macho
 	;;
 x86_64-*-darwin*)
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
 	tm_file="${tm_file} ${cpu_type}/darwin64.h"
+	lto_binary_reader=lto-macho
 	;;
 i[34567]86-*-elf*)
 	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
@@ -1417,6 +1421,7 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
 		thread_file='posix'
 	fi
 	use_gcc_stdint=wrap
+	lto_binary_reader=lto-coff
 	;;
 i[34567]86-*-mingw* | x86_64-*-mingw*)
 	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h"
@@ -1489,6 +1494,7 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
 	cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
 	default_use_cxa_atexit=yes
 	use_gcc_stdint=wrap
+	lto_binary_reader=lto-coff
 	case ${enable_threads} in
 	  "" | yes | win32)	  thread_file='win32'
 	  tmake_file="${tmake_file} i386/t-gthr-win32"
@@ -2000,6 +2006,7 @@ powerpc-*-darwin*)
 	    ;;
 	esac
 	tmake_file="${tmake_file} t-slibgcc-darwin"
+	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc64-*-darwin*)
@@ -2007,6 +2014,7 @@ powerpc64-*-darwin*)
 	extra_parts="crt2.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin"
 	tm_file="${tm_file} ${cpu_type}/darwin8.h ${cpu_type}/darwin64.h"
+	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc*-*-freebsd*)

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

* Re: Discussion about merging Go frontend
  2010-11-02 18:01                       ` Ian Lance Taylor
@ 2010-11-02 18:06                         ` H.J. Lu
  0 siblings, 0 replies; 68+ messages in thread
From: H.J. Lu @ 2010-11-02 18:06 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

On Tue, Nov 2, 2010 at 10:59 AM, Ian Lance Taylor <iant@google.com> wrote:
> "H.J. Lu" <hjl.tools@gmail.com> writes:
>
>> This patch breaks gcc on Linux:
>>
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46273
>
> Sorry about that.  I did not test with the LTO plugin.
>
> I have reverted the relevant portion of the patch, until Dave's patch
> updating the lto plugin has been committed.
>
> Ian
>
>
> 2010-11-02  Ian Lance Taylor  <iant@google.com>
>
>        PR lto/46273
>        * config.gcc: Revert last patch: set lto_binary_reader.
>

Thanks.


-- 
H.J.

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

* Re: Discussion about merging Go frontend
  2010-11-02 15:12                   ` Discussion about merging Go frontend Ian Lance Taylor
@ 2010-11-02 22:22                     ` Dave Korn
  2010-11-02 22:30                       ` Ian Lance Taylor
  2010-11-03  6:09                       ` Ralf Wildenhues
  0 siblings, 2 replies; 68+ messages in thread
From: Dave Korn @ 2010-11-02 22:22 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

On 02/11/2010 15:06, Ian Lance Taylor wrote:
> Dave Korn writes:
> 
>> +# Trying to get this information from gcc's config is tricky.
>> +case $target in
>> +  x86_64*-mingw*)
>> +    SYM_STYLE=-DSYM_STYLE=ss_none
>> +    ;;
>> +  *-cygwin* | i?86*-mingw* )
>> +    SYM_STYLE=-DSYM_STYLE=ss_win32
>> +    ;;
>> +  *)
>> +    SYM_STYLE=-DSYM_STYLE=ss_none
>> +    ;;
>>  esac
>> -
>> -AC_SUBST(LTO_FORMAT)
>> +AC_SUBST(SYM_STYLE)
> 
> It would seem more natural to use AC_DEFINE here.  Any reason not to do
> that?

  It seems a bit much overkill.  There's only a single -D right now, so why
not pass it straight through?  With AC_DEFINE I'd still have to import @DEFS@
into the makefile, just to get HAVE_CONFIG_H available at build time, and then
add a config.h with a single #define in it.  If there were several symbols to
define, or if there was already an AC_CONFIG_HEADER, I'd do it, but there
isn't yet, so why haul all that extra weight?

>> +  else if (!strncmp (option, "-sym-style=", sizeof ("-sym-style=") - 1))
>> +    {
>> +      switch (option[sizeof ("-sym-style=")])
>> +	{
>> +	case 'w':
>> +	  sym_style = ss_win32;
>> +	  break;
>> +	case 'u':
>> +	  sym_style = ss_uscore;
>> +	  break;
>> +	default:
>> +	  sym_style = ss_none;
>> +	  break;
>> +	}
>> +    }
> 
> This looks wrong, because sizeof ("-sym-style=") will be 1 too large in
> the switch clause.

  Oops, yes, thanks.

> And of course this code now has to use simple_object rather than
> objfile.

  Yep, I'm just revising it now.  Will spin those fixes in at the same time,
thanks for reviewing.  Let me know if you really want to insist on the
AC_DEFINE change, but if it's up to me I'd rather just leave it as it is.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-11-02 22:22                     ` Dave Korn
@ 2010-11-02 22:30                       ` Ian Lance Taylor
  2010-11-02 22:50                         ` Dave Korn
  2010-11-03  6:09                       ` Ralf Wildenhues
  1 sibling, 1 reply; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-02 22:30 UTC (permalink / raw)
  To: Dave Korn; +Cc: gcc-patches, ccoutant

Dave Korn <dave.korn.cygwin@gmail.com> writes:

> On 02/11/2010 15:06, Ian Lance Taylor wrote:
>
>> It would seem more natural to use AC_DEFINE here.  Any reason not to do
>> that?
>
>   It seems a bit much overkill.  There's only a single -D right now, so why
> not pass it straight through?  With AC_DEFINE I'd still have to import @DEFS@
> into the makefile, just to get HAVE_CONFIG_H available at build time, and then
> add a config.h with a single #define in it.  If there were several symbols to
> define, or if there was already an AC_CONFIG_HEADER, I'd do it, but there
> isn't yet, so why haul all that extra weight?

Because we will almost inevitably want it eventually?  I often agree
with that kind of argument, but in this case I lean more toward "start
as you plan to proceed."


>> And of course this code now has to use simple_object rather than
>> objfile.
>
>   Yep, I'm just revising it now.  Will spin those fixes in at the same time,
> thanks for reviewing.  Let me know if you really want to insist on the
> AC_DEFINE change, but if it's up to me I'd rather just leave it as it is.

I've CC'ed the official lto-plugin maintainer, Cary Coutant, to make the
call here.

Ian

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

* Re: Discussion about merging Go frontend
  2010-11-02 22:30                       ` Ian Lance Taylor
@ 2010-11-02 22:50                         ` Dave Korn
  0 siblings, 0 replies; 68+ messages in thread
From: Dave Korn @ 2010-11-02 22:50 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches, ccoutant

On 02/11/2010 22:30, Ian Lance Taylor wrote:

> Because we will almost inevitably want it eventually?  I often agree
> with that kind of argument, but in this case I lean more toward "start
> as you plan to proceed."

  Ah, hell with it.  I know you're right really.  :)

  I'll do it the full way.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-11-02 17:58                       ` H.J. Lu
@ 2010-11-02 22:51                         ` Dave Korn
  2010-11-03  0:16                           ` Dave Korn
  0 siblings, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-11-02 22:51 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Ian Lance Taylor, gcc-patches

On 02/11/2010 17:43, H.J. Lu wrote:
> On Tue, Nov 2, 2010 at 7:56 AM, Ian Lance Taylor <iant@google.com> wrote:
>> I have committed the simple-object (nee objfile) patches to libiberty,
>> include, gcc/lto and gcc top level.  Thanks to Dave Korn and Iain Sandoe
>> for testing and fixes for the COFF and Mach-O support.
>>
>> I have not yet committed the top level configury patches or the gcc/doc
>> patch, pending the commit of Dave's patch to remove the use of libelf
>> from lto-plugin.
>>
>> Please let me know about any problems.
>>
> 
> GCC won't build any more since lto-plugin hasn't been converted:
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46273
> 
> It is quite frustrating.

  I have a patch, I'll post it within the hour.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-11-02 15:06                     ` Ian Lance Taylor
  2010-11-02 17:58                       ` H.J. Lu
@ 2010-11-02 23:00                       ` Dave Korn
  2010-11-02 23:36                         ` Ian Lance Taylor
  1 sibling, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-11-02 23:00 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

On 02/11/2010 14:56, Ian Lance Taylor wrote:

> 
> Please let me know about any problems.

  You forgot the gcc/doc/install.texi part, as far as I can see.  Would you
like me to roll it into the lto-plugin fix?

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-11-02 23:00                       ` Discussion about merging Go frontend Dave Korn
@ 2010-11-02 23:36                         ` Ian Lance Taylor
  0 siblings, 0 replies; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-02 23:36 UTC (permalink / raw)
  To: Dave Korn; +Cc: gcc-patches

Dave Korn <dave.korn.cygwin@gmail.com> writes:

> On 02/11/2010 14:56, Ian Lance Taylor wrote:
>
>> 
>> Please let me know about any problems.
>
>   You forgot the gcc/doc/install.texi part, as far as I can see.  Would you
> like me to roll it into the lto-plugin fix?

I deliberately left it out because technically libelf is still required
until your patch is committed.  Same with the top level configury
patches.

Sure, if you want to roll the install.texi patch into yours, that would
be convenient.  Thanks.

Ian

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

* Re: Discussion about merging Go frontend
  2010-11-02 22:51                         ` Dave Korn
@ 2010-11-03  0:16                           ` Dave Korn
  2010-11-03  0:38                             ` Dave Korn
  0 siblings, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-11-03  0:16 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Ian Lance Taylor, gcc-patches

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

On 02/11/2010 23:13, Dave Korn wrote:
> On 02/11/2010 17:43, H.J. Lu wrote:
>> On Tue, Nov 2, 2010 at 7:56 AM, Ian Lance Taylor <iant@google.com> wrote:
>>> I have committed the simple-object (nee objfile) patches to libiberty,
>>> include, gcc/lto and gcc top level.  Thanks to Dave Korn and Iain Sandoe
>>> for testing and fixes for the COFF and Mach-O support.
>>>
>>> I have not yet committed the top level configury patches or the gcc/doc
>>> patch, pending the commit of Dave's patch to remove the use of libelf
>>> from lto-plugin.
>>>
>>> Please let me know about any problems.
>>>
>> GCC won't build any more since lto-plugin hasn't been converted:
>>
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46273
>>
>> It is quite frustrating.
> 
>   I have a patch, I'll post it within the hour.

  Well, close enough.  simpleobj-lto-plugin.diff switches over the lto-plugin
and incorporates Ian's changes to remove the last libelf parts from the
configury and docs.

ChangeLog:

2010-11-03  Ian Lance Taylor  <iant@google.com>

	* configure.ac: Don't set default_enable_lto.  Remove libelf tests.
	* configure: Rebuild.

gcc/ChangeLog:

2010-11-03  Ian Lance Taylor  <iant@google.com>

	* gcc/config.gcc: Don't set lto_binary_reader.
	* doc/install.texi (Prerequisites): Remove libelf paragraphs.
	(Configuration): Mention --disable-lto.  Remove --with-libelf
	paragraph.

lto-plugin/ChangeLog:

2010-11-03  Dave Korn  <dave.korn.cygwin@gmail.com>

	* lto-plugin.h: Delete.
	* lto-plugin-elf.c: Likewise.
	* lto-plugin-coff.c: Likewise.
	* configure.ac: Don't use libelf, don't source config.gcc.
	(LIBELFLIBS): Delete.
	(LIBELFINC): Delete.
	(LTO_FORMAT): Delete.
	(SYM_STYLE): Add AC_DEFINE var, set based on $target.
	(config.h): Add AC_CONFIG_HEADERS directive.
	* Makefile.am (LIBELFLIBS): Delete.
	(LIBELFINC): Delete.
	(LTO_FORMAT): Delete.
	(DEFS): Import.
	(AM_CPPFLAGS): Use it.  Don't use LIBELFINC.
	(liblto_plugin_la_SOURCES): Don't use LTO_FORMAT, don't include
	any object-format-specific source file in the link.
	(liblto_plugin_la_LIBADD): Don't use LIBELFLIBS.
	* config.h.in: Generate.
	* configure: Regenerate.
	* Makefile.in: Likewise.
	* lto-plugin.c (O_BINARY): Definition moved here from lto-plugin.h.
	(LTO_SEGMENT_NAME): New definition.
	(LTO_SECTION_PREFIX): Definition moved here from lto-plugin.h.
	(LTO_SECTION_PREFIX_LEN): New definition.
	(struct sym_aux): Struct definition moved here from lto-plugin.h.
	(struct plugin_symtab): Likewise.
	(struct plugin_objfile): Likewise.
	(struct plugin_objfile): New struct def.
	(enum symbol_style): New enum type.
	(add_symbols): Make static.
	(claimed_files): Likewise.
	(num_claimed_files): Likewise.
	(sym_style): New global.
	(check): Make static.
	(parse_table_entry): Likewise.  Respect sym_style when extracting
	symbol from symtab entry.
	(translate): Make static.
	(resolve_conflicts): Likewise.
	(process_symtab): New function, per-section callback version of
	old object-format-specific handling from deleted lto-plugin-elf.c.
	(claim_file_handler): Convert ELF-specific version from deleted
	lto-plugin-elf.c to simple_object interface and move here.
	(process_options): Allow new '-sym-style=' option.
	(onload): Don't call deleted onload_format_checks hook.

  Along with that, there's a tiny bugfix in simpleobj-coff-fix.diff

libiberty/ChangeLog:

2010-11-03  Dave Korn  <dave.korn.cygwin@gmail.com>

	* simple-object-coff.c (simple_object_coff_read_strtab): Use offset.

  And finally the simpleobj-lto-plugin-cygming.diff patch makes it work on
Cygwin and MinGW targets.

gcc/ChangeLog:

2010-11-03  Dave Korn  <dave.korn.cygwin@gmail.com>

	* gcc.c (PLUGIN_PASSTHROUGH_SPEC): New macro factored out from
	LINK_COMMAND_SPEC.
	(LINK_COMMAND_SPEC): Use it.
	(static_spec_functions[]): Add pass-through-libs entry.
	(pass_through_libs_spec_func): Add related spec function.
	* config/i386/cygming.h (PLUGIN_PASSTHROUGH_SPEC): Define.
	* doc/tm.texi.in (PLUGIN_PASSTHROUGH_SPEC): Document.
	(LINK_COMMAND_SPEC): Mention it.
	* doc/tm.texi: Regenerate.
	* doc/invoke.texi (pass-through-libs): Mention new spec function.

  I've just sent the lot for a testrun on x86_64 linux at the cfarm, and am
bootstrapping and testing it on the cygwin side here.

  OK for the first patch (simpleobj-lto-plugin.diff) when the linux tests pass
without regressions?  OK for the second two once the cygwin tests have passed?

    cheers,
      DaveK


[-- Attachment #2: simpleobj-lto-plugin.diff --]
[-- Type: text/x-c, Size: 30249 bytes --]

Index: configure.ac
===================================================================
--- configure.ac	(revision 166214)
+++ configure.ac	(working copy)
@@ -1654,175 +1654,8 @@ AC_SUBST(clooginc)
 AC_ARG_ENABLE(lto,
 [  --enable-lto            enable link time optimization support],
 enable_lto=$enableval,
-enable_lto=yes; default_enable_lto=yes)
+enable_lto=yes)
 
-
-ACX_ELF_TARGET_IFELSE([if test x"$enable_lto" = x"yes" ; then
-  # Make sure that libelf.h and gelf.h are available.
-  AC_ARG_WITH(libelf, [  --with-libelf=PATH       Specify prefix directory for the installed libelf package
-                          Equivalent to --with-libelf-include=PATH/include
-                          plus --with-libelf-lib=PATH/lib])
-
-  AC_ARG_WITH(libelf_include, [  --with-libelf-include=PATH Specify directory for installed libelf include files])
-
-  AC_ARG_WITH(libelf_lib, [  --with-libelf-lib=PATH   Specify the directory for the installed libelf library])
-
-  saved_CFLAGS="$CFLAGS"
-  saved_CPPFLAGS="$CPPFLAGS"
-  saved_LIBS="$LIBS"
-
-  case $with_libelf in 
-    "")
-      libelflibs="-lelf"
-      libelfinc="-I/usr/include/libelf"
-      ;;
-    *)
-      libelflibs="-L$with_libelf/lib -lelf"
-      libelfinc="-I$with_libelf/include -I$with_libelf/include/libelf"
-      LIBS="$libelflibs $LIBS"
-      ;;
-  esac
-
-  if test "x$with_libelf_include" != x; then
-    libelfinc="-I$with_libelf_include"
-  fi
-
-  if test "x$with_libelf_lib" != x; then
-    libelflibs="-L$with_libelf_lib -lelf"
-    LIBS="$libelflibs $LIBS"
-  fi
-
-  if test "x$with_libelf$with_libelf_include$with_libelf_lib" = x \
-     && test -d ${srcdir}/libelf; then
-    libelflibs='-L$$r/$(HOST_SUBDIR)/libelf/lib -lelf '
-    libelfinc='-D__LIBELF_INTERNAL__ -I$$r/$(HOST_SUBDIR)/libelf/lib -I$$s/libelf/lib'
-    LIBS="$libelflibs $LIBS"
-
- else
-
-  CFLAGS="$CFLAGS $libelfinc"
-  CPPFLAGS="$CPPFLAGS $libelfinc"
-  LIBS="$LIBS $libelflibs"
-
-  AC_CHECK_HEADERS(libelf.h, [have_libelf_h=yes])
-  AC_CHECK_HEADERS(gelf.h, [have_gelf_h=yes])
-
-  AC_CHECK_HEADERS(libelf/libelf.h, [have_libelf_libelf_h=yes])
-  AC_CHECK_HEADERS(libelf/gelf.h, [have_libelf_gelf_h=yes])
-
-  # If we couldn't find libelf.h and the user forced it, emit an error.
-  if test x"$have_libelf_h" != x"yes" \
-     && test x"$have_libelf_libelf_h" != x"yes" ; then
-    if test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([LTO support requires libelf.h or libelf/libelf.h.])
-    else
-      enable_lto=no
-      libelflibs=
-      libelfinc=
-    fi
-  fi
-
-  # If we couldn't find gelf.h and the user forced it, emit an error.
-  if test x"$have_gelf_h" != x"yes" \
-     && test x"$have_libelf_gelf_h" != x"yes" ; then
-    if test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([LTO support requires gelf.h or libelf/gelf.h.])
-    else
-      enable_lto=no
-      libelflibs=
-      libelfinc=
-    fi
-  fi
-
-  # Check that the detected libelf has the functions we need.  We cannot
-  # rely on just detecting the headers since they do not include 
-  # versioning information.  Add functions, if needed.
-  if test x"$enable_lto" = x"yes" ; then
-    AC_MSG_CHECKING([for the correct version of libelf])
-    AC_TRY_LINK(
-      [#include <libelf.h>],[
-      elf_errmsg (0);
-      elf_getscn (0, 0);
-      elf_nextscn (0, 0);
-      elf_strptr (0, 0, 0);
-      elf_getident (0, 0);
-      elf_begin (0, 0, 0);
-      elf_ndxscn (0);
-      elf_end (0);
-      ],
-      [AC_MSG_RESULT([yes]);],
-      [AC_MSG_RESULT([no]); enable_lto=no; libelflibs= ; libelfinc= ]
-    )
-
-    # Check for elf_getshdrstrndx or elf_getshstrndx.  The latter's flavor
-    # is determined in gcc/configure.ac.
-    if test x"$enable_lto" = x"yes" ; then
-      AC_MSG_CHECKING([for elf_getshdrstrndx])
-      AC_TRY_LINK(
-        [#include <libelf.h>],[
-	elf_getshdrstrndx (0, 0);
-        ],
-        [AC_MSG_RESULT([yes]);],
-        [AC_MSG_RESULT([no]);
-	 AC_MSG_CHECKING([for elf_getshstrndx])
-         AC_TRY_LINK(
-           [#include <libelf.h>],[
-	   elf_getshstrndx (0, 0);
-           ],
-           [AC_MSG_RESULT([yes]);],
-           [AC_MSG_RESULT([no]); enable_lto=no; libelflibs= ; libelfinc= ]
-         )]
-      )
-    fi
-
-    # If we couldn't enable LTO and the user forced it, emit an error.
-    if test x"$enable_lto" = x"no" \
-       && test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([To enable LTO, GCC requires libelf v0.8.12+.
-Try the --with-libelf, --with-libelf-include and --with-libelf-lib options
-to specify its location.])
-    fi
-  fi
-
-  CFLAGS="$saved_CFLAGS"
-  CPPFLAGS="$saved_CPPFLAGS"
-  LIBS="$saved_LIBS"
-
- fi
-
-  # Flags needed for libelf.
-  AC_SUBST(libelflibs)
-  AC_SUBST(libelfinc)
-  # ELF platforms build the lto-plugin when GOLD is in use.
-  build_lto_plugin=${ENABLE_GOLD}
-fi],[if test x"$default_enable_lto" = x"yes" ; then
-    case $target in
-      *-apple-darwin* | *-cygwin* | *-mingw*) ;;
-      # On other non-ELF platforms, LTO must be explicitly enabled.
-      *) enable_lto=no ;;
-    esac
-  else
-  # Apart from ELF platforms, only Windows and Darwin support LTO so far.
-  # It would also be nice to check the binutils support, but we don't
-  # have gcc_GAS_CHECK_FEATURE available here.  For now, we'll just
-  # warn during gcc/ subconfigure; unless you're bootstrapping with
-  # -flto it won't be needed until after installation anyway.
-    case $target in
-      *-cygwin* | *-mingw* | *-apple-darwin*) ;;
-      *) if test x"$enable_lto" = x"yes"; then
-	AC_MSG_ERROR([LTO support is not enabled for this target.])
-        fi
-      ;;
-    esac
-  fi
-  # Among non-ELF, only Windows platforms support the lto-plugin so far.
-  case $target in
-    *-cygwin* | *-mingw*) build_lto_plugin=yes ;;
-    *) ;;
-  esac
-  default_enable_lto=no])
-
-
 # By default, C is the only stage 1 language.
 stage1_languages=,c,
 
Index: lto-plugin/lto-plugin-elf.c
===================================================================
--- lto-plugin/lto-plugin-elf.c	(revision 166214)
+++ lto-plugin/lto-plugin-elf.c	(working copy)
@@ -1,157 +0,0 @@
-/* LTO plugin for gold.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
-   Contributed by Rafael Avila de Espindola (espindola@google.com).
-
-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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-#include <libiberty.h>
-#include <stdlib.h>
-#include <inttypes.h>
-
-/* The presence of gelf.h is checked by the toplevel configure script.  */
-#include <gelf.h>
-
-/* Common definitions that the object format dependent code needs.  */
-#include "lto-plugin.h"
-
-/* Process all lto symtabs of file ELF. */
-
-static int
-process_symtab (Elf *elf, struct plugin_symtab *out)
-{
-  int found = 0;
-  Elf_Scn *section = 0;
-  GElf_Ehdr header;
-  GElf_Ehdr *t = gelf_getehdr (elf, &header);
-  if (t == NULL)
-    return 0;
-  assert (t == &header);
-
-  while ((section = elf_nextscn(elf, section)) != 0)
-    {
-      GElf_Shdr shdr;
-      GElf_Shdr *tshdr = gelf_getshdr (section, &shdr);
-      Elf_Data *symtab;
-      const char *t;
-      assert (tshdr == &shdr);
-      t = elf_strptr (elf, header.e_shstrndx, shdr.sh_name);
-      assert (t != NULL);
-      if (strncmp (t, LTO_SECTION_PREFIX, strlen (LTO_SECTION_PREFIX)) == 0) 
-	{
-	  char *s = strrchr (t, '.');
-	  if (s)
-	      sscanf (s, ".%x", &out->id);
-	  symtab = elf_getdata (section, NULL);
-	  translate (symtab->d_buf, symtab->d_buf + symtab->d_size, out);
-	  found++;
-	}
-    }
-  return found;
-}
-
-/* Callback used by gold to check if the plugin will claim FILE. Writes
-   the result in CLAIMED. */
-
-enum ld_plugin_status
-claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
-{
-  enum ld_plugin_status status;
-  Elf *elf;
-  struct plugin_file_info lto_file;
-  int n;
-
-  memset (&lto_file, 0, sizeof (struct plugin_file_info));
-
-  if (file->offset != 0)
-    {
-      char *objname;
-      Elf *archive;
-      off_t offset;
-      /* We pass the offset of the actual file, not the archive header. */
-      int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
-                        (int64_t) file->offset);
-      check (t >= 0, LDPL_FATAL, "asprintf failed");
-      lto_file.name = objname;
-
-      archive = elf_begin (file->fd, ELF_C_READ, NULL);
-      check (elf_kind (archive) == ELF_K_AR, LDPL_FATAL,
-             "Not an archive and offset not 0");
-
-      /* elf_rand expects the offset to point to the ar header, not the
-         object itself. Subtract the size of the ar header (60 bytes).
-         We don't uses sizeof (struct ar_hd) to avoid including ar.h */
-
-      offset = file->offset - 60;
-      check (offset == elf_rand (archive, offset), LDPL_FATAL,
-             "could not seek in archive");
-      elf = elf_begin (file->fd, ELF_C_READ, archive);
-      check (elf != NULL, LDPL_FATAL, "could not find archive member");
-      elf_end (archive);
-    }
-  else
-    {
-      lto_file.name = xstrdup (file->name);
-      elf = elf_begin (file->fd, ELF_C_READ, NULL);
-    }
-  lto_file.handle = file->handle;
-
-  *claimed = 0;
-
-  if (!elf)
-    goto err;
-
-  n = process_symtab (elf, &lto_file.symtab);
-  if (n == 0)
-    goto err;
-
-  if (n > 1)
-    resolve_conflicts (&lto_file.symtab, &lto_file.conflicts);
-
-  status = add_symbols (file->handle, lto_file.symtab.nsyms,
-			lto_file.symtab.syms);
-  check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
-
-  *claimed = 1;
-  num_claimed_files++;
-  claimed_files =
-    xrealloc (claimed_files,
-	      num_claimed_files * sizeof (struct plugin_file_info));
-  claimed_files[num_claimed_files - 1] = lto_file;
-
-  goto cleanup;
-
- err:
-  free (lto_file.name);
-
- cleanup:
-  if (elf)
-    elf_end (elf);
-
-  return LDPS_OK;
-}
-
-/* Method called first thing at onload time to perform sanity checks.  */
-
-enum ld_plugin_status
-onload_format_checks (struct ld_plugin_tv *tv)
-{
-  unsigned version = elf_version (EV_CURRENT);
-  check (version != EV_NONE, LDPL_FATAL, "invalid ELF version");
-  return LDPS_OK;
-}
-
Index: lto-plugin/lto-plugin.h
===================================================================
--- lto-plugin/lto-plugin.h	(revision 166214)
+++ lto-plugin/lto-plugin.h	(working copy)
@@ -1,84 +0,0 @@
-/* Common declarations for LTO plugin for gold and/or GNU ld.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
-   Contributed by Rafael Avila de Espindola (espindola@google.com).
-
-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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include <stdbool.h>
-#include "plugin-api.h"
-
-/* LTO magic section name.  */
-
-#define LTO_SECTION_PREFIX ".gnu.lto_.symtab"
-
-/* The part of the symbol table the plugin has to keep track of. Note that we
-   must keep SYMS until all_symbols_read is called to give the linker time to
-   copy the symbol information. */
-
-struct sym_aux
-{
-  uint32_t slot;
-  unsigned id;
-  unsigned next_conflict;
-};
-
-struct plugin_symtab
-{
-  int nsyms;
-  struct sym_aux *aux;
-  struct ld_plugin_symbol *syms;
-  unsigned id;
-};
-
-/* All that we have to remember about a file. */
-
-struct plugin_file_info
-{
-  char *name;
-  void *handle;
-  struct plugin_symtab symtab;
-  struct plugin_symtab conflicts;
-};
-
-/* These are the methods supplied by one of the object format
-   dependent files lto-plugin-elf.c or lto-plugin-coff.c  */
-
-extern enum ld_plugin_status claim_file_handler 
-		(const struct ld_plugin_input_file *file, int *claimed);
-
-extern enum ld_plugin_status onload_format_checks (struct ld_plugin_tv *tv);
-
-/* These methods are made available to the object format
-   dependent files.  */
-
-extern void check (bool gate, enum ld_plugin_level level, const char *text);
-
-extern void translate (char *data, char *end, struct plugin_symtab *out);
-
-extern char *parse_table_entry (char *p, struct ld_plugin_symbol *entry,
-			struct sym_aux *aux);
-
-extern void resolve_conflicts (struct plugin_symtab *t,
-			struct plugin_symtab *conflicts);
-
-/* And this callback function is exposed.  */
-
-extern ld_plugin_add_symbols add_symbols;
-
-/* Along with these two variables.  */
-
-extern struct plugin_file_info *claimed_files;
-extern unsigned int num_claimed_files;
-
Index: lto-plugin/configure.ac
===================================================================
--- lto-plugin/configure.ac	(revision 166214)
+++ lto-plugin/configure.ac	(working copy)
@@ -6,18 +6,21 @@ AM_INIT_AUTOMAKE([foreign no-dist])
 AM_MAINTAINER_MODE
 AC_PROG_CC
 AC_SYS_LARGEFILE
-AC_ARG_VAR(LIBELFLIBS,[How to link libelf])
-AC_ARG_VAR(LIBELFINC,[How to find libelf include files])
 AM_PROG_LIBTOOL
 AC_SUBST(target_noncanonical)
-. ${srcdir}/../gcc/config.gcc
-case ${lto_binary_reader} in
-  *coff*) LTO_FORMAT=coff ;;
-  *elf*)  LTO_FORMAT=elf ;;
-  *) AC_MSG_ERROR([LTO plugin is not supported on this target.]) ;;
+# Trying to get this information from gcc's config is tricky.
+case $target in
+  x86_64*-mingw*)
+    AC_DEFINE([SYM_STYLE], [ss_none], [Default symbol style])
+    ;;
+  *-cygwin* | i?86*-mingw* )
+    AC_DEFINE([SYM_STYLE], [ss_win32], [Default symbol style])
+    ;;
+  *)
+    AC_DEFINE([SYM_STYLE], [ss_none], [Default symbol style])
+    ;;
 esac
-
-AC_SUBST(LTO_FORMAT)
 AC_TYPE_UINT64_T
 AC_CONFIG_FILES(Makefile)
+AC_CONFIG_HEADERS(config.h)
 AC_OUTPUT
Index: lto-plugin/lto-plugin-coff.c
===================================================================
--- lto-plugin/lto-plugin-coff.c	(revision 166214)
+++ lto-plugin/lto-plugin-coff.c	(working copy)
@@ -1,38 +0,0 @@
-/* LTO plugin for gold.
-   Copyright (C) 2010 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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-/* Common definitions that the object format dependent code needs.  */
-#include "lto-plugin.h"
-
-/* Callback used by gold to check if the plugin will claim FILE. Writes
-   the result in CLAIMED. */
-
-enum ld_plugin_status
-claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
-{
-  /* To be implemented; for now, simply do nothing.  */
-  return LDPS_OK;
-}
-
-/* Method called first thing at onload time to perform sanity checks.  */
-
-enum ld_plugin_status
-onload_format_checks (struct ld_plugin_tv *tv)
-{
-  return LDPS_OK;
-}
-
Index: lto-plugin/Makefile.am
===================================================================
--- lto-plugin/Makefile.am	(revision 166214)
+++ lto-plugin/Makefile.am	(working copy)
@@ -7,20 +7,13 @@ gcc_version := $(shell cat $(top_srcdir)/../gcc/BA
 target_noncanonical := @target_noncanonical@
 libexecsubdir := $(libexecdir)/gcc/$(target_noncanonical)/$(gcc_version)
 
-# How to find libelf
-LIBELFLIBS = @LIBELFLIBS@
-LIBELFINC = @LIBELFINC@
-
-# Which object format to parse.
-LTO_FORMAT = @LTO_FORMAT@
-
-AM_CPPFLAGS = -I$(top_srcdir)/../include $(LIBELFINC)
+AM_CPPFLAGS = -I$(top_srcdir)/../include $(DEFS)
 AM_CFLAGS = -Wall -Werror
 
 libexecsub_LTLIBRARIES = liblto_plugin.la
 
-liblto_plugin_la_SOURCES = lto-plugin.c lto-plugin-$(LTO_FORMAT).c
-liblto_plugin_la_LIBADD = $(LIBELFLIBS) \
+liblto_plugin_la_SOURCES = lto-plugin.c
+liblto_plugin_la_LIBADD = \
 	$(if $(wildcard ../libiberty/pic/libiberty.a),../libiberty/pic/libiberty.a,)
 liblto_plugin_la_LDFLAGS = -no-undefined -bindir $(libexecsubdir) \
 	$(if $(wildcard ../libiberty/pic/libiberty.a),,-Wc,../libiberty/libiberty.a)
Index: lto-plugin/lto-plugin.c
===================================================================
--- lto-plugin/lto-plugin.c	(revision 166214)
+++ lto-plugin/lto-plugin.c	(working copy)
@@ -32,6 +32,9 @@ along with this program; see the file COPYING3.  I
    -nop: Instead of running lto-wrapper, pass the original to the plugin. This
    only works if the input files are hybrid.  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 #include <assert.h>
 #include <string.h>
 #include <stdlib.h>
@@ -46,10 +49,73 @@ along with this program; see the file COPYING3.  I
 #include <libiberty.h>
 #include <hashtab.h>
 #include "../gcc/lto/common.h"
+#include "simple-object.h"
+#include "plugin-api.h"
 
-/* Common definitions for/from the object format dependent code.  */
-#include "lto-plugin.h"
+/* Handle opening elf files on hosts, such as Windows, that may use
+   text file handling that will break binary access.  */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
 
+/* Segment name for LTO sections.  This is only used for Mach-O.
+   FIXME: This needs to be kept in sync with darwin.c.  */
+
+#define LTO_SEGMENT_NAME "__GNU_LTO"
+
+/* LTO magic section name.  */
+
+#define LTO_SECTION_PREFIX	".gnu.lto_.symtab"
+#define LTO_SECTION_PREFIX_LEN	(sizeof (LTO_SECTION_PREFIX) - 1)
+
+/* The part of the symbol table the plugin has to keep track of. Note that we
+   must keep SYMS until all_symbols_read is called to give the linker time to
+   copy the symbol information. */
+
+struct sym_aux
+{
+  uint32_t slot;
+  unsigned id;
+  unsigned next_conflict;
+};
+
+struct plugin_symtab
+{
+  int nsyms;
+  struct sym_aux *aux;
+  struct ld_plugin_symbol *syms;
+  unsigned id;
+};
+
+/* Encapsulates object file data during symbol scan.  */
+struct plugin_objfile
+{
+  int found;
+  simple_object_read *objfile;
+  struct plugin_symtab *out;
+  const struct ld_plugin_input_file *file;
+};
+
+/* All that we have to remember about a file. */
+
+struct plugin_file_info
+{
+  char *name;
+  void *handle;
+  struct plugin_symtab symtab;
+  struct plugin_symtab conflicts;
+};
+
+/* Until ASM_OUTPUT_LABELREF can be hookized and decoupled from
+   stdio file streams, we do simple label translation here.  */
+
+enum symbol_style
+{
+  ss_none,	/* No underscore prefix. */
+  ss_win32,	/* Underscore prefix any symbol not beginning with '@'.  */
+  ss_uscore,	/* Underscore prefix all symbols.  */
+};
+
 static char *arguments_file_name;
 static ld_plugin_register_claim_file register_claim_file;
 static ld_plugin_register_all_symbols_read register_all_symbols_read;
@@ -58,14 +124,11 @@ static ld_plugin_register_cleanup register_cleanup
 static ld_plugin_add_input_file add_input_file;
 static ld_plugin_add_input_library add_input_library;
 static ld_plugin_message message;
+static ld_plugin_add_symbols add_symbols;
 
-/* These are not static because the object format dependent
-   claim_file hooks in lto-plugin-{coff,elf}.c need them.  */
-ld_plugin_add_symbols add_symbols;
+static struct plugin_file_info *claimed_files = NULL;
+static unsigned int num_claimed_files = 0;
 
-struct plugin_file_info *claimed_files = NULL;
-unsigned int num_claimed_files = 0;
-
 static char **output_files = NULL;
 static unsigned int num_output_files = 0;
 
@@ -79,7 +142,12 @@ static bool debug;
 static bool nop;
 static char *resolution_file = NULL;
 
-void
+/* Set by default from configure.ac, but can be overridden at runtime
+   by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
+   (in fact, only first letter of style arg is checked.)  */
+static enum symbol_style sym_style = SYM_STYLE;
+
+static void
 check (bool gate, enum ld_plugin_level level, const char *text)
 {
   if (gate)
@@ -100,7 +168,7 @@ check (bool gate, enum ld_plugin_level level, cons
    by P and the result is written in ENTRY. The slot number is stored in SLOT.
    Returns the address of the next entry. */
 
-char *
+static char *
 parse_table_entry (char *p, struct ld_plugin_symbol *entry, 
 		   struct sym_aux *aux)
 {
@@ -122,7 +190,24 @@ parse_table_entry (char *p, struct ld_plugin_symbo
       LDPV_HIDDEN
     };
 
-  entry->name = xstrdup (p);
+  switch (sym_style)
+    {
+    case ss_win32:
+      if (p[0] == '@')
+	{
+    /* cf. Duff's device.  */
+    case ss_none:
+	  entry->name = xstrdup (p);
+	  break;
+	}
+    /* FALL-THROUGH.  */
+    case ss_uscore:
+      entry->name = concat ("_", p, NULL);
+      break;
+    default:
+      check (false, LDPL_FATAL, "invalid symbol style requested");
+      break;
+    }
   while (*p)
     p++;
   p++;
@@ -165,7 +250,7 @@ parse_table_entry (char *p, struct ld_plugin_symbo
 /* Translate the IL symbol table located between DATA and END. Append the
    slots and symbols to OUT. */
 
-void
+static void
 translate (char *data, char *end, struct plugin_symtab *out)
 {
   struct sym_aux *aux;
@@ -621,7 +706,7 @@ static int symbol_strength (struct ld_plugin_symbo
    
    XXX how to handle common? */
 
-void
+static void
 resolve_conflicts (struct plugin_symtab *t, struct plugin_symtab *conflicts)
 {
   htab_t symtab = htab_create (t->nsyms, hash_sym, eq_sym, NULL);
@@ -689,6 +774,120 @@ resolve_conflicts (struct plugin_symtab *t, struct
   htab_delete (symtab);
 }
 
+/* Process one section of an object file.  */
+
+static int 
+process_symtab (void *data, const char *name, off_t offset, off_t length)
+{
+  struct plugin_objfile *obj = (struct plugin_objfile *)data;
+  char *s;
+  char *secdata;
+
+  if (strncmp (name, LTO_SECTION_PREFIX, LTO_SECTION_PREFIX_LEN) != 0)
+    return 1;
+
+  s = strrchr (name, '.');
+  if (s)
+    sscanf (s, ".%x", &obj->out->id);
+  secdata = xmalloc (length);
+  offset += obj->file->offset;
+  if (offset != lseek (obj->file->fd, offset, SEEK_SET)
+	|| length != read (obj->file->fd, secdata, length))
+    {
+      if (message)
+	message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
+      /* Force claim_file_handler to abandon this file.  */
+      obj->found = 0;
+      free (secdata);
+      return 0;
+    }
+
+  translate (secdata, secdata + length, obj->out);
+  obj->found++;
+  free (secdata);
+  return 1;
+}
+
+/* Callback used by gold to check if the plugin will claim FILE. Writes
+   the result in CLAIMED. */
+
+static enum ld_plugin_status
+claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
+{
+  enum ld_plugin_status status;
+  struct plugin_objfile obj;
+  struct plugin_file_info lto_file;
+  int err;
+  const char *errmsg;
+
+  memset (&lto_file, 0, sizeof (struct plugin_file_info));
+
+  if (file->offset != 0)
+    {
+      char *objname;
+      /* We pass the offset of the actual file, not the archive header. */
+      int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
+                        (int64_t) file->offset);
+      check (t >= 0, LDPL_FATAL, "asprintf failed");
+      lto_file.name = objname;
+    }
+  else
+    {
+      lto_file.name = xstrdup (file->name);
+    }
+  lto_file.handle = file->handle;
+
+  *claimed = 0;
+  obj.file = file;
+  obj.found = 0;
+  obj.out = &lto_file.symtab;
+  errmsg = NULL;
+  obj.objfile = simple_object_start_read (file->fd, file->offset, LTO_SEGMENT_NAME,
+			&errmsg, &err);
+  if (obj.objfile)
+    errmsg = simple_object_find_sections (obj.objfile, process_symtab, &obj, &err);
+
+  if (!obj.objfile || errmsg)
+    {
+      if (err && message)
+	message (LDPL_FATAL, "%s: %s: %s", file->name, errmsg,
+		xstrerror (err));
+      else if (message)
+	message (LDPL_FATAL, "%s: %s", file->name, errmsg);
+      goto err;
+    }
+
+  if (obj.found == 0)
+    goto err;
+
+  if (obj.found > 1)
+    resolve_conflicts (&lto_file.symtab, &lto_file.conflicts);
+
+  status = add_symbols (file->handle, lto_file.symtab.nsyms,
+			lto_file.symtab.syms);
+  check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
+
+  *claimed = 1;
+  num_claimed_files++;
+  claimed_files =
+    xrealloc (claimed_files,
+	      num_claimed_files * sizeof (struct plugin_file_info));
+  claimed_files[num_claimed_files - 1] = lto_file;
+
+  goto cleanup;
+
+ err:
+  free (lto_file.name);
+
+ cleanup:
+  if (obj.objfile)
+    simple_object_release_read (obj.objfile);
+  if (file->fd >= 0)
+    close (file->fd);
+
+  return LDPS_OK;
+}
+
 /* Parse the plugin options. */
 
 static void
@@ -706,6 +905,21 @@ process_option (const char *option)
       pass_through_items[num_pass_through_items - 1] =
           xstrdup (option + strlen ("-pass-through="));
     }
+  else if (!strncmp (option, "-sym-style=", sizeof ("-sym-style=") - 1))
+    {
+      switch (option[sizeof ("-sym-style=") - 1])
+	{
+	case 'w':
+	  sym_style = ss_win32;
+	  break;
+	case 'u':
+	  sym_style = ss_uscore;
+	  break;
+	default:
+	  sym_style = ss_none;
+	  break;
+	}
+    }
   else
     {
       int size;
@@ -727,10 +941,6 @@ onload (struct ld_plugin_tv *tv)
   struct ld_plugin_tv *p;
   enum ld_plugin_status status;
 
-  status = onload_format_checks (tv);
-  if (status != LDPS_OK)
-    return status;
-
   p = tv;
   while (p->tv_tag)
     {
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 166214)
+++ gcc/config.gcc	(working copy)
@@ -219,8 +219,6 @@ default_gnu_indirect_function=no
 target_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
-# Selects the object file format reader/writer used by LTO.
-lto_binary_reader=lto-elf
 
 # Don't carry these over build->host->target.  Please.
 xm_file=
@@ -1160,13 +1158,11 @@ i[34567]86-*-darwin*)
 	# support.
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
-	lto_binary_reader=lto-macho
 	;;
 x86_64-*-darwin*)
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
 	tm_file="${tm_file} ${cpu_type}/darwin64.h"
-	lto_binary_reader=lto-macho
 	;;
 i[34567]86-*-elf*)
 	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
@@ -1421,7 +1417,6 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
 		thread_file='posix'
 	fi
 	use_gcc_stdint=wrap
-	lto_binary_reader=lto-coff
 	;;
 i[34567]86-*-mingw* | x86_64-*-mingw*)
 	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h"
@@ -1494,7 +1489,6 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
 	cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
 	default_use_cxa_atexit=yes
 	use_gcc_stdint=wrap
-	lto_binary_reader=lto-coff
 	case ${enable_threads} in
 	  "" | yes | win32)	  thread_file='win32'
 	  tmake_file="${tmake_file} i386/t-gthr-win32"
@@ -2006,7 +2000,6 @@ powerpc-*-darwin*)
 	    ;;
 	esac
 	tmake_file="${tmake_file} t-slibgcc-darwin"
-	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc64-*-darwin*)
@@ -2014,7 +2007,6 @@ powerpc64-*-darwin*)
 	extra_parts="crt2.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin"
 	tm_file="${tm_file} ${cpu_type}/darwin8.h ${cpu_type}/darwin64.h"
-	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc*-*-freebsd*)
Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 166214)
+++ gcc/doc/install.texi	(working copy)
@@ -355,17 +355,6 @@ not installed in your default library search path.
 
 Necessary to build libgcj, the GCJ runtime.
 
-@item libelf version 0.8.12 (or later)
-
-Necessary to build link-time optimization (LTO) support.  It can be
-downloaded from @uref{http://www.mr511.de/software/libelf-0.8.12.tar.gz},
-though it is commonly available in several systems.  The version in
-IRIX 6.5 doesn't work since it lacks @file{gelf.h}.  The version in
-Solaris 2 does work.
-
-The @option{--with-libelf} configure option should be used if libelf is
-not installed in your default library search patch.
-
 @end table
 
 @heading Tools/packages necessary for modifying GCC
@@ -1650,21 +1639,10 @@ default for a native toolchain with an assembler t
 GLIBC 2.11 or above, otherwise disabled.
 
 @item --enable-lto
+@itemx --disable-lto
 Enable support for link-time optimization (LTO).  This is enabled by
-default if a working libelf implementation is found (see
-@option{--with-libelf}).
+default, and may be disabled using @option{--disable-lto}.
 
-@item --with-libelf=@var{pathname}
-@itemx --with-libelf-include=@var{pathname}
-@itemx --with-libelf-lib=@var{pathname}
-If you do not have libelf installed in a standard location and you
-want to enable support for link-time optimization (LTO), you can
-explicitly specify the directory where libelf is installed
-(@samp{--with-libelf=@var{libelfinstalldir}}).  The
-@option{--with-libelf=@var{libelfinstalldir}} option is shorthand for
-@option{--with-libelf-include=@var{libelfinstalldir}/include}
-@option{--with-libelf-lib=@var{libelfinstalldir}/lib}.
-
 @item --enable-gold
 Enable support for using @command{gold} as the linker.  If gold support is
 enabled together with @option{--enable-lto}, an additional directory

[-- Attachment #3: simpleobj-coff-fix.diff --]
[-- Type: text/x-c, Size: 620 bytes --]

Index: libiberty/simple-object-coff.c
===================================================================
--- libiberty/simple-object-coff.c	(revision 166214)
+++ libiberty/simple-object-coff.c	(working copy)
@@ -308,7 +308,8 @@ simple_object_coff_read_strtab (simple_object_read
   size_t strsize;
   char *strtab;
 
-  strtab_offset = ocr->symptr + ocr->nsyms * sizeof (struct external_syment);
+  strtab_offset = sobj->offset
+		+ ocr->symptr + ocr->nsyms * sizeof (struct external_syment);
   if (!simple_object_internal_read (sobj->descriptor, strtab_offset,
 				    strsizebuf, 4, errmsg, err))
     return NULL;

[-- Attachment #4: simpleobj-lto-plugin-cygming.diff --]
[-- Type: text/x-c, Size: 6063 bytes --]

Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	(revision 166214)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -394,6 +394,15 @@ The sequence in which libgcc and libc are specifie
 By default this is @code{%G %L %G}.
 @end defmac
 
+@defmac PLUGIN_PASSTHROUGH_SPEC
+This macro is used as part of @code{LINK_COMMAND_SPEC} when the LTO plugin
+is in use.  It allows the system's standard libraries to be sent to the
+plugin as @option{-pass-through} plugin options, which causes them to be
+added at the end of the link when it may be necessary to resolve new
+undefined references generated as LTO expands builtins from the IR.  The
+default definition should suit ELF platforms.
+@end defmac
+
 @defmac LINK_COMMAND_SPEC
 A C string constant giving the complete command line need to execute the
 linker.  When you do this, you will need to update your port each time a
@@ -401,7 +410,7 @@ change is made to the link command line within @fi
 define this macro only if you need to completely redefine the command
 line for invoking the linker and there is no other way to accomplish
 the effect you need.  Overriding this macro may be avoidable by overriding
-@code{LINK_GCC_C_SEQUENCE_SPEC} instead.
+@code{LINK_GCC_C_SEQUENCE_SPEC} and/or @code{PLUGIN_PASSTHROUGH_SPEC} instead.
 @end defmac
 
 @defmac LINK_ELIMINATE_DUPLICATE_LDIRECTORIES
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 166214)
+++ gcc/doc/invoke.texi	(working copy)
@@ -9683,6 +9683,17 @@ its usage:
 %:remove-outfile(-lm)
 @end smallexample
 
+@item @code{pass-through-libs}
+The @code{pass-through-libs} spec function takes any number of arguments.  It
+finds any @option{-l} options and any non-options (which it assumes are the
+names of linker input files) and returns a result containing all the found
+arguments each prepended by @option{-plugin-opt=-pass-through=} and joined by
+spaces.  This list is intended to be passed to the LTO linker plugin.
+
+@smallexample
+%:pass-through-libs(%G %L %G)
+@end smallexample
+
 @item @code{print-asm-header}
 The @code{print-asm-header} function takes no arguments and simply
 prints a banner like:
Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c	(revision 166214)
+++ gcc/gcc.c	(working copy)
@@ -287,6 +287,7 @@ static const char *print_asm_header_spec_function
 static const char *compare_debug_dump_opt_spec_function (int, const char **);
 static const char *compare_debug_self_opt_spec_function (int, const char **);
 static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
+static const char *pass_through_libs_spec_func (int, const char **);
 \f
 /* The Specs Language
 
@@ -531,6 +532,14 @@ proper position among the other output files.  */
 #define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
 #endif
 
+/* config.h can define PLUGIN_PASSTHROUGH_SPEC to control which
+   libraries are passed through to the final link by the lto-plugin.  */
+#ifndef PLUGIN_PASSTHROUGH_SPEC
+#define PLUGIN_PASSTHROUGH_SPEC " \
+  %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)} \
+  %{static:-plugin-opt=-pass-through=-lc} "
+#endif
+
 /* mudflap specs */
 #ifndef MFWRAP_SPEC
 /* XXX: valid only for GNU ld */
@@ -658,10 +667,8 @@ proper position among the other output files.  */
     %{fuse-linker-plugin: \
     -plugin %(linker_plugin_file) \
     -plugin-opt=%(lto_wrapper) \
-    -plugin-opt=-fresolution=%u.res \
-    %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)}	\
-    %{static:-plugin-opt=-pass-through=-lc}	\
-    } \
+    -plugin-opt=-fresolution=%u.res " \
+    PLUGIN_PASSTHROUGH_SPEC " } \
     %{flto:%<fcompare-debug*} %{fwhopr*:%<fcompare-debug*} \
     %{flto} %{fwhopr*} %l " LINK_PIE_SPEC \
    "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
@@ -1244,6 +1251,7 @@ static const struct spec_function static_spec_func
   { "compare-debug-dump-opt",	compare_debug_dump_opt_spec_function },
   { "compare-debug-self-opt",	compare_debug_self_opt_spec_function },
   { "compare-debug-auxbase-opt", compare_debug_auxbase_opt_spec_function },
+  { "pass-through-libs",	pass_through_libs_spec_func },
 #ifdef EXTRA_SPEC_FUNCTIONS
   EXTRA_SPEC_FUNCTIONS
 #endif
@@ -8216,3 +8224,33 @@ compare_debug_auxbase_opt_spec_function (int arg,
 
   return name;
 }
+
+/* %:pass-through-libs spec function.  Finds all -l options and input
+   file names in the lib spec passed to it, and makes a list of them
+   prepended with the plugin option to cause them to be passed through
+   to the final link after all the new object files have been added.  */
+
+const char *
+pass_through_libs_spec_func (int argc, const char **argv)
+{
+  char *prepended = xstrdup (" ");
+  int n;
+  /* Shlemiel the painter's algorithm.  Innately horrible, but at least
+     we know that there will never be more than a handful of strings to
+     concat, and it's only once per run, so it's not worth optimising.  */
+  for (n = 0; n < argc; n++)
+    {
+    char *old = prepended;
+      /* Anything that isn't an option is a full path to an output
+         file; pass it through if it ends in '.a'.  Among options,
+	 pass only -l.  */
+      if (argv[n][0] == '-'
+		? argv[n][1] == 'l'
+		: !strcmp (".a", argv[n] + strlen (argv[n]) - 2))
+	prepended = concat (prepended, "-plugin-opt=-pass-through=",
+		argv[n], " ", NULL);
+      if (prepended != old)
+	free (old);
+    }
+  return prepended;
+}
Index: gcc/config/i386/cygming.h
===================================================================
--- gcc/config/i386/cygming.h	(revision 166214)
+++ gcc/config/i386/cygming.h	(working copy)
@@ -161,6 +161,8 @@ along with GCC; see the file COPYING3.  If not see
 #define SUBTARGET_EXTRA_SPECS						\
   { "mingw_include_path", DEFAULT_TARGET_MACHINE }
 
+#define PLUGIN_PASSTHROUGH_SPEC " %:pass-through-libs(%o %G %L %G) "
+
 #undef MATH_LIBRARY
 #define MATH_LIBRARY ""
 

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

* Re: Discussion about merging Go frontend
  2010-11-03  0:16                           ` Dave Korn
@ 2010-11-03  0:38                             ` Dave Korn
  2010-11-03  2:04                               ` Dave Korn
  0 siblings, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-11-03  0:38 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Ian Lance Taylor, gcc-patches

On 03/11/2010 00:30, Dave Korn wrote:

>   Well, close enough.  simpleobj-lto-plugin.diff switches over the lto-plugin
> and incorporates Ian's changes to remove the last libelf parts from the
> configury and docs.
> 
> ChangeLog:
> 
> 2010-11-03  Ian Lance Taylor  <iant@google.com>
> 
> 	* configure.ac: Don't set default_enable_lto.  Remove libelf tests.
> 	* configure: Rebuild.

  Ah.  That bit is a little too keen, and causes lto-plugin never to be built
at all.  Respin coming shortly.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-11-03  0:38                             ` Dave Korn
@ 2010-11-03  2:04                               ` Dave Korn
  2010-11-03  4:29                                 ` Dave Korn
  2010-11-03  4:36                                 ` Ian Lance Taylor
  0 siblings, 2 replies; 68+ messages in thread
From: Dave Korn @ 2010-11-03  2:04 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Ian Lance Taylor, gcc-patches

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

On 03/11/2010 00:50, Dave Korn wrote:
> On 03/11/2010 00:30, Dave Korn wrote:
> 
>>   Well, close enough.  simpleobj-lto-plugin.diff switches over the lto-plugin
>> and incorporates Ian's changes to remove the last libelf parts from the
>> configury and docs.
>>
>> ChangeLog:
>>
>> 2010-11-03  Ian Lance Taylor  
>>
>> 	* configure.ac: Don't set default_enable_lto.  Remove libelf tests.
>> 	* configure: Rebuild.
> 
>   Ah.  That bit is a little too keen, and causes lto-plugin never to be built
> at all.  Respin coming shortly.

  Revised patch attached.  Changed top-level configury only; revised changelog
entry reads:

ChangeLog:

	* configure.ac: Remove libelf tests.  Build lto-plugin on ELF always
	and on other supported platforms whenever LTO is enabled.
	* configure: Rebuild.

  Rest of it as before(*).  Bootstrap+tests running.

    cheers,
      DaveK
-- 
(*) - http://gcc.gnu.org/ml/gcc-patches/2010-11/msg00229.html

[-- Attachment #2: simpleobj-lto-plugin.diff --]
[-- Type: text/x-c, Size: 29958 bytes --]

Index: configure.ac
===================================================================
--- configure.ac	(revision 166214)
+++ configure.ac	(working copy)
@@ -1656,149 +1656,12 @@ AC_ARG_ENABLE(lto,
 enable_lto=$enableval,
 enable_lto=yes; default_enable_lto=yes)
 
-
-ACX_ELF_TARGET_IFELSE([if test x"$enable_lto" = x"yes" ; then
-  # Make sure that libelf.h and gelf.h are available.
-  AC_ARG_WITH(libelf, [  --with-libelf=PATH       Specify prefix directory for the installed libelf package
-                          Equivalent to --with-libelf-include=PATH/include
-                          plus --with-libelf-lib=PATH/lib])
-
-  AC_ARG_WITH(libelf_include, [  --with-libelf-include=PATH Specify directory for installed libelf include files])
-
-  AC_ARG_WITH(libelf_lib, [  --with-libelf-lib=PATH   Specify the directory for the installed libelf library])
-
-  saved_CFLAGS="$CFLAGS"
-  saved_CPPFLAGS="$CPPFLAGS"
-  saved_LIBS="$LIBS"
-
-  case $with_libelf in 
-    "")
-      libelflibs="-lelf"
-      libelfinc="-I/usr/include/libelf"
-      ;;
-    *)
-      libelflibs="-L$with_libelf/lib -lelf"
-      libelfinc="-I$with_libelf/include -I$with_libelf/include/libelf"
-      LIBS="$libelflibs $LIBS"
-      ;;
-  esac
-
-  if test "x$with_libelf_include" != x; then
-    libelfinc="-I$with_libelf_include"
-  fi
-
-  if test "x$with_libelf_lib" != x; then
-    libelflibs="-L$with_libelf_lib -lelf"
-    LIBS="$libelflibs $LIBS"
-  fi
-
-  if test "x$with_libelf$with_libelf_include$with_libelf_lib" = x \
-     && test -d ${srcdir}/libelf; then
-    libelflibs='-L$$r/$(HOST_SUBDIR)/libelf/lib -lelf '
-    libelfinc='-D__LIBELF_INTERNAL__ -I$$r/$(HOST_SUBDIR)/libelf/lib -I$$s/libelf/lib'
-    LIBS="$libelflibs $LIBS"
-
- else
-
-  CFLAGS="$CFLAGS $libelfinc"
-  CPPFLAGS="$CPPFLAGS $libelfinc"
-  LIBS="$LIBS $libelflibs"
-
-  AC_CHECK_HEADERS(libelf.h, [have_libelf_h=yes])
-  AC_CHECK_HEADERS(gelf.h, [have_gelf_h=yes])
-
-  AC_CHECK_HEADERS(libelf/libelf.h, [have_libelf_libelf_h=yes])
-  AC_CHECK_HEADERS(libelf/gelf.h, [have_libelf_gelf_h=yes])
-
-  # If we couldn't find libelf.h and the user forced it, emit an error.
-  if test x"$have_libelf_h" != x"yes" \
-     && test x"$have_libelf_libelf_h" != x"yes" ; then
-    if test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([LTO support requires libelf.h or libelf/libelf.h.])
-    else
-      enable_lto=no
-      libelflibs=
-      libelfinc=
-    fi
-  fi
-
-  # If we couldn't find gelf.h and the user forced it, emit an error.
-  if test x"$have_gelf_h" != x"yes" \
-     && test x"$have_libelf_gelf_h" != x"yes" ; then
-    if test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([LTO support requires gelf.h or libelf/gelf.h.])
-    else
-      enable_lto=no
-      libelflibs=
-      libelfinc=
-    fi
-  fi
-
-  # Check that the detected libelf has the functions we need.  We cannot
-  # rely on just detecting the headers since they do not include 
-  # versioning information.  Add functions, if needed.
-  if test x"$enable_lto" = x"yes" ; then
-    AC_MSG_CHECKING([for the correct version of libelf])
-    AC_TRY_LINK(
-      [#include <libelf.h>],[
-      elf_errmsg (0);
-      elf_getscn (0, 0);
-      elf_nextscn (0, 0);
-      elf_strptr (0, 0, 0);
-      elf_getident (0, 0);
-      elf_begin (0, 0, 0);
-      elf_ndxscn (0);
-      elf_end (0);
-      ],
-      [AC_MSG_RESULT([yes]);],
-      [AC_MSG_RESULT([no]); enable_lto=no; libelflibs= ; libelfinc= ]
-    )
-
-    # Check for elf_getshdrstrndx or elf_getshstrndx.  The latter's flavor
-    # is determined in gcc/configure.ac.
-    if test x"$enable_lto" = x"yes" ; then
-      AC_MSG_CHECKING([for elf_getshdrstrndx])
-      AC_TRY_LINK(
-        [#include <libelf.h>],[
-	elf_getshdrstrndx (0, 0);
-        ],
-        [AC_MSG_RESULT([yes]);],
-        [AC_MSG_RESULT([no]);
-	 AC_MSG_CHECKING([for elf_getshstrndx])
-         AC_TRY_LINK(
-           [#include <libelf.h>],[
-	   elf_getshstrndx (0, 0);
-           ],
-           [AC_MSG_RESULT([yes]);],
-           [AC_MSG_RESULT([no]); enable_lto=no; libelflibs= ; libelfinc= ]
-         )]
-      )
-    fi
-
-    # If we couldn't enable LTO and the user forced it, emit an error.
-    if test x"$enable_lto" = x"no" \
-       && test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([To enable LTO, GCC requires libelf v0.8.12+.
-Try the --with-libelf, --with-libelf-include and --with-libelf-lib options
-to specify its location.])
-    fi
-  fi
-
-  CFLAGS="$saved_CFLAGS"
-  CPPFLAGS="$saved_CPPFLAGS"
-  LIBS="$saved_LIBS"
-
- fi
-
-  # Flags needed for libelf.
-  AC_SUBST(libelflibs)
-  AC_SUBST(libelfinc)
-  # ELF platforms build the lto-plugin when GOLD is in use.
-  build_lto_plugin=${ENABLE_GOLD}
-fi],[if test x"$default_enable_lto" = x"yes" ; then
+ACX_ELF_TARGET_IFELSE([# ELF platforms build the lto-plugin always.
+  build_lto_plugin=yes
+],[if test x"$default_enable_lto" = x"yes" ; then
     case $target in
       *-apple-darwin* | *-cygwin* | *-mingw*) ;;
-      # On other non-ELF platforms, LTO must be explicitly enabled.
+      # On other non-ELF platforms, LTO has yet to be validated.
       *) enable_lto=no ;;
     esac
   else
@@ -1816,11 +1679,12 @@ enable_lto=yes; default_enable_lto=yes)
     esac
   fi
   # Among non-ELF, only Windows platforms support the lto-plugin so far.
+  # Build it unless LTO was explicitly disabled.
   case $target in
-    *-cygwin* | *-mingw*) build_lto_plugin=yes ;;
+    *-cygwin* | *-mingw*) build_lto_plugin=$enable_lto ;;
     *) ;;
   esac
-  default_enable_lto=no])
+])
 
 
 # By default, C is the only stage 1 language.
Index: lto-plugin/lto-plugin-elf.c
===================================================================
--- lto-plugin/lto-plugin-elf.c	(revision 166214)
+++ lto-plugin/lto-plugin-elf.c	(working copy)
@@ -1,157 +0,0 @@
-/* LTO plugin for gold.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
-   Contributed by Rafael Avila de Espindola (espindola@google.com).
-
-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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-#include <libiberty.h>
-#include <stdlib.h>
-#include <inttypes.h>
-
-/* The presence of gelf.h is checked by the toplevel configure script.  */
-#include <gelf.h>
-
-/* Common definitions that the object format dependent code needs.  */
-#include "lto-plugin.h"
-
-/* Process all lto symtabs of file ELF. */
-
-static int
-process_symtab (Elf *elf, struct plugin_symtab *out)
-{
-  int found = 0;
-  Elf_Scn *section = 0;
-  GElf_Ehdr header;
-  GElf_Ehdr *t = gelf_getehdr (elf, &header);
-  if (t == NULL)
-    return 0;
-  assert (t == &header);
-
-  while ((section = elf_nextscn(elf, section)) != 0)
-    {
-      GElf_Shdr shdr;
-      GElf_Shdr *tshdr = gelf_getshdr (section, &shdr);
-      Elf_Data *symtab;
-      const char *t;
-      assert (tshdr == &shdr);
-      t = elf_strptr (elf, header.e_shstrndx, shdr.sh_name);
-      assert (t != NULL);
-      if (strncmp (t, LTO_SECTION_PREFIX, strlen (LTO_SECTION_PREFIX)) == 0) 
-	{
-	  char *s = strrchr (t, '.');
-	  if (s)
-	      sscanf (s, ".%x", &out->id);
-	  symtab = elf_getdata (section, NULL);
-	  translate (symtab->d_buf, symtab->d_buf + symtab->d_size, out);
-	  found++;
-	}
-    }
-  return found;
-}
-
-/* Callback used by gold to check if the plugin will claim FILE. Writes
-   the result in CLAIMED. */
-
-enum ld_plugin_status
-claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
-{
-  enum ld_plugin_status status;
-  Elf *elf;
-  struct plugin_file_info lto_file;
-  int n;
-
-  memset (&lto_file, 0, sizeof (struct plugin_file_info));
-
-  if (file->offset != 0)
-    {
-      char *objname;
-      Elf *archive;
-      off_t offset;
-      /* We pass the offset of the actual file, not the archive header. */
-      int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
-                        (int64_t) file->offset);
-      check (t >= 0, LDPL_FATAL, "asprintf failed");
-      lto_file.name = objname;
-
-      archive = elf_begin (file->fd, ELF_C_READ, NULL);
-      check (elf_kind (archive) == ELF_K_AR, LDPL_FATAL,
-             "Not an archive and offset not 0");
-
-      /* elf_rand expects the offset to point to the ar header, not the
-         object itself. Subtract the size of the ar header (60 bytes).
-         We don't uses sizeof (struct ar_hd) to avoid including ar.h */
-
-      offset = file->offset - 60;
-      check (offset == elf_rand (archive, offset), LDPL_FATAL,
-             "could not seek in archive");
-      elf = elf_begin (file->fd, ELF_C_READ, archive);
-      check (elf != NULL, LDPL_FATAL, "could not find archive member");
-      elf_end (archive);
-    }
-  else
-    {
-      lto_file.name = xstrdup (file->name);
-      elf = elf_begin (file->fd, ELF_C_READ, NULL);
-    }
-  lto_file.handle = file->handle;
-
-  *claimed = 0;
-
-  if (!elf)
-    goto err;
-
-  n = process_symtab (elf, &lto_file.symtab);
-  if (n == 0)
-    goto err;
-
-  if (n > 1)
-    resolve_conflicts (&lto_file.symtab, &lto_file.conflicts);
-
-  status = add_symbols (file->handle, lto_file.symtab.nsyms,
-			lto_file.symtab.syms);
-  check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
-
-  *claimed = 1;
-  num_claimed_files++;
-  claimed_files =
-    xrealloc (claimed_files,
-	      num_claimed_files * sizeof (struct plugin_file_info));
-  claimed_files[num_claimed_files - 1] = lto_file;
-
-  goto cleanup;
-
- err:
-  free (lto_file.name);
-
- cleanup:
-  if (elf)
-    elf_end (elf);
-
-  return LDPS_OK;
-}
-
-/* Method called first thing at onload time to perform sanity checks.  */
-
-enum ld_plugin_status
-onload_format_checks (struct ld_plugin_tv *tv)
-{
-  unsigned version = elf_version (EV_CURRENT);
-  check (version != EV_NONE, LDPL_FATAL, "invalid ELF version");
-  return LDPS_OK;
-}
-
Index: lto-plugin/lto-plugin.h
===================================================================
--- lto-plugin/lto-plugin.h	(revision 166214)
+++ lto-plugin/lto-plugin.h	(working copy)
@@ -1,84 +0,0 @@
-/* Common declarations for LTO plugin for gold and/or GNU ld.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
-   Contributed by Rafael Avila de Espindola (espindola@google.com).
-
-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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include <stdbool.h>
-#include "plugin-api.h"
-
-/* LTO magic section name.  */
-
-#define LTO_SECTION_PREFIX ".gnu.lto_.symtab"
-
-/* The part of the symbol table the plugin has to keep track of. Note that we
-   must keep SYMS until all_symbols_read is called to give the linker time to
-   copy the symbol information. */
-
-struct sym_aux
-{
-  uint32_t slot;
-  unsigned id;
-  unsigned next_conflict;
-};
-
-struct plugin_symtab
-{
-  int nsyms;
-  struct sym_aux *aux;
-  struct ld_plugin_symbol *syms;
-  unsigned id;
-};
-
-/* All that we have to remember about a file. */
-
-struct plugin_file_info
-{
-  char *name;
-  void *handle;
-  struct plugin_symtab symtab;
-  struct plugin_symtab conflicts;
-};
-
-/* These are the methods supplied by one of the object format
-   dependent files lto-plugin-elf.c or lto-plugin-coff.c  */
-
-extern enum ld_plugin_status claim_file_handler 
-		(const struct ld_plugin_input_file *file, int *claimed);
-
-extern enum ld_plugin_status onload_format_checks (struct ld_plugin_tv *tv);
-
-/* These methods are made available to the object format
-   dependent files.  */
-
-extern void check (bool gate, enum ld_plugin_level level, const char *text);
-
-extern void translate (char *data, char *end, struct plugin_symtab *out);
-
-extern char *parse_table_entry (char *p, struct ld_plugin_symbol *entry,
-			struct sym_aux *aux);
-
-extern void resolve_conflicts (struct plugin_symtab *t,
-			struct plugin_symtab *conflicts);
-
-/* And this callback function is exposed.  */
-
-extern ld_plugin_add_symbols add_symbols;
-
-/* Along with these two variables.  */
-
-extern struct plugin_file_info *claimed_files;
-extern unsigned int num_claimed_files;
-
Index: lto-plugin/configure.ac
===================================================================
--- lto-plugin/configure.ac	(revision 166214)
+++ lto-plugin/configure.ac	(working copy)
@@ -6,18 +6,21 @@ AM_INIT_AUTOMAKE([foreign no-dist])
 AM_MAINTAINER_MODE
 AC_PROG_CC
 AC_SYS_LARGEFILE
-AC_ARG_VAR(LIBELFLIBS,[How to link libelf])
-AC_ARG_VAR(LIBELFINC,[How to find libelf include files])
 AM_PROG_LIBTOOL
 AC_SUBST(target_noncanonical)
-. ${srcdir}/../gcc/config.gcc
-case ${lto_binary_reader} in
-  *coff*) LTO_FORMAT=coff ;;
-  *elf*)  LTO_FORMAT=elf ;;
-  *) AC_MSG_ERROR([LTO plugin is not supported on this target.]) ;;
+# Trying to get this information from gcc's config is tricky.
+case $target in
+  x86_64*-mingw*)
+    AC_DEFINE([SYM_STYLE], [ss_none], [Default symbol style])
+    ;;
+  *-cygwin* | i?86*-mingw* )
+    AC_DEFINE([SYM_STYLE], [ss_win32], [Default symbol style])
+    ;;
+  *)
+    AC_DEFINE([SYM_STYLE], [ss_none], [Default symbol style])
+    ;;
 esac
-
-AC_SUBST(LTO_FORMAT)
 AC_TYPE_UINT64_T
 AC_CONFIG_FILES(Makefile)
+AC_CONFIG_HEADERS(config.h)
 AC_OUTPUT
Index: lto-plugin/lto-plugin-coff.c
===================================================================
--- lto-plugin/lto-plugin-coff.c	(revision 166214)
+++ lto-plugin/lto-plugin-coff.c	(working copy)
@@ -1,38 +0,0 @@
-/* LTO plugin for gold.
-   Copyright (C) 2010 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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-/* Common definitions that the object format dependent code needs.  */
-#include "lto-plugin.h"
-
-/* Callback used by gold to check if the plugin will claim FILE. Writes
-   the result in CLAIMED. */
-
-enum ld_plugin_status
-claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
-{
-  /* To be implemented; for now, simply do nothing.  */
-  return LDPS_OK;
-}
-
-/* Method called first thing at onload time to perform sanity checks.  */
-
-enum ld_plugin_status
-onload_format_checks (struct ld_plugin_tv *tv)
-{
-  return LDPS_OK;
-}
-
Index: lto-plugin/Makefile.am
===================================================================
--- lto-plugin/Makefile.am	(revision 166214)
+++ lto-plugin/Makefile.am	(working copy)
@@ -7,20 +7,13 @@ gcc_version := $(shell cat $(top_srcdir)/../gcc/BA
 target_noncanonical := @target_noncanonical@
 libexecsubdir := $(libexecdir)/gcc/$(target_noncanonical)/$(gcc_version)
 
-# How to find libelf
-LIBELFLIBS = @LIBELFLIBS@
-LIBELFINC = @LIBELFINC@
-
-# Which object format to parse.
-LTO_FORMAT = @LTO_FORMAT@
-
-AM_CPPFLAGS = -I$(top_srcdir)/../include $(LIBELFINC)
+AM_CPPFLAGS = -I$(top_srcdir)/../include $(DEFS)
 AM_CFLAGS = -Wall -Werror
 
 libexecsub_LTLIBRARIES = liblto_plugin.la
 
-liblto_plugin_la_SOURCES = lto-plugin.c lto-plugin-$(LTO_FORMAT).c
-liblto_plugin_la_LIBADD = $(LIBELFLIBS) \
+liblto_plugin_la_SOURCES = lto-plugin.c
+liblto_plugin_la_LIBADD = \
 	$(if $(wildcard ../libiberty/pic/libiberty.a),../libiberty/pic/libiberty.a,)
 liblto_plugin_la_LDFLAGS = -no-undefined -bindir $(libexecsubdir) \
 	$(if $(wildcard ../libiberty/pic/libiberty.a),,-Wc,../libiberty/libiberty.a)
Index: lto-plugin/lto-plugin.c
===================================================================
--- lto-plugin/lto-plugin.c	(revision 166214)
+++ lto-plugin/lto-plugin.c	(working copy)
@@ -32,6 +32,9 @@ along with this program; see the file COPYING3.  I
    -nop: Instead of running lto-wrapper, pass the original to the plugin. This
    only works if the input files are hybrid.  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 #include <assert.h>
 #include <string.h>
 #include <stdlib.h>
@@ -46,10 +49,73 @@ along with this program; see the file COPYING3.  I
 #include <libiberty.h>
 #include <hashtab.h>
 #include "../gcc/lto/common.h"
+#include "simple-object.h"
+#include "plugin-api.h"
 
-/* Common definitions for/from the object format dependent code.  */
-#include "lto-plugin.h"
+/* Handle opening elf files on hosts, such as Windows, that may use
+   text file handling that will break binary access.  */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
 
+/* Segment name for LTO sections.  This is only used for Mach-O.
+   FIXME: This needs to be kept in sync with darwin.c.  */
+
+#define LTO_SEGMENT_NAME "__GNU_LTO"
+
+/* LTO magic section name.  */
+
+#define LTO_SECTION_PREFIX	".gnu.lto_.symtab"
+#define LTO_SECTION_PREFIX_LEN	(sizeof (LTO_SECTION_PREFIX) - 1)
+
+/* The part of the symbol table the plugin has to keep track of. Note that we
+   must keep SYMS until all_symbols_read is called to give the linker time to
+   copy the symbol information. */
+
+struct sym_aux
+{
+  uint32_t slot;
+  unsigned id;
+  unsigned next_conflict;
+};
+
+struct plugin_symtab
+{
+  int nsyms;
+  struct sym_aux *aux;
+  struct ld_plugin_symbol *syms;
+  unsigned id;
+};
+
+/* Encapsulates object file data during symbol scan.  */
+struct plugin_objfile
+{
+  int found;
+  simple_object_read *objfile;
+  struct plugin_symtab *out;
+  const struct ld_plugin_input_file *file;
+};
+
+/* All that we have to remember about a file. */
+
+struct plugin_file_info
+{
+  char *name;
+  void *handle;
+  struct plugin_symtab symtab;
+  struct plugin_symtab conflicts;
+};
+
+/* Until ASM_OUTPUT_LABELREF can be hookized and decoupled from
+   stdio file streams, we do simple label translation here.  */
+
+enum symbol_style
+{
+  ss_none,	/* No underscore prefix. */
+  ss_win32,	/* Underscore prefix any symbol not beginning with '@'.  */
+  ss_uscore,	/* Underscore prefix all symbols.  */
+};
+
 static char *arguments_file_name;
 static ld_plugin_register_claim_file register_claim_file;
 static ld_plugin_register_all_symbols_read register_all_symbols_read;
@@ -58,14 +124,11 @@ static ld_plugin_register_cleanup register_cleanup
 static ld_plugin_add_input_file add_input_file;
 static ld_plugin_add_input_library add_input_library;
 static ld_plugin_message message;
+static ld_plugin_add_symbols add_symbols;
 
-/* These are not static because the object format dependent
-   claim_file hooks in lto-plugin-{coff,elf}.c need them.  */
-ld_plugin_add_symbols add_symbols;
+static struct plugin_file_info *claimed_files = NULL;
+static unsigned int num_claimed_files = 0;
 
-struct plugin_file_info *claimed_files = NULL;
-unsigned int num_claimed_files = 0;
-
 static char **output_files = NULL;
 static unsigned int num_output_files = 0;
 
@@ -79,7 +142,12 @@ static bool debug;
 static bool nop;
 static char *resolution_file = NULL;
 
-void
+/* Set by default from configure.ac, but can be overridden at runtime
+   by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
+   (in fact, only first letter of style arg is checked.)  */
+static enum symbol_style sym_style = SYM_STYLE;
+
+static void
 check (bool gate, enum ld_plugin_level level, const char *text)
 {
   if (gate)
@@ -100,7 +168,7 @@ check (bool gate, enum ld_plugin_level level, cons
    by P and the result is written in ENTRY. The slot number is stored in SLOT.
    Returns the address of the next entry. */
 
-char *
+static char *
 parse_table_entry (char *p, struct ld_plugin_symbol *entry, 
 		   struct sym_aux *aux)
 {
@@ -122,7 +190,24 @@ parse_table_entry (char *p, struct ld_plugin_symbo
       LDPV_HIDDEN
     };
 
-  entry->name = xstrdup (p);
+  switch (sym_style)
+    {
+    case ss_win32:
+      if (p[0] == '@')
+	{
+    /* cf. Duff's device.  */
+    case ss_none:
+	  entry->name = xstrdup (p);
+	  break;
+	}
+    /* FALL-THROUGH.  */
+    case ss_uscore:
+      entry->name = concat ("_", p, NULL);
+      break;
+    default:
+      check (false, LDPL_FATAL, "invalid symbol style requested");
+      break;
+    }
   while (*p)
     p++;
   p++;
@@ -165,7 +250,7 @@ parse_table_entry (char *p, struct ld_plugin_symbo
 /* Translate the IL symbol table located between DATA and END. Append the
    slots and symbols to OUT. */
 
-void
+static void
 translate (char *data, char *end, struct plugin_symtab *out)
 {
   struct sym_aux *aux;
@@ -621,7 +706,7 @@ static int symbol_strength (struct ld_plugin_symbo
    
    XXX how to handle common? */
 
-void
+static void
 resolve_conflicts (struct plugin_symtab *t, struct plugin_symtab *conflicts)
 {
   htab_t symtab = htab_create (t->nsyms, hash_sym, eq_sym, NULL);
@@ -689,6 +774,120 @@ resolve_conflicts (struct plugin_symtab *t, struct
   htab_delete (symtab);
 }
 
+/* Process one section of an object file.  */
+
+static int 
+process_symtab (void *data, const char *name, off_t offset, off_t length)
+{
+  struct plugin_objfile *obj = (struct plugin_objfile *)data;
+  char *s;
+  char *secdata;
+
+  if (strncmp (name, LTO_SECTION_PREFIX, LTO_SECTION_PREFIX_LEN) != 0)
+    return 1;
+
+  s = strrchr (name, '.');
+  if (s)
+    sscanf (s, ".%x", &obj->out->id);
+  secdata = xmalloc (length);
+  offset += obj->file->offset;
+  if (offset != lseek (obj->file->fd, offset, SEEK_SET)
+	|| length != read (obj->file->fd, secdata, length))
+    {
+      if (message)
+	message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
+      /* Force claim_file_handler to abandon this file.  */
+      obj->found = 0;
+      free (secdata);
+      return 0;
+    }
+
+  translate (secdata, secdata + length, obj->out);
+  obj->found++;
+  free (secdata);
+  return 1;
+}
+
+/* Callback used by gold to check if the plugin will claim FILE. Writes
+   the result in CLAIMED. */
+
+static enum ld_plugin_status
+claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
+{
+  enum ld_plugin_status status;
+  struct plugin_objfile obj;
+  struct plugin_file_info lto_file;
+  int err;
+  const char *errmsg;
+
+  memset (&lto_file, 0, sizeof (struct plugin_file_info));
+
+  if (file->offset != 0)
+    {
+      char *objname;
+      /* We pass the offset of the actual file, not the archive header. */
+      int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
+                        (int64_t) file->offset);
+      check (t >= 0, LDPL_FATAL, "asprintf failed");
+      lto_file.name = objname;
+    }
+  else
+    {
+      lto_file.name = xstrdup (file->name);
+    }
+  lto_file.handle = file->handle;
+
+  *claimed = 0;
+  obj.file = file;
+  obj.found = 0;
+  obj.out = &lto_file.symtab;
+  errmsg = NULL;
+  obj.objfile = simple_object_start_read (file->fd, file->offset, LTO_SEGMENT_NAME,
+			&errmsg, &err);
+  if (obj.objfile)
+    errmsg = simple_object_find_sections (obj.objfile, process_symtab, &obj, &err);
+
+  if (!obj.objfile || errmsg)
+    {
+      if (err && message)
+	message (LDPL_FATAL, "%s: %s: %s", file->name, errmsg,
+		xstrerror (err));
+      else if (message)
+	message (LDPL_FATAL, "%s: %s", file->name, errmsg);
+      goto err;
+    }
+
+  if (obj.found == 0)
+    goto err;
+
+  if (obj.found > 1)
+    resolve_conflicts (&lto_file.symtab, &lto_file.conflicts);
+
+  status = add_symbols (file->handle, lto_file.symtab.nsyms,
+			lto_file.symtab.syms);
+  check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
+
+  *claimed = 1;
+  num_claimed_files++;
+  claimed_files =
+    xrealloc (claimed_files,
+	      num_claimed_files * sizeof (struct plugin_file_info));
+  claimed_files[num_claimed_files - 1] = lto_file;
+
+  goto cleanup;
+
+ err:
+  free (lto_file.name);
+
+ cleanup:
+  if (obj.objfile)
+    simple_object_release_read (obj.objfile);
+  if (file->fd >= 0)
+    close (file->fd);
+
+  return LDPS_OK;
+}
+
 /* Parse the plugin options. */
 
 static void
@@ -706,6 +905,21 @@ process_option (const char *option)
       pass_through_items[num_pass_through_items - 1] =
           xstrdup (option + strlen ("-pass-through="));
     }
+  else if (!strncmp (option, "-sym-style=", sizeof ("-sym-style=") - 1))
+    {
+      switch (option[sizeof ("-sym-style=") - 1])
+	{
+	case 'w':
+	  sym_style = ss_win32;
+	  break;
+	case 'u':
+	  sym_style = ss_uscore;
+	  break;
+	default:
+	  sym_style = ss_none;
+	  break;
+	}
+    }
   else
     {
       int size;
@@ -727,10 +941,6 @@ onload (struct ld_plugin_tv *tv)
   struct ld_plugin_tv *p;
   enum ld_plugin_status status;
 
-  status = onload_format_checks (tv);
-  if (status != LDPS_OK)
-    return status;
-
   p = tv;
   while (p->tv_tag)
     {
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 166214)
+++ gcc/config.gcc	(working copy)
@@ -219,8 +219,6 @@ default_gnu_indirect_function=no
 target_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
-# Selects the object file format reader/writer used by LTO.
-lto_binary_reader=lto-elf
 
 # Don't carry these over build->host->target.  Please.
 xm_file=
@@ -1160,13 +1158,11 @@ i[34567]86-*-darwin*)
 	# support.
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
-	lto_binary_reader=lto-macho
 	;;
 x86_64-*-darwin*)
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
 	tm_file="${tm_file} ${cpu_type}/darwin64.h"
-	lto_binary_reader=lto-macho
 	;;
 i[34567]86-*-elf*)
 	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
@@ -1421,7 +1417,6 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
 		thread_file='posix'
 	fi
 	use_gcc_stdint=wrap
-	lto_binary_reader=lto-coff
 	;;
 i[34567]86-*-mingw* | x86_64-*-mingw*)
 	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h"
@@ -1494,7 +1489,6 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
 	cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
 	default_use_cxa_atexit=yes
 	use_gcc_stdint=wrap
-	lto_binary_reader=lto-coff
 	case ${enable_threads} in
 	  "" | yes | win32)	  thread_file='win32'
 	  tmake_file="${tmake_file} i386/t-gthr-win32"
@@ -2006,7 +2000,6 @@ powerpc-*-darwin*)
 	    ;;
 	esac
 	tmake_file="${tmake_file} t-slibgcc-darwin"
-	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc64-*-darwin*)
@@ -2014,7 +2007,6 @@ powerpc64-*-darwin*)
 	extra_parts="crt2.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin"
 	tm_file="${tm_file} ${cpu_type}/darwin8.h ${cpu_type}/darwin64.h"
-	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc*-*-freebsd*)
Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 166214)
+++ gcc/doc/install.texi	(working copy)
@@ -355,17 +355,6 @@ not installed in your default library search path.
 
 Necessary to build libgcj, the GCJ runtime.
 
-@item libelf version 0.8.12 (or later)
-
-Necessary to build link-time optimization (LTO) support.  It can be
-downloaded from @uref{http://www.mr511.de/software/libelf-0.8.12.tar.gz},
-though it is commonly available in several systems.  The version in
-IRIX 6.5 doesn't work since it lacks @file{gelf.h}.  The version in
-Solaris 2 does work.
-
-The @option{--with-libelf} configure option should be used if libelf is
-not installed in your default library search patch.
-
 @end table
 
 @heading Tools/packages necessary for modifying GCC
@@ -1650,21 +1639,10 @@ default for a native toolchain with an assembler t
 GLIBC 2.11 or above, otherwise disabled.
 
 @item --enable-lto
+@itemx --disable-lto
 Enable support for link-time optimization (LTO).  This is enabled by
-default if a working libelf implementation is found (see
-@option{--with-libelf}).
+default, and may be disabled using @option{--disable-lto}.
 
-@item --with-libelf=@var{pathname}
-@itemx --with-libelf-include=@var{pathname}
-@itemx --with-libelf-lib=@var{pathname}
-If you do not have libelf installed in a standard location and you
-want to enable support for link-time optimization (LTO), you can
-explicitly specify the directory where libelf is installed
-(@samp{--with-libelf=@var{libelfinstalldir}}).  The
-@option{--with-libelf=@var{libelfinstalldir}} option is shorthand for
-@option{--with-libelf-include=@var{libelfinstalldir}/include}
-@option{--with-libelf-lib=@var{libelfinstalldir}/lib}.
-
 @item --enable-gold
 Enable support for using @command{gold} as the linker.  If gold support is
 enabled together with @option{--enable-lto}, an additional directory

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

* Re: Discussion about merging Go frontend
  2010-11-03  2:04                               ` Dave Korn
@ 2010-11-03  4:29                                 ` Dave Korn
  2010-11-03  4:46                                   ` Dave Korn
  2010-11-03  4:36                                 ` Ian Lance Taylor
  1 sibling, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-11-03  4:29 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Ian Lance Taylor, gcc-patches

On 03/11/2010 01:25, Dave Korn wrote:

>   Revised patch attached.  Changed top-level configury only; revised changelog
> entry reads:
> 
> ChangeLog:
> 
> 	* configure.ac: Remove libelf tests.  Build lto-plugin on ELF always
> 	and on other supported platforms whenever LTO is enabled.
> 	* configure: Rebuild.
> 
>   Rest of it as before(*).  Bootstrap+tests running.

  Something went wrong:

> Executing on host: /home/davek/gcc/obj/gcc/xgcc -B/home/davek/gcc/obj/gcc/
> linker_plugin10991.c -flto -fuse-linker-plugin -o linker_plugin10991.exe
> (timeout = 300)
> gold: fatal error: /usr/lib/../lib64/libc.so: file not recognized
> collect2: ld returned 1 exit status
> compiler exited with status 1
> output is:
> gold: fatal error: /usr/lib/../lib64/libc.so: file not recognized
> collect2: ld returned 1 exit status
> 
> UNSUPPORTED: /n/10/davek/gcc/gcc/gcc/testsuite/gcc.dg/lto/20100722-1_0.c

  The libc.so in question is a linker script:

> davek@gcc10:~/state/patched/2010_11_03_02_55_55/patched$ cat /usr/lib/../lib64/libc.so
> /* GNU ld script
>    Use the shared library, but some functions are only in
>    the static library, so try that secondarily.  */
> OUTPUT_FORMAT(elf64-x86-64)
> GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a  AS_NEEDED ( /lib/ld-linux-x86-64.so.2 ) )

  Unfortunately I didn't think to use the -savecompilers option, so I'll have
to build it again before I can figure out what went wrong.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-11-03  2:04                               ` Dave Korn
  2010-11-03  4:29                                 ` Dave Korn
@ 2010-11-03  4:36                                 ` Ian Lance Taylor
  2010-11-03  4:43                                   ` Dave Korn
  1 sibling, 1 reply; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-03  4:36 UTC (permalink / raw)
  To: Dave Korn; +Cc: H.J. Lu, gcc-patches

Dave Korn <dave.korn.cygwin@gmail.com> writes:

> +  secdata = xmalloc (length);

secdata = XNEWVEC (char *, length);

+  free (secdata);

XDELETEVEC (secdata);


I assume you ran both autoconf and autoheader.

This is OK with those changes if it bootstraps on GNU/Linux.

Thanks.

Ian

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

* Re: Discussion about merging Go frontend
  2010-11-03  4:36                                 ` Ian Lance Taylor
@ 2010-11-03  4:43                                   ` Dave Korn
  2010-11-03  4:47                                     ` Ian Lance Taylor
  0 siblings, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-11-03  4:43 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: H.J. Lu, gcc-patches

On 03/11/2010 04:29, Ian Lance Taylor wrote:
> Dave Korn <dave.korn.cygwin@gmail.com> writes:
> 
>> +  secdata = xmalloc (length);
> 
> secdata = XNEWVEC (char *, length);
> 
> +  free (secdata);
> 
> XDELETEVEC (secdata);

  The whole rest of the file (that I didn't change) is crawling with xmalloc,
xrealloc, xcalloc and free calls.  I didn't want to break the convention.  Do
I have to change them all as well?

> I assume you ran both autoconf and autoheader.

  Yep.  And automake.

> This is OK with those changes if it bootstraps on GNU/Linux.

  The version prior to these changes bootstrapped OK, but the plugin didn't
work right, falling over a linker script.  I need to investigate whether it
was gold or the plugin that was the actual source of the error.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-11-03  4:29                                 ` Dave Korn
@ 2010-11-03  4:46                                   ` Dave Korn
  0 siblings, 0 replies; 68+ messages in thread
From: Dave Korn @ 2010-11-03  4:46 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Ian Lance Taylor, gcc-patches

On 03/11/2010 04:41, Dave Korn wrote:

>   Something went wrong:
> 
>> Executing on host: /home/davek/gcc/obj/gcc/xgcc -B/home/davek/gcc/obj/gcc/
>> linker_plugin10991.c -flto -fuse-linker-plugin -o linker_plugin10991.exe
>> (timeout = 300)
>> gold: fatal error: /usr/lib/../lib64/libc.so: file not recognized
>> collect2: ld returned 1 exit status
>> compiler exited with status 1
>> output is:
>> gold: fatal error: /usr/lib/../lib64/libc.so: file not recognized
>> collect2: ld returned 1 exit status
>>
>> UNSUPPORTED: /n/10/davek/gcc/gcc/gcc/testsuite/gcc.dg/lto/20100722-1_0.c
> 
>   The libc.so in question is a linker script:
> 
>> davek@gcc10:~/state/patched/2010_11_03_02_55_55/patched$ cat /usr/lib/../lib64/libc.so
>> /* GNU ld script
>>    Use the shared library, but some functions are only in
>>    the static library, so try that secondarily.  */
>> OUTPUT_FORMAT(elf64-x86-64)
>> GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a  AS_NEEDED ( /lib/ld-linux-x86-64.so.2 ) )
> 
>   Unfortunately I didn't think to use the -savecompilers option, so I'll have
> to build it again before I can figure out what went wrong.

  Actually, I think I can see it anyway.  simple_object_start_read returns
that when it doesn't recognize the object format.  We should just return
without claiming the file in that case.  It can be distinguished by getting a
NULL return and an errmsg from the call to simple_object_start_read(), but the
err value being zero.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-11-03  4:43                                   ` Dave Korn
@ 2010-11-03  4:47                                     ` Ian Lance Taylor
  2010-11-03  5:06                                       ` Dave Korn
  0 siblings, 1 reply; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-03  4:47 UTC (permalink / raw)
  To: Dave Korn; +Cc: gcc-patches

Dave Korn <dave.korn.cygwin@gmail.com> writes:

> On 03/11/2010 04:29, Ian Lance Taylor wrote:
>> Dave Korn <dave.korn.cygwin@gmail.com> writes:
>> 
>>> +  secdata = xmalloc (length);
>> 
>> secdata = XNEWVEC (char *, length);
>> 
>> +  free (secdata);
>> 
>> XDELETEVEC (secdata);
>
>   The whole rest of the file (that I didn't change) is crawling with xmalloc,
> xrealloc, xcalloc and free calls.  I didn't want to break the convention.  Do
> I have to change them all as well?

Well, no, I guess not.  We can leave this for later.

>   The version prior to these changes bootstrapped OK, but the plugin didn't
> work right, falling over a linker script.  I need to investigate whether it
> was gold or the plugin that was the actual source of the error.

The "file not recognized" error is coming from simple_object_start_read,
which (naturally) does not recognize the linker script as an object
file.  The LTO plugin code is reporting that error.

Looking at the existing lto-plugin-elf.c, it simply returns LDPS_OK when
it is given a filename at offset 0 which elf_begin can not open.  I
guess your code should do the same.

Ian

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

* Re: Discussion about merging Go frontend
  2010-11-03  4:47                                     ` Ian Lance Taylor
@ 2010-11-03  5:06                                       ` Dave Korn
  2010-11-03  5:40                                         ` Dave Korn
  0 siblings, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-11-03  5:06 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

On 03/11/2010 04:45, Ian Lance Taylor wrote:
> Dave Korn <dave.korn.cygwin@gmail.com> writes:
> 
>> On 03/11/2010 04:29, Ian Lance Taylor wrote:
>>> Dave Korn <dave.korn.cygwin@gmail.com> writes:
>>>
>>>> +  secdata = xmalloc (length);
>>> secdata = XNEWVEC (char *, length);
>>>
>>> +  free (secdata);
>>>
>>> XDELETEVEC (secdata);
>>   The whole rest of the file (that I didn't change) is crawling with xmalloc,
>> xrealloc, xcalloc and free calls.  I didn't want to break the convention.  Do
>> I have to change them all as well?
> 
> Well, no, I guess not.  We can leave this for later.
> 
>>   The version prior to these changes bootstrapped OK, but the plugin didn't
>> work right, falling over a linker script.  I need to investigate whether it
>> was gold or the plugin that was the actual source of the error.
> 
> The "file not recognized" error is coming from simple_object_start_read,
> which (naturally) does not recognize the linker script as an object
> file.  The LTO plugin code is reporting that error.
> 
> Looking at the existing lto-plugin-elf.c, it simply returns LDPS_OK when
> it is given a filename at offset 0 which elf_begin can not open.  I
> guess your code should do the same.

  :) I see our emails crossed in the ether.  Just preparing a (hopefully
final!) spin.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-11-03  5:06                                       ` Dave Korn
@ 2010-11-03  5:40                                         ` Dave Korn
  2010-11-03  9:47                                           ` Dave Korn
  0 siblings, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-11-03  5:40 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

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

On 03/11/2010 05:10, Dave Korn wrote:

>   :) I see our emails crossed in the ether.  Just preparing a (hopefully
> final!) spin.

  This is underway on the cfarm.  No changes to the previous changelogs with
this revision.

    cheers,
      DaveK


[-- Attachment #2: simpleobj-lto-plugin-take2.diff --]
[-- Type: text/x-c, Size: 49965 bytes --]

Index: configure.ac
===================================================================
--- configure.ac	(revision 166214)
+++ configure.ac	(working copy)
@@ -1656,149 +1656,12 @@ AC_ARG_ENABLE(lto,
 enable_lto=$enableval,
 enable_lto=yes; default_enable_lto=yes)
 
-
-ACX_ELF_TARGET_IFELSE([if test x"$enable_lto" = x"yes" ; then
-  # Make sure that libelf.h and gelf.h are available.
-  AC_ARG_WITH(libelf, [  --with-libelf=PATH       Specify prefix directory for the installed libelf package
-                          Equivalent to --with-libelf-include=PATH/include
-                          plus --with-libelf-lib=PATH/lib])
-
-  AC_ARG_WITH(libelf_include, [  --with-libelf-include=PATH Specify directory for installed libelf include files])
-
-  AC_ARG_WITH(libelf_lib, [  --with-libelf-lib=PATH   Specify the directory for the installed libelf library])
-
-  saved_CFLAGS="$CFLAGS"
-  saved_CPPFLAGS="$CPPFLAGS"
-  saved_LIBS="$LIBS"
-
-  case $with_libelf in 
-    "")
-      libelflibs="-lelf"
-      libelfinc="-I/usr/include/libelf"
-      ;;
-    *)
-      libelflibs="-L$with_libelf/lib -lelf"
-      libelfinc="-I$with_libelf/include -I$with_libelf/include/libelf"
-      LIBS="$libelflibs $LIBS"
-      ;;
-  esac
-
-  if test "x$with_libelf_include" != x; then
-    libelfinc="-I$with_libelf_include"
-  fi
-
-  if test "x$with_libelf_lib" != x; then
-    libelflibs="-L$with_libelf_lib -lelf"
-    LIBS="$libelflibs $LIBS"
-  fi
-
-  if test "x$with_libelf$with_libelf_include$with_libelf_lib" = x \
-     && test -d ${srcdir}/libelf; then
-    libelflibs='-L$$r/$(HOST_SUBDIR)/libelf/lib -lelf '
-    libelfinc='-D__LIBELF_INTERNAL__ -I$$r/$(HOST_SUBDIR)/libelf/lib -I$$s/libelf/lib'
-    LIBS="$libelflibs $LIBS"
-
- else
-
-  CFLAGS="$CFLAGS $libelfinc"
-  CPPFLAGS="$CPPFLAGS $libelfinc"
-  LIBS="$LIBS $libelflibs"
-
-  AC_CHECK_HEADERS(libelf.h, [have_libelf_h=yes])
-  AC_CHECK_HEADERS(gelf.h, [have_gelf_h=yes])
-
-  AC_CHECK_HEADERS(libelf/libelf.h, [have_libelf_libelf_h=yes])
-  AC_CHECK_HEADERS(libelf/gelf.h, [have_libelf_gelf_h=yes])
-
-  # If we couldn't find libelf.h and the user forced it, emit an error.
-  if test x"$have_libelf_h" != x"yes" \
-     && test x"$have_libelf_libelf_h" != x"yes" ; then
-    if test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([LTO support requires libelf.h or libelf/libelf.h.])
-    else
-      enable_lto=no
-      libelflibs=
-      libelfinc=
-    fi
-  fi
-
-  # If we couldn't find gelf.h and the user forced it, emit an error.
-  if test x"$have_gelf_h" != x"yes" \
-     && test x"$have_libelf_gelf_h" != x"yes" ; then
-    if test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([LTO support requires gelf.h or libelf/gelf.h.])
-    else
-      enable_lto=no
-      libelflibs=
-      libelfinc=
-    fi
-  fi
-
-  # Check that the detected libelf has the functions we need.  We cannot
-  # rely on just detecting the headers since they do not include 
-  # versioning information.  Add functions, if needed.
-  if test x"$enable_lto" = x"yes" ; then
-    AC_MSG_CHECKING([for the correct version of libelf])
-    AC_TRY_LINK(
-      [#include <libelf.h>],[
-      elf_errmsg (0);
-      elf_getscn (0, 0);
-      elf_nextscn (0, 0);
-      elf_strptr (0, 0, 0);
-      elf_getident (0, 0);
-      elf_begin (0, 0, 0);
-      elf_ndxscn (0);
-      elf_end (0);
-      ],
-      [AC_MSG_RESULT([yes]);],
-      [AC_MSG_RESULT([no]); enable_lto=no; libelflibs= ; libelfinc= ]
-    )
-
-    # Check for elf_getshdrstrndx or elf_getshstrndx.  The latter's flavor
-    # is determined in gcc/configure.ac.
-    if test x"$enable_lto" = x"yes" ; then
-      AC_MSG_CHECKING([for elf_getshdrstrndx])
-      AC_TRY_LINK(
-        [#include <libelf.h>],[
-	elf_getshdrstrndx (0, 0);
-        ],
-        [AC_MSG_RESULT([yes]);],
-        [AC_MSG_RESULT([no]);
-	 AC_MSG_CHECKING([for elf_getshstrndx])
-         AC_TRY_LINK(
-           [#include <libelf.h>],[
-	   elf_getshstrndx (0, 0);
-           ],
-           [AC_MSG_RESULT([yes]);],
-           [AC_MSG_RESULT([no]); enable_lto=no; libelflibs= ; libelfinc= ]
-         )]
-      )
-    fi
-
-    # If we couldn't enable LTO and the user forced it, emit an error.
-    if test x"$enable_lto" = x"no" \
-       && test x"$default_enable_lto" != x"yes" ; then
-      AC_MSG_ERROR([To enable LTO, GCC requires libelf v0.8.12+.
-Try the --with-libelf, --with-libelf-include and --with-libelf-lib options
-to specify its location.])
-    fi
-  fi
-
-  CFLAGS="$saved_CFLAGS"
-  CPPFLAGS="$saved_CPPFLAGS"
-  LIBS="$saved_LIBS"
-
- fi
-
-  # Flags needed for libelf.
-  AC_SUBST(libelflibs)
-  AC_SUBST(libelfinc)
-  # ELF platforms build the lto-plugin when GOLD is in use.
-  build_lto_plugin=${ENABLE_GOLD}
-fi],[if test x"$default_enable_lto" = x"yes" ; then
+ACX_ELF_TARGET_IFELSE([# ELF platforms build the lto-plugin always.
+  build_lto_plugin=yes
+],[if test x"$default_enable_lto" = x"yes" ; then
     case $target in
       *-apple-darwin* | *-cygwin* | *-mingw*) ;;
-      # On other non-ELF platforms, LTO must be explicitly enabled.
+      # On other non-ELF platforms, LTO has yet to be validated.
       *) enable_lto=no ;;
     esac
   else
@@ -1816,11 +1679,12 @@ enable_lto=yes; default_enable_lto=yes)
     esac
   fi
   # Among non-ELF, only Windows platforms support the lto-plugin so far.
+  # Build it unless LTO was explicitly disabled.
   case $target in
-    *-cygwin* | *-mingw*) build_lto_plugin=yes ;;
+    *-cygwin* | *-mingw*) build_lto_plugin=$enable_lto ;;
     *) ;;
   esac
-  default_enable_lto=no])
+])
 
 
 # By default, C is the only stage 1 language.
Index: lto-plugin/lto-plugin-elf.c
===================================================================
--- lto-plugin/lto-plugin-elf.c	(revision 166214)
+++ lto-plugin/lto-plugin-elf.c	(working copy)
@@ -1,157 +0,0 @@
-/* LTO plugin for gold.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
-   Contributed by Rafael Avila de Espindola (espindola@google.com).
-
-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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-#include <libiberty.h>
-#include <stdlib.h>
-#include <inttypes.h>
-
-/* The presence of gelf.h is checked by the toplevel configure script.  */
-#include <gelf.h>
-
-/* Common definitions that the object format dependent code needs.  */
-#include "lto-plugin.h"
-
-/* Process all lto symtabs of file ELF. */
-
-static int
-process_symtab (Elf *elf, struct plugin_symtab *out)
-{
-  int found = 0;
-  Elf_Scn *section = 0;
-  GElf_Ehdr header;
-  GElf_Ehdr *t = gelf_getehdr (elf, &header);
-  if (t == NULL)
-    return 0;
-  assert (t == &header);
-
-  while ((section = elf_nextscn(elf, section)) != 0)
-    {
-      GElf_Shdr shdr;
-      GElf_Shdr *tshdr = gelf_getshdr (section, &shdr);
-      Elf_Data *symtab;
-      const char *t;
-      assert (tshdr == &shdr);
-      t = elf_strptr (elf, header.e_shstrndx, shdr.sh_name);
-      assert (t != NULL);
-      if (strncmp (t, LTO_SECTION_PREFIX, strlen (LTO_SECTION_PREFIX)) == 0) 
-	{
-	  char *s = strrchr (t, '.');
-	  if (s)
-	      sscanf (s, ".%x", &out->id);
-	  symtab = elf_getdata (section, NULL);
-	  translate (symtab->d_buf, symtab->d_buf + symtab->d_size, out);
-	  found++;
-	}
-    }
-  return found;
-}
-
-/* Callback used by gold to check if the plugin will claim FILE. Writes
-   the result in CLAIMED. */
-
-enum ld_plugin_status
-claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
-{
-  enum ld_plugin_status status;
-  Elf *elf;
-  struct plugin_file_info lto_file;
-  int n;
-
-  memset (&lto_file, 0, sizeof (struct plugin_file_info));
-
-  if (file->offset != 0)
-    {
-      char *objname;
-      Elf *archive;
-      off_t offset;
-      /* We pass the offset of the actual file, not the archive header. */
-      int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
-                        (int64_t) file->offset);
-      check (t >= 0, LDPL_FATAL, "asprintf failed");
-      lto_file.name = objname;
-
-      archive = elf_begin (file->fd, ELF_C_READ, NULL);
-      check (elf_kind (archive) == ELF_K_AR, LDPL_FATAL,
-             "Not an archive and offset not 0");
-
-      /* elf_rand expects the offset to point to the ar header, not the
-         object itself. Subtract the size of the ar header (60 bytes).
-         We don't uses sizeof (struct ar_hd) to avoid including ar.h */
-
-      offset = file->offset - 60;
-      check (offset == elf_rand (archive, offset), LDPL_FATAL,
-             "could not seek in archive");
-      elf = elf_begin (file->fd, ELF_C_READ, archive);
-      check (elf != NULL, LDPL_FATAL, "could not find archive member");
-      elf_end (archive);
-    }
-  else
-    {
-      lto_file.name = xstrdup (file->name);
-      elf = elf_begin (file->fd, ELF_C_READ, NULL);
-    }
-  lto_file.handle = file->handle;
-
-  *claimed = 0;
-
-  if (!elf)
-    goto err;
-
-  n = process_symtab (elf, &lto_file.symtab);
-  if (n == 0)
-    goto err;
-
-  if (n > 1)
-    resolve_conflicts (&lto_file.symtab, &lto_file.conflicts);
-
-  status = add_symbols (file->handle, lto_file.symtab.nsyms,
-			lto_file.symtab.syms);
-  check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
-
-  *claimed = 1;
-  num_claimed_files++;
-  claimed_files =
-    xrealloc (claimed_files,
-	      num_claimed_files * sizeof (struct plugin_file_info));
-  claimed_files[num_claimed_files - 1] = lto_file;
-
-  goto cleanup;
-
- err:
-  free (lto_file.name);
-
- cleanup:
-  if (elf)
-    elf_end (elf);
-
-  return LDPS_OK;
-}
-
-/* Method called first thing at onload time to perform sanity checks.  */
-
-enum ld_plugin_status
-onload_format_checks (struct ld_plugin_tv *tv)
-{
-  unsigned version = elf_version (EV_CURRENT);
-  check (version != EV_NONE, LDPL_FATAL, "invalid ELF version");
-  return LDPS_OK;
-}
-
Index: lto-plugin/lto-plugin.h
===================================================================
--- lto-plugin/lto-plugin.h	(revision 166214)
+++ lto-plugin/lto-plugin.h	(working copy)
@@ -1,84 +0,0 @@
-/* Common declarations for LTO plugin for gold and/or GNU ld.
-   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
-   Contributed by Rafael Avila de Espindola (espindola@google.com).
-
-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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include <stdbool.h>
-#include "plugin-api.h"
-
-/* LTO magic section name.  */
-
-#define LTO_SECTION_PREFIX ".gnu.lto_.symtab"
-
-/* The part of the symbol table the plugin has to keep track of. Note that we
-   must keep SYMS until all_symbols_read is called to give the linker time to
-   copy the symbol information. */
-
-struct sym_aux
-{
-  uint32_t slot;
-  unsigned id;
-  unsigned next_conflict;
-};
-
-struct plugin_symtab
-{
-  int nsyms;
-  struct sym_aux *aux;
-  struct ld_plugin_symbol *syms;
-  unsigned id;
-};
-
-/* All that we have to remember about a file. */
-
-struct plugin_file_info
-{
-  char *name;
-  void *handle;
-  struct plugin_symtab symtab;
-  struct plugin_symtab conflicts;
-};
-
-/* These are the methods supplied by one of the object format
-   dependent files lto-plugin-elf.c or lto-plugin-coff.c  */
-
-extern enum ld_plugin_status claim_file_handler 
-		(const struct ld_plugin_input_file *file, int *claimed);
-
-extern enum ld_plugin_status onload_format_checks (struct ld_plugin_tv *tv);
-
-/* These methods are made available to the object format
-   dependent files.  */
-
-extern void check (bool gate, enum ld_plugin_level level, const char *text);
-
-extern void translate (char *data, char *end, struct plugin_symtab *out);
-
-extern char *parse_table_entry (char *p, struct ld_plugin_symbol *entry,
-			struct sym_aux *aux);
-
-extern void resolve_conflicts (struct plugin_symtab *t,
-			struct plugin_symtab *conflicts);
-
-/* And this callback function is exposed.  */
-
-extern ld_plugin_add_symbols add_symbols;
-
-/* Along with these two variables.  */
-
-extern struct plugin_file_info *claimed_files;
-extern unsigned int num_claimed_files;
-
Index: lto-plugin/config.h.in
===================================================================
--- lto-plugin/config.h.in	(revision 0)
+++ lto-plugin/config.h.in	(revision 0)
@@ -0,0 +1,80 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Default symbol style */
+#undef SYM_STYLE
+
+/* Version number of package */
+#undef VERSION
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+   #define below would cause a syntax error. */
+#undef _UINT64_T
+
+/* Define to the type of an unsigned integer type of width exactly 64 bits if
+   such a type exists and the standard includes do not define it. */
+#undef uint64_t
Index: lto-plugin/configure
===================================================================
--- lto-plugin/configure	(revision 166214)
+++ lto-plugin/configure	(working copy)
@@ -601,7 +601,6 @@ ac_subst_vars='am__EXEEXT_FALSE
 am__EXEEXT_TRUE
 LTLIBOBJS
 LIBOBJS
-LTO_FORMAT
 target_noncanonical
 CPP
 OTOOL64
@@ -622,8 +621,6 @@ EGREP
 GREP
 SED
 LIBTOOL
-LIBELFINC
-LIBELFLIBS
 am__fastdepCC_FALSE
 am__fastdepCC_TRUE
 CCDEPMODE
@@ -742,8 +739,6 @@ CFLAGS
 LDFLAGS
 LIBS
 CPPFLAGS
-LIBELFLIBS
-LIBELFINC
 CPP'
 
 
@@ -1392,8 +1387,6 @@ Some influential environment variables:
   LIBS        libraries to pass to the linker, e.g. -l<library>
   CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
               you have headers in a nonstandard directory <include dir>
-  LIBELFLIBS  How to link libelf
-  LIBELFINC   How to find libelf include files
   CPP         C preprocessor
 
 Use these variables to override the choices made by `configure' or to help
@@ -3975,8 +3968,6 @@ rm -rf conftest*
   fi
 fi
 
-
-
 case `pwd` in
   *\ * | *\	*)
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
@@ -10443,7 +10434,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 10446 "configure"
+#line 10437 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10549,7 +10540,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 10552 "configure"
+#line 10543 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10787,14 +10778,24 @@ CC="$lt_save_CC"
 
 
 
-. ${srcdir}/../gcc/config.gcc
-case ${lto_binary_reader} in
-  *coff*) LTO_FORMAT=coff ;;
-  *elf*)  LTO_FORMAT=elf ;;
-  *) as_fn_error "LTO plugin is not supported on this target." "$LINENO" 5 ;;
-esac
+# Trying to get this information from gcc's config is tricky.
+case $target in
+  x86_64*-mingw*)
 
+$as_echo "#define SYM_STYLE ss_none" >>confdefs.h
 
+    ;;
+  *-cygwin* | i?86*-mingw* )
+
+$as_echo "#define SYM_STYLE ss_win32" >>confdefs.h
+
+    ;;
+  *)
+
+$as_echo "#define SYM_STYLE ss_none" >>confdefs.h
+
+    ;;
+esac
 ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t"
 case $ac_cv_c_uint64_t in #(
   no|yes) ;; #(
@@ -10811,6 +10812,8 @@ _ACEOF
 
 ac_config_files="$ac_config_files Makefile"
 
+ac_config_headers="$ac_config_headers config.h"
+
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
@@ -10890,44 +10893,8 @@ test "x$prefix" = xNONE && prefix=$ac_default_pref
 # Let make expand exec_prefix.
 test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
 
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-#
-# If the first sed substitution is executed (which looks for macros that
-# take arguments), then branch to the quote section.  Otherwise,
-# look for a macro that doesn't take arguments.
-ac_script='
-:mline
-/\\$/{
- N
- s,\\\n,,
- b mline
-}
-t clear
-:clear
-s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
-t quote
-s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
-t quote
-b any
-:quote
-s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
-s/\[/\\&/g
-s/\]/\\&/g
-s/\$/$$/g
-H
-:any
-${
-	g
-	s/^\n//
-	s/\n/ /g
-	p
-}
-'
-DEFS=`sed -n "$ac_script" confdefs.h`
+DEFS=-DHAVE_CONFIG_H
 
-
 ac_libobjs=
 ac_ltlibobjs=
 for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
@@ -11390,11 +11357,15 @@ case $ac_config_files in *"
 "*) set x $ac_config_files; shift; ac_config_files=$*;;
 esac
 
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
 
 
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 # Files that config.status was made for.
 config_files="$ac_config_files"
+config_headers="$ac_config_headers"
 config_commands="$ac_config_commands"
 
 _ACEOF
@@ -11415,10 +11386,15 @@ Usage: $0 [OPTION]... [TAG]...
       --recheck    update $as_me by reconfiguring in the same conditions
       --file=FILE[:TEMPLATE]
                    instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
 
 Configuration files:
 $config_files
 
+Configuration headers:
+$config_headers
+
 Configuration commands:
 $config_commands
 
@@ -11476,7 +11452,18 @@ do
     esac
     as_fn_append CONFIG_FILES " '$ac_optarg'"
     ac_need_defaults=false;;
-  --he | --h |  --help | --hel | -h )
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
     $as_echo "$ac_cs_usage"; exit ;;
   -q | -quiet | --quiet | --quie | --qui | --qu | --q \
   | -silent | --silent | --silen | --sile | --sil | --si | --s)
@@ -11800,6 +11787,7 @@ do
     "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
     "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
 
   *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
@@ -11812,6 +11800,7 @@ done
 # bizarre bug on SunOS 4.1.3.
 if $ac_need_defaults; then
   test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
   test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
 fi
 
@@ -11990,8 +11979,116 @@ fi
 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 fi # test -n "$CONFIG_FILES"
 
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
 
-eval set X "  :F $CONFIG_FILES      :C $CONFIG_COMMANDS"
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_t"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = "\a"
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
 shift
 for ac_tag
 do
@@ -12209,8 +12306,65 @@ which seems to be undefined.  Please make sure it
   esac \
   || as_fn_error "could not create $ac_file" "$LINENO" 5
  ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+    } >"$tmp/config.h" \
+      || as_fn_error "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$tmp/config.h" "$ac_file" \
+	|| as_fn_error "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
 
-
   :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
 $as_echo "$as_me: executing $ac_file commands" >&6;}
  ;;
Index: lto-plugin/Makefile.in
===================================================================
--- lto-plugin/Makefile.in	(revision 166214)
+++ lto-plugin/Makefile.in	(working copy)
@@ -36,10 +36,11 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
+target_triplet = @target@
 subdir = .
 DIST_COMMON = ChangeLog $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/configure $(am__configure_deps) \
-	$(srcdir)/../mkinstalldirs
+	$(srcdir)/config.h.in $(srcdir)/../mkinstalldirs
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
 	$(top_srcdir)/../config/depstand.m4 \
@@ -53,6 +54,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONF
 am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
  configure.lineno config.status.lineno
 mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_HEADER = config.h
 CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
@@ -78,11 +80,9 @@ am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
 am__installdirs = "$(DESTDIR)$(libexecsubdir)"
 LTLIBRARIES = $(libexecsub_LTLIBRARIES)
-am__DEPENDENCIES_1 =
-liblto_plugin_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(if $(wildcard \
+liblto_plugin_la_DEPENDENCIES = $(if $(wildcard \
 	../libiberty/pic/libiberty.a),../libiberty/pic/libiberty.a,)
-am_liblto_plugin_la_OBJECTS = lto-plugin.lo \
-	lto-plugin-$(LTO_FORMAT).lo
+am_liblto_plugin_la_OBJECTS = lto-plugin.lo
 liblto_plugin_la_OBJECTS = $(am_liblto_plugin_la_OBJECTS)
 liblto_plugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -133,19 +133,12 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
-LIBELFINC = @LIBELFINC@
-
-# How to find libelf
-LIBELFLIBS = @LIBELFLIBS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
-
-# Which object format to parse.
-LTO_FORMAT = @LTO_FORMAT@
 MAINT = @MAINT@
 MAKEINFO = @MAKEINFO@
 MKDIR_P = @MKDIR_P@
@@ -219,9 +212,13 @@ sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
 sysconfdir = @sysconfdir@
+target = @target@
 target_alias = @target_alias@
+target_cpu = @target_cpu@
 target_noncanonical := @target_noncanonical@
+target_os = @target_os@
 target_subdir = @target_subdir@
+target_vendor = @target_vendor@
 top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
@@ -229,17 +226,18 @@ ACLOCAL_AMFLAGS = -I .. -I ../config
 AUTOMAKE_OPTIONS = no-dependencies
 gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
 libexecsubdir := $(libexecdir)/gcc/$(target_noncanonical)/$(gcc_version)
-AM_CPPFLAGS = -I$(top_srcdir)/../include $(LIBELFINC)
+AM_CPPFLAGS = -I$(top_srcdir)/../include $(DEFS)
 AM_CFLAGS = -Wall -Werror
 libexecsub_LTLIBRARIES = liblto_plugin.la
-liblto_plugin_la_SOURCES = lto-plugin.c lto-plugin-$(LTO_FORMAT).c
-liblto_plugin_la_LIBADD = $(LIBELFLIBS) \
+liblto_plugin_la_SOURCES = lto-plugin.c
+liblto_plugin_la_LIBADD = \
 	$(if $(wildcard ../libiberty/pic/libiberty.a),../libiberty/pic/libiberty.a,)
 
 liblto_plugin_la_LDFLAGS = -no-undefined -bindir $(libexecsubdir) \
 	$(if $(wildcard ../libiberty/pic/libiberty.a),,-Wc,../libiberty/libiberty.a)
 
-all: all-am
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-am
 
 .SUFFIXES:
 .SUFFIXES: .c .lo .o .obj
@@ -277,6 +275,23 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(
 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
 	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
 $(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+	@if test ! -f $@; then \
+	  rm -f stamp-h1; \
+	  $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+	else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
 install-libexecsubLTLIBRARIES: $(libexecsub_LTLIBRARIES)
 	@$(NORMAL_INSTALL)
 	test -z "$(libexecsubdir)" || $(MKDIR_P) "$(DESTDIR)$(libexecsubdir)"
@@ -345,11 +360,11 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
 	mkid -fID $$unique
 tags: TAGS
 
-TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+TAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
 		$(TAGS_FILES) $(LISP)
 	set x; \
 	here=`pwd`; \
-	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
 	unique=`for i in $$list; do \
 	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
 	  done | \
@@ -367,9 +382,9 @@ tags: TAGS
 	  fi; \
 	fi
 ctags: CTAGS
-CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+CTAGS:  $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
 		$(TAGS_FILES) $(LISP)
-	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
 	unique=`for i in $$list; do \
 	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
 	  done | \
@@ -388,7 +403,7 @@ distclean-tags:
 	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 check-am: all-am
 check: check-am
-all-am: Makefile $(LTLIBRARIES)
+all-am: Makefile $(LTLIBRARIES) config.h
 installdirs:
 	for dir in "$(DESTDIR)$(libexecsubdir)"; do \
 	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
@@ -427,7 +442,7 @@ distclean: distclean-am
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
-	distclean-libtool distclean-tags
+	distclean-hdr distclean-libtool distclean-tags
 
 dvi: dvi-am
 
@@ -490,11 +505,11 @@ ps-am:
 
 uninstall-am: uninstall-libexecsubLTLIBRARIES
 
-.MAKE: install-am install-strip
+.MAKE: all install-am install-strip
 
 .PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
 	clean-generic clean-libexecsubLTLIBRARIES clean-libtool ctags \
-	distclean distclean-compile distclean-generic \
+	distclean distclean-compile distclean-generic distclean-hdr \
 	distclean-libtool distclean-tags dvi dvi-am html html-am info \
 	info-am install install-am install-data install-data-am \
 	install-dvi install-dvi-am install-exec install-exec-am \
Index: lto-plugin/configure.ac
===================================================================
--- lto-plugin/configure.ac	(revision 166214)
+++ lto-plugin/configure.ac	(working copy)
@@ -6,18 +6,21 @@ AM_INIT_AUTOMAKE([foreign no-dist])
 AM_MAINTAINER_MODE
 AC_PROG_CC
 AC_SYS_LARGEFILE
-AC_ARG_VAR(LIBELFLIBS,[How to link libelf])
-AC_ARG_VAR(LIBELFINC,[How to find libelf include files])
 AM_PROG_LIBTOOL
 AC_SUBST(target_noncanonical)
-. ${srcdir}/../gcc/config.gcc
-case ${lto_binary_reader} in
-  *coff*) LTO_FORMAT=coff ;;
-  *elf*)  LTO_FORMAT=elf ;;
-  *) AC_MSG_ERROR([LTO plugin is not supported on this target.]) ;;
+# Trying to get this information from gcc's config is tricky.
+case $target in
+  x86_64*-mingw*)
+    AC_DEFINE([SYM_STYLE], [ss_none], [Default symbol style])
+    ;;
+  *-cygwin* | i?86*-mingw* )
+    AC_DEFINE([SYM_STYLE], [ss_win32], [Default symbol style])
+    ;;
+  *)
+    AC_DEFINE([SYM_STYLE], [ss_none], [Default symbol style])
+    ;;
 esac
-
-AC_SUBST(LTO_FORMAT)
 AC_TYPE_UINT64_T
 AC_CONFIG_FILES(Makefile)
+AC_CONFIG_HEADERS(config.h)
 AC_OUTPUT
Index: lto-plugin/lto-plugin-coff.c
===================================================================
--- lto-plugin/lto-plugin-coff.c	(revision 166214)
+++ lto-plugin/lto-plugin-coff.c	(working copy)
@@ -1,38 +0,0 @@
-/* LTO plugin for gold.
-   Copyright (C) 2010 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 3, 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; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-/* Common definitions that the object format dependent code needs.  */
-#include "lto-plugin.h"
-
-/* Callback used by gold to check if the plugin will claim FILE. Writes
-   the result in CLAIMED. */
-
-enum ld_plugin_status
-claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
-{
-  /* To be implemented; for now, simply do nothing.  */
-  return LDPS_OK;
-}
-
-/* Method called first thing at onload time to perform sanity checks.  */
-
-enum ld_plugin_status
-onload_format_checks (struct ld_plugin_tv *tv)
-{
-  return LDPS_OK;
-}
-
Index: lto-plugin/Makefile.am
===================================================================
--- lto-plugin/Makefile.am	(revision 166214)
+++ lto-plugin/Makefile.am	(working copy)
@@ -7,20 +7,13 @@ gcc_version := $(shell cat $(top_srcdir)/../gcc/BA
 target_noncanonical := @target_noncanonical@
 libexecsubdir := $(libexecdir)/gcc/$(target_noncanonical)/$(gcc_version)
 
-# How to find libelf
-LIBELFLIBS = @LIBELFLIBS@
-LIBELFINC = @LIBELFINC@
-
-# Which object format to parse.
-LTO_FORMAT = @LTO_FORMAT@
-
-AM_CPPFLAGS = -I$(top_srcdir)/../include $(LIBELFINC)
+AM_CPPFLAGS = -I$(top_srcdir)/../include $(DEFS)
 AM_CFLAGS = -Wall -Werror
 
 libexecsub_LTLIBRARIES = liblto_plugin.la
 
-liblto_plugin_la_SOURCES = lto-plugin.c lto-plugin-$(LTO_FORMAT).c
-liblto_plugin_la_LIBADD = $(LIBELFLIBS) \
+liblto_plugin_la_SOURCES = lto-plugin.c
+liblto_plugin_la_LIBADD = \
 	$(if $(wildcard ../libiberty/pic/libiberty.a),../libiberty/pic/libiberty.a,)
 liblto_plugin_la_LDFLAGS = -no-undefined -bindir $(libexecsubdir) \
 	$(if $(wildcard ../libiberty/pic/libiberty.a),,-Wc,../libiberty/libiberty.a)
Index: lto-plugin/lto-plugin.c
===================================================================
--- lto-plugin/lto-plugin.c	(revision 166214)
+++ lto-plugin/lto-plugin.c	(working copy)
@@ -32,6 +32,9 @@ along with this program; see the file COPYING3.  I
    -nop: Instead of running lto-wrapper, pass the original to the plugin. This
    only works if the input files are hybrid.  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 #include <assert.h>
 #include <string.h>
 #include <stdlib.h>
@@ -46,10 +49,73 @@ along with this program; see the file COPYING3.  I
 #include <libiberty.h>
 #include <hashtab.h>
 #include "../gcc/lto/common.h"
+#include "simple-object.h"
+#include "plugin-api.h"
 
-/* Common definitions for/from the object format dependent code.  */
-#include "lto-plugin.h"
+/* Handle opening elf files on hosts, such as Windows, that may use
+   text file handling that will break binary access.  */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
 
+/* Segment name for LTO sections.  This is only used for Mach-O.
+   FIXME: This needs to be kept in sync with darwin.c.  */
+
+#define LTO_SEGMENT_NAME "__GNU_LTO"
+
+/* LTO magic section name.  */
+
+#define LTO_SECTION_PREFIX	".gnu.lto_.symtab"
+#define LTO_SECTION_PREFIX_LEN	(sizeof (LTO_SECTION_PREFIX) - 1)
+
+/* The part of the symbol table the plugin has to keep track of. Note that we
+   must keep SYMS until all_symbols_read is called to give the linker time to
+   copy the symbol information. */
+
+struct sym_aux
+{
+  uint32_t slot;
+  unsigned id;
+  unsigned next_conflict;
+};
+
+struct plugin_symtab
+{
+  int nsyms;
+  struct sym_aux *aux;
+  struct ld_plugin_symbol *syms;
+  unsigned id;
+};
+
+/* Encapsulates object file data during symbol scan.  */
+struct plugin_objfile
+{
+  int found;
+  simple_object_read *objfile;
+  struct plugin_symtab *out;
+  const struct ld_plugin_input_file *file;
+};
+
+/* All that we have to remember about a file. */
+
+struct plugin_file_info
+{
+  char *name;
+  void *handle;
+  struct plugin_symtab symtab;
+  struct plugin_symtab conflicts;
+};
+
+/* Until ASM_OUTPUT_LABELREF can be hookized and decoupled from
+   stdio file streams, we do simple label translation here.  */
+
+enum symbol_style
+{
+  ss_none,	/* No underscore prefix. */
+  ss_win32,	/* Underscore prefix any symbol not beginning with '@'.  */
+  ss_uscore,	/* Underscore prefix all symbols.  */
+};
+
 static char *arguments_file_name;
 static ld_plugin_register_claim_file register_claim_file;
 static ld_plugin_register_all_symbols_read register_all_symbols_read;
@@ -58,14 +124,11 @@ static ld_plugin_register_cleanup register_cleanup
 static ld_plugin_add_input_file add_input_file;
 static ld_plugin_add_input_library add_input_library;
 static ld_plugin_message message;
+static ld_plugin_add_symbols add_symbols;
 
-/* These are not static because the object format dependent
-   claim_file hooks in lto-plugin-{coff,elf}.c need them.  */
-ld_plugin_add_symbols add_symbols;
+static struct plugin_file_info *claimed_files = NULL;
+static unsigned int num_claimed_files = 0;
 
-struct plugin_file_info *claimed_files = NULL;
-unsigned int num_claimed_files = 0;
-
 static char **output_files = NULL;
 static unsigned int num_output_files = 0;
 
@@ -79,7 +142,12 @@ static bool debug;
 static bool nop;
 static char *resolution_file = NULL;
 
-void
+/* Set by default from configure.ac, but can be overridden at runtime
+   by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
+   (in fact, only first letter of style arg is checked.)  */
+static enum symbol_style sym_style = SYM_STYLE;
+
+static void
 check (bool gate, enum ld_plugin_level level, const char *text)
 {
   if (gate)
@@ -100,7 +168,7 @@ check (bool gate, enum ld_plugin_level level, cons
    by P and the result is written in ENTRY. The slot number is stored in SLOT.
    Returns the address of the next entry. */
 
-char *
+static char *
 parse_table_entry (char *p, struct ld_plugin_symbol *entry, 
 		   struct sym_aux *aux)
 {
@@ -122,7 +190,24 @@ parse_table_entry (char *p, struct ld_plugin_symbo
       LDPV_HIDDEN
     };
 
-  entry->name = xstrdup (p);
+  switch (sym_style)
+    {
+    case ss_win32:
+      if (p[0] == '@')
+	{
+    /* cf. Duff's device.  */
+    case ss_none:
+	  entry->name = xstrdup (p);
+	  break;
+	}
+    /* FALL-THROUGH.  */
+    case ss_uscore:
+      entry->name = concat ("_", p, NULL);
+      break;
+    default:
+      check (false, LDPL_FATAL, "invalid symbol style requested");
+      break;
+    }
   while (*p)
     p++;
   p++;
@@ -165,7 +250,7 @@ parse_table_entry (char *p, struct ld_plugin_symbo
 /* Translate the IL symbol table located between DATA and END. Append the
    slots and symbols to OUT. */
 
-void
+static void
 translate (char *data, char *end, struct plugin_symtab *out)
 {
   struct sym_aux *aux;
@@ -621,7 +706,7 @@ static int symbol_strength (struct ld_plugin_symbo
    
    XXX how to handle common? */
 
-void
+static void
 resolve_conflicts (struct plugin_symtab *t, struct plugin_symtab *conflicts)
 {
   htab_t symtab = htab_create (t->nsyms, hash_sym, eq_sym, NULL);
@@ -689,6 +774,124 @@ resolve_conflicts (struct plugin_symtab *t, struct
   htab_delete (symtab);
 }
 
+/* Process one section of an object file.  */
+
+static int 
+process_symtab (void *data, const char *name, off_t offset, off_t length)
+{
+  struct plugin_objfile *obj = (struct plugin_objfile *)data;
+  char *s;
+  char *secdata;
+
+  if (strncmp (name, LTO_SECTION_PREFIX, LTO_SECTION_PREFIX_LEN) != 0)
+    return 1;
+
+  s = strrchr (name, '.');
+  if (s)
+    sscanf (s, ".%x", &obj->out->id);
+  secdata = xmalloc (length);
+  offset += obj->file->offset;
+  if (offset != lseek (obj->file->fd, offset, SEEK_SET)
+	|| length != read (obj->file->fd, secdata, length))
+    {
+      if (message)
+	message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
+      /* Force claim_file_handler to abandon this file.  */
+      obj->found = 0;
+      free (secdata);
+      return 0;
+    }
+
+  translate (secdata, secdata + length, obj->out);
+  obj->found++;
+  free (secdata);
+  return 1;
+}
+
+/* Callback used by gold to check if the plugin will claim FILE. Writes
+   the result in CLAIMED. */
+
+static enum ld_plugin_status
+claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
+{
+  enum ld_plugin_status status;
+  struct plugin_objfile obj;
+  struct plugin_file_info lto_file;
+  int err;
+  const char *errmsg;
+
+  memset (&lto_file, 0, sizeof (struct plugin_file_info));
+
+  if (file->offset != 0)
+    {
+      char *objname;
+      /* We pass the offset of the actual file, not the archive header. */
+      int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
+                        (int64_t) file->offset);
+      check (t >= 0, LDPL_FATAL, "asprintf failed");
+      lto_file.name = objname;
+    }
+  else
+    {
+      lto_file.name = xstrdup (file->name);
+    }
+  lto_file.handle = file->handle;
+
+  *claimed = 0;
+  obj.file = file;
+  obj.found = 0;
+  obj.out = &lto_file.symtab;
+  errmsg = NULL;
+  obj.objfile = simple_object_start_read (file->fd, file->offset, LTO_SEGMENT_NAME,
+			&errmsg, &err);
+  /* No file, but also no error code means unrecognized format; just skip it.  */
+  if (!obj.objfile && !err)
+    goto err;
+
+  if (obj.objfile)
+    errmsg = simple_object_find_sections (obj.objfile, process_symtab, &obj, &err);
+
+  if (!obj.objfile || errmsg)
+    {
+      if (err && message)
+	message (LDPL_FATAL, "%s: %s: %s", file->name, errmsg,
+		xstrerror (err));
+      else if (message)
+	message (LDPL_FATAL, "%s: %s", file->name, errmsg);
+      goto err;
+    }
+
+  if (obj.found == 0)
+    goto err;
+
+  if (obj.found > 1)
+    resolve_conflicts (&lto_file.symtab, &lto_file.conflicts);
+
+  status = add_symbols (file->handle, lto_file.symtab.nsyms,
+			lto_file.symtab.syms);
+  check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
+
+  *claimed = 1;
+  num_claimed_files++;
+  claimed_files =
+    xrealloc (claimed_files,
+	      num_claimed_files * sizeof (struct plugin_file_info));
+  claimed_files[num_claimed_files - 1] = lto_file;
+
+  goto cleanup;
+
+ err:
+  free (lto_file.name);
+
+ cleanup:
+  if (obj.objfile)
+    simple_object_release_read (obj.objfile);
+  if (file->fd >= 0)
+    close (file->fd);
+
+  return LDPS_OK;
+}
+
 /* Parse the plugin options. */
 
 static void
@@ -706,6 +909,21 @@ process_option (const char *option)
       pass_through_items[num_pass_through_items - 1] =
           xstrdup (option + strlen ("-pass-through="));
     }
+  else if (!strncmp (option, "-sym-style=", sizeof ("-sym-style=") - 1))
+    {
+      switch (option[sizeof ("-sym-style=") - 1])
+	{
+	case 'w':
+	  sym_style = ss_win32;
+	  break;
+	case 'u':
+	  sym_style = ss_uscore;
+	  break;
+	default:
+	  sym_style = ss_none;
+	  break;
+	}
+    }
   else
     {
       int size;
@@ -727,10 +945,6 @@ onload (struct ld_plugin_tv *tv)
   struct ld_plugin_tv *p;
   enum ld_plugin_status status;
 
-  status = onload_format_checks (tv);
-  if (status != LDPS_OK)
-    return status;
-
   p = tv;
   while (p->tv_tag)
     {
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 166214)
+++ gcc/config.gcc	(working copy)
@@ -219,8 +219,6 @@ default_gnu_indirect_function=no
 target_gtfiles=
 need_64bit_hwint=
 need_64bit_isa=
-# Selects the object file format reader/writer used by LTO.
-lto_binary_reader=lto-elf
 
 # Don't carry these over build->host->target.  Please.
 xm_file=
@@ -1160,13 +1158,11 @@ i[34567]86-*-darwin*)
 	# support.
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
-	lto_binary_reader=lto-macho
 	;;
 x86_64-*-darwin*)
 	with_cpu=${with_cpu:-generic}
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-crtpc i386/t-crtfm"
 	tm_file="${tm_file} ${cpu_type}/darwin64.h"
-	lto_binary_reader=lto-macho
 	;;
 i[34567]86-*-elf*)
 	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
@@ -1421,7 +1417,6 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
 		thread_file='posix'
 	fi
 	use_gcc_stdint=wrap
-	lto_binary_reader=lto-coff
 	;;
 i[34567]86-*-mingw* | x86_64-*-mingw*)
 	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h"
@@ -1494,7 +1489,6 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
 	cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
 	default_use_cxa_atexit=yes
 	use_gcc_stdint=wrap
-	lto_binary_reader=lto-coff
 	case ${enable_threads} in
 	  "" | yes | win32)	  thread_file='win32'
 	  tmake_file="${tmake_file} i386/t-gthr-win32"
@@ -2006,7 +2000,6 @@ powerpc-*-darwin*)
 	    ;;
 	esac
 	tmake_file="${tmake_file} t-slibgcc-darwin"
-	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc64-*-darwin*)
@@ -2014,7 +2007,6 @@ powerpc64-*-darwin*)
 	extra_parts="crt2.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-darwin"
 	tm_file="${tm_file} ${cpu_type}/darwin8.h ${cpu_type}/darwin64.h"
-	lto_binary_reader=lto-macho
 	extra_headers=altivec.h
 	;;
 powerpc*-*-freebsd*)
Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 166214)
+++ gcc/doc/install.texi	(working copy)
@@ -355,17 +355,6 @@ not installed in your default library search path.
 
 Necessary to build libgcj, the GCJ runtime.
 
-@item libelf version 0.8.12 (or later)
-
-Necessary to build link-time optimization (LTO) support.  It can be
-downloaded from @uref{http://www.mr511.de/software/libelf-0.8.12.tar.gz},
-though it is commonly available in several systems.  The version in
-IRIX 6.5 doesn't work since it lacks @file{gelf.h}.  The version in
-Solaris 2 does work.
-
-The @option{--with-libelf} configure option should be used if libelf is
-not installed in your default library search patch.
-
 @end table
 
 @heading Tools/packages necessary for modifying GCC
@@ -1650,21 +1639,10 @@ default for a native toolchain with an assembler t
 GLIBC 2.11 or above, otherwise disabled.
 
 @item --enable-lto
+@itemx --disable-lto
 Enable support for link-time optimization (LTO).  This is enabled by
-default if a working libelf implementation is found (see
-@option{--with-libelf}).
+default, and may be disabled using @option{--disable-lto}.
 
-@item --with-libelf=@var{pathname}
-@itemx --with-libelf-include=@var{pathname}
-@itemx --with-libelf-lib=@var{pathname}
-If you do not have libelf installed in a standard location and you
-want to enable support for link-time optimization (LTO), you can
-explicitly specify the directory where libelf is installed
-(@samp{--with-libelf=@var{libelfinstalldir}}).  The
-@option{--with-libelf=@var{libelfinstalldir}} option is shorthand for
-@option{--with-libelf-include=@var{libelfinstalldir}/include}
-@option{--with-libelf-lib=@var{libelfinstalldir}/lib}.
-
 @item --enable-gold
 Enable support for using @command{gold} as the linker.  If gold support is
 enabled together with @option{--enable-lto}, an additional directory

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

* Re: Discussion about merging Go frontend
  2010-11-02 22:22                     ` Dave Korn
  2010-11-02 22:30                       ` Ian Lance Taylor
@ 2010-11-03  6:09                       ` Ralf Wildenhues
  2010-11-03  7:05                         ` Dave Korn
  1 sibling, 1 reply; 68+ messages in thread
From: Ralf Wildenhues @ 2010-11-03  6:09 UTC (permalink / raw)
  To: Dave Korn; +Cc: Ian Lance Taylor, gcc-patches

* Dave Korn wrote on Tue, Nov 02, 2010 at 11:44:49PM CET:
> On 02/11/2010 15:06, Ian Lance Taylor wrote:
> > Dave Korn writes:
> > 
> >> -AC_SUBST(LTO_FORMAT)
> >> +AC_SUBST(SYM_STYLE)
> > 
> > It would seem more natural to use AC_DEFINE here.  Any reason not to do
> > that?
> 
>   It seems a bit much overkill.  There's only a single -D right now, so why
> not pass it straight through?  With AC_DEFINE I'd still have to import @DEFS@
> into the makefile, just to get HAVE_CONFIG_H available at build time, and then
> add a config.h with a single #define in it.  If there were several symbols to
> define, or if there was already an AC_CONFIG_HEADER, I'd do it, but there
> isn't yet, so why haul all that extra weight?

FWIW, you don't need an AC_CONFIG_HEADER.  If you don't have one, @DEFS@
will expand to all the defines defined by AC_DEFINE.

Cheers,
Ralf

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

* Re: Discussion about merging Go frontend
  2010-11-03  6:09                       ` Ralf Wildenhues
@ 2010-11-03  7:05                         ` Dave Korn
  0 siblings, 0 replies; 68+ messages in thread
From: Dave Korn @ 2010-11-03  7:05 UTC (permalink / raw)
  To: Ralf Wildenhues, Dave Korn, Ian Lance Taylor, gcc-patches

On 03/11/2010 05:58, Ralf Wildenhues wrote:

> 
> FWIW, you don't need an AC_CONFIG_HEADER.  If you don't have one, @DEFS@
> will expand to all the defines defined by AC_DEFINE.

  Ah well, I did it now anyway.  Noted for next time, thanks! :)

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-11-03  5:40                                         ` Dave Korn
@ 2010-11-03  9:47                                           ` Dave Korn
  2010-11-03 16:19                                             ` H.J. Lu
  0 siblings, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-11-03  9:47 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

On 03/11/2010 05:29, Dave Korn wrote:
> On 03/11/2010 05:10, Dave Korn wrote:
> 
>>   :) I see our emails crossed in the ether.  Just preparing a (hopefully
>> final!) spin.
> 
>   This is underway on the cfarm.  No changes to the previous changelogs with
> this revision.

  Testing completed without regressions on x86-64-unknown-linux-gnu; committed
(just the simpleobj-lto-plugin-take2.diff, not the cygming nor coff patches)
at revision 166233.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-11-03  9:47                                           ` Dave Korn
@ 2010-11-03 16:19                                             ` H.J. Lu
  2010-11-03 21:03                                               ` [PATCH] Fix PR46291: broken lto-bootstrap [was Re: Discussion about merging Go frontend] Dave Korn
  0 siblings, 1 reply; 68+ messages in thread
From: H.J. Lu @ 2010-11-03 16:19 UTC (permalink / raw)
  To: Dave Korn; +Cc: Ian Lance Taylor, gcc-patches

On Wed, Nov 3, 2010 at 2:41 AM, Dave Korn <dave.korn.cygwin@gmail.com> wrote:
> On 03/11/2010 05:29, Dave Korn wrote:
>> On 03/11/2010 05:10, Dave Korn wrote:
>>
>>>   :) I see our emails crossed in the ether.  Just preparing a (hopefully
>>> final!) spin.
>>
>>   This is underway on the cfarm.  No changes to the previous changelogs with
>> this revision.
>
>  Testing completed without regressions on x86-64-unknown-linux-gnu; committed
> (just the simpleobj-lto-plugin-take2.diff, not the cygming nor coff patches)
> at revision 166233.
>

I am afraid this caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46291


-- 
H.J.

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

* [PATCH] Fix PR46291: broken lto-bootstrap [was Re: Discussion about merging Go frontend]
  2010-11-03 16:19                                             ` H.J. Lu
@ 2010-11-03 21:03                                               ` Dave Korn
  2010-11-03 21:12                                                 ` Ian Lance Taylor
  2010-11-05 17:33                                                 ` H.J. Lu
  0 siblings, 2 replies; 68+ messages in thread
From: Dave Korn @ 2010-11-03 21:03 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Ian Lance Taylor, gcc-patches

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

On 03/11/2010 16:18, H.J. Lu wrote:
> On Wed, Nov 3, 2010 at 2:41 AM, Dave Korn <dave.korn.cygwin@gmail.com> wrote:
>> On 03/11/2010 05:29, Dave Korn wrote:
>>> On 03/11/2010 05:10, Dave Korn wrote:
>>>
>>>>   :) I see our emails crossed in the ether.  Just preparing a (hopefully
>>>> final!) spin.
>>>   This is underway on the cfarm.  No changes to the previous changelogs with
>>> this revision.
>>  Testing completed without regressions on x86-64-unknown-linux-gnu; committed
>> (just the simpleobj-lto-plugin-take2.diff, not the cygming nor coff patches)
>> at revision 166233.
>>
> 
> I am afraid this caused:
> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46291

  As mentioned in the audit trail, this patch will fix bootstrap while we
decide how to resolve the ambiguity in the linker plugin interface spec.

lto-plugin/ChangeLog:

2010-11-03  Dave Korn  <dave.korn.cygwin@gmail.com>

	* lto-plugin.c (must_close_files): New global bool.
	(claim_file_handler): Respect it.
	(onload): Set it if loaded by GNU LD.

  Now LTO-bootstrapping on x86_64-unknown-linux-gnu.  OK once it completes
successfully?

    cheers,
      DaveK


[-- Attachment #2: pr46291.diff --]
[-- Type: text/x-c, Size: 1472 bytes --]

Index: lto-plugin/lto-plugin.c
===================================================================
--- lto-plugin/lto-plugin.c	(revision 166233)
+++ lto-plugin/lto-plugin.c	(working copy)
@@ -145,8 +145,16 @@ static char *resolution_file = NULL;
 /* Set by default from configure.ac, but can be overridden at runtime
    by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
    (in fact, only first letter of style arg is checked.)  */
+
 static enum symbol_style sym_style = SYM_STYLE;
 
+/* Until ambiguity in the linker plugin API is resolved, it will be
+   necessary for us to detect which linker is calling us at onload
+   time, and infer from that whether to close the file descriptors
+   passed into the claim_file_handler (LD) or not (GOLD).  */
+
+static bool must_close_files = false;
+
 static void
 check (bool gate, enum ld_plugin_level level, const char *text)
 {
@@ -886,7 +894,7 @@ claim_file_handler (const struct ld_plugin_input_f
  cleanup:
   if (obj.objfile)
     simple_object_release_read (obj.objfile);
-  if (file->fd >= 0)
+  if (must_close_files && file->fd >= 0)
     close (file->fd);
 
   return LDPS_OK;
@@ -959,6 +967,9 @@ onload (struct ld_plugin_tv *tv)
 	case LDPT_ADD_SYMBOLS:
 	  add_symbols = p->tv_u.tv_add_symbols;
 	  break;
+	case LDPT_GNU_LD_VERSION:
+	  must_close_files = true;
+	  break;
 	case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
 	  register_all_symbols_read = p->tv_u.tv_register_all_symbols_read;
 	  break;

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

* Re: [PATCH] Fix PR46291: broken lto-bootstrap [was Re: Discussion about merging Go frontend]
  2010-11-03 21:03                                               ` [PATCH] Fix PR46291: broken lto-bootstrap [was Re: Discussion about merging Go frontend] Dave Korn
@ 2010-11-03 21:12                                                 ` Ian Lance Taylor
  2010-11-03 21:40                                                   ` [PATCH,take2] " Dave Korn
  2010-11-05 17:33                                                 ` H.J. Lu
  1 sibling, 1 reply; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-03 21:12 UTC (permalink / raw)
  To: Dave Korn; +Cc: H.J. Lu, gcc-patches

Dave Korn <dave.korn.cygwin@gmail.com> writes:

> 2010-11-03  Dave Korn  <dave.korn.cygwin@gmail.com>
>
> 	* lto-plugin.c (must_close_files): New global bool.
> 	(claim_file_handler): Respect it.
> 	(onload): Set it if loaded by GNU LD.
>
>   Now LTO-bootstrapping on x86_64-unknown-linux-gnu.  OK once it completes
> successfully?

This is OK if bootstrap succeeds.

Thanks.

Ian

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

* [PATCH,take2] Re: [PATCH] Fix PR46291: broken lto-bootstrap [was Re: Discussion about merging Go frontend]
  2010-11-03 21:12                                                 ` Ian Lance Taylor
@ 2010-11-03 21:40                                                   ` Dave Korn
  2010-11-03 22:06                                                     ` Ian Lance Taylor
  0 siblings, 1 reply; 68+ messages in thread
From: Dave Korn @ 2010-11-03 21:40 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: H.J. Lu, gcc-patches

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

On 03/11/2010 21:10, Ian Lance Taylor wrote:
> Dave Korn <dave.korn.cygwin@gmail.com> writes:
> 
>> 2010-11-03  Dave Korn  <dave.korn.cygwin@gmail.com>
>>
>> 	* lto-plugin.c (must_close_files): New global bool.
>> 	(claim_file_handler): Respect it.
>> 	(onload): Set it if loaded by GNU LD.
>>
>>   Now LTO-bootstrapping on x86_64-unknown-linux-gnu.  OK once it completes
>> successfully?
> 
> This is OK if bootstrap succeeds.

  (As you may already have seen in the audit trail), Cary says that the fd is
supposed to belong to the linker, and the plugin should never close it.  So
this simpler patch does that, and I'll fix up LD to do likewise.

2010-11-03  Dave Korn  <dave.korn.cygwin@gmail.com>

	* lto-plugin.c (claim_file_handler): Don't close file descriptor.


  OK likewise after it passes bootstrap?

    cheers,
      DaveK

[-- Attachment #2: pr46291-take2.diff --]
[-- Type: text/x-c, Size: 442 bytes --]

Index: gcc-patched/lto-plugin/lto-plugin.c
===================================================================
--- gcc-patched/lto-plugin/lto-plugin.c	(revision 166233)
+++ gcc-patched/lto-plugin/lto-plugin.c	(working copy)
@@ -886,8 +886,6 @@ claim_file_handler (const struct ld_plugin_input_f
  cleanup:
   if (obj.objfile)
     simple_object_release_read (obj.objfile);
-  if (file->fd >= 0)
-    close (file->fd);
 
   return LDPS_OK;
 }

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

* Re: [PATCH,take2] Re: [PATCH] Fix PR46291: broken lto-bootstrap [was Re: Discussion about merging Go frontend]
  2010-11-03 21:40                                                   ` [PATCH,take2] " Dave Korn
@ 2010-11-03 22:06                                                     ` Ian Lance Taylor
  2010-11-03 23:53                                                       ` Dave Korn
  0 siblings, 1 reply; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-03 22:06 UTC (permalink / raw)
  To: Dave Korn; +Cc: H.J. Lu, gcc-patches

Dave Korn <dave.korn.cygwin@gmail.com> writes:

> 2010-11-03  Dave Korn  <dave.korn.cygwin@gmail.com>
>
> 	* lto-plugin.c (claim_file_handler): Don't close file descriptor.
>
>
>   OK likewise after it passes bootstrap?

Yes, this is OK after bootstrap.

Thanks.

Ian

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

* Re: [PATCH,take2] Re: [PATCH] Fix PR46291: broken lto-bootstrap [was Re: Discussion about merging Go frontend]
  2010-11-03 22:06                                                     ` Ian Lance Taylor
@ 2010-11-03 23:53                                                       ` Dave Korn
  0 siblings, 0 replies; 68+ messages in thread
From: Dave Korn @ 2010-11-03 23:53 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: H.J. Lu, gcc-patches

On 03/11/2010 21:51, Ian Lance Taylor wrote:
> Dave Korn <dave.korn.cygwin@gmail.com> writes:
> 
>> 2010-11-03  Dave Korn  <dave.korn.cygwin@gmail.com>
>>
>> 	* lto-plugin.c (claim_file_handler): Don't close file descriptor.
>>
>>
>>   OK likewise after it passes bootstrap?
> 
> Yes, this is OK after bootstrap.
> 
> Thanks.
> 
> Ian

  Committed revision 166285.  Remembered to mention the PR in the changelog.

    cheers,
      DaveK

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

* Re: [PATCH] Fix PR46291: broken lto-bootstrap [was Re: Discussion about merging Go frontend]
  2010-11-03 21:03                                               ` [PATCH] Fix PR46291: broken lto-bootstrap [was Re: Discussion about merging Go frontend] Dave Korn
  2010-11-03 21:12                                                 ` Ian Lance Taylor
@ 2010-11-05 17:33                                                 ` H.J. Lu
  1 sibling, 0 replies; 68+ messages in thread
From: H.J. Lu @ 2010-11-05 17:33 UTC (permalink / raw)
  To: Dave Korn; +Cc: Ian Lance Taylor, gcc-patches

On Wed, Nov 3, 2010 at 2:22 PM, Dave Korn <dave.korn.cygwin@gmail.com> wrote:
> On 03/11/2010 16:18, H.J. Lu wrote:
>> On Wed, Nov 3, 2010 at 2:41 AM, Dave Korn <dave.korn.cygwin@gmail.com> wrote:
>>> On 03/11/2010 05:29, Dave Korn wrote:
>>>> On 03/11/2010 05:10, Dave Korn wrote:
>>>>
>>>>>   :) I see our emails crossed in the ether.  Just preparing a (hopefully
>>>>> final!) spin.
>>>>   This is underway on the cfarm.  No changes to the previous changelogs with
>>>> this revision.
>>>  Testing completed without regressions on x86-64-unknown-linux-gnu; committed
>>> (just the simpleobj-lto-plugin-take2.diff, not the cygming nor coff patches)
>>> at revision 166233.
>>>
>>
>> I am afraid this caused:
>>
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46291
>
>  As mentioned in the audit trail, this patch will fix bootstrap while we
> decide how to resolve the ambiguity in the linker plugin interface spec.
>
> lto-plugin/ChangeLog:
>
> 2010-11-03  Dave Korn  <dave.korn.cygwin@gmail.com>
>
>        * lto-plugin.c (must_close_files): New global bool.
>        (claim_file_handler): Respect it.
>        (onload): Set it if loaded by GNU LD.
>
>  Now LTO-bootstrapping on x86_64-unknown-linux-gnu.  OK once it completes
> successfully?

Have you run

# make check-gcc RUNTESTFLAGS="plugin.exp --target_board 'unix{-m32,}'"

with --with-build-config=bootstrap-lto --with-plugin-ld=ld on Linux/x86-64?
I got extra plugin test failures:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46319


-- 
H.J.

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

* Re: [PATCH] Enable linker plugin for windows [was Re: Discussion about merging Go frontend]
  2010-10-30 20:02                   ` [PATCH] Enable linker plugin for windows [was Re: Discussion about merging Go frontend] Dave Korn
@ 2010-11-05 22:02                     ` Ian Lance Taylor
  2010-11-05 22:03                       ` Dave Korn
  2010-11-16 16:38                       ` [withdrawn] " Dave Korn
  0 siblings, 2 replies; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-05 22:02 UTC (permalink / raw)
  To: Dave Korn; +Cc: gcc-patches

Dave Korn <dave.korn.cygwin@gmail.com> writes:

> gcc/ChangeLog:
>
> 	* gcc.c (PLUGIN_PASSTHROUGH_SPEC): New macro factored out from
> 	LINK_COMMAND_SPEC.
> 	(LINK_COMMAND_SPEC): Use it.
> 	(static_spec_functions[]): Add pass-through-libs entry.
> 	(pass_through_libs_spec_func): Add related spec function.
> 	* config/i386/cygming.h (PLUGIN_PASSTHROUGH_SPEC): Define.
> 	* doc/tm.texi.in (PLUGIN_PASSTHROUGH_SPEC): Document.
> 	(LINK_COMMAND_SPEC): Mention it.
> 	* doc/tm.texi: Regenerate.
> 	* doc/invoke.texi (pass-through-libs): Mention new spec function.

> @@ -658,10 +667,8 @@
>      %{fuse-linker-plugin: \
>      -plugin %(linker_plugin_file) \
>      -plugin-opt=%(lto_wrapper) \
> -    -plugin-opt=-fresolution=%u.res \
> -    %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)}	\
> -    %{static:-plugin-opt=-pass-through=-lc}	\
> -    } \
> +    -plugin-opt=-fresolution=%u.res " \
> +    PLUGIN_PASSTHROUGH_SPEC " } \
>      %{flto:%<fcompare-debug*} %{fwhopr*:%<fcompare-debug*} \
>      %{flto} %{fwhopr*} %l " LINK_PIE_SPEC \
>     "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\

Any reason not to make PLUGIN_PASSTHROUGH_SPEC into a proper spec,
invoked by %(plugin_passthrough) rather than by preprocessor string
concatenation?

Ian

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

* Re: [PATCH] Enable linker plugin for windows [was Re: Discussion about merging Go frontend]
  2010-11-05 22:02                     ` Ian Lance Taylor
@ 2010-11-05 22:03                       ` Dave Korn
  2010-11-16 16:38                       ` [withdrawn] " Dave Korn
  1 sibling, 0 replies; 68+ messages in thread
From: Dave Korn @ 2010-11-05 22:03 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

On 05/11/2010 21:35, Ian Lance Taylor wrote:
> Dave Korn <dave.korn.cygwin@gmail.com> writes:
> 
>> gcc/ChangeLog:
>>
>> 	* gcc.c (PLUGIN_PASSTHROUGH_SPEC): New macro factored out from
>> 	LINK_COMMAND_SPEC.
>> 	(LINK_COMMAND_SPEC): Use it.
>> 	(static_spec_functions[]): Add pass-through-libs entry.
>> 	(pass_through_libs_spec_func): Add related spec function.
>> 	* config/i386/cygming.h (PLUGIN_PASSTHROUGH_SPEC): Define.
>> 	* doc/tm.texi.in (PLUGIN_PASSTHROUGH_SPEC): Document.
>> 	(LINK_COMMAND_SPEC): Mention it.
>> 	* doc/tm.texi: Regenerate.
>> 	* doc/invoke.texi (pass-through-libs): Mention new spec function.
> 
>> @@ -658,10 +667,8 @@
>>      %{fuse-linker-plugin: \
>>      -plugin %(linker_plugin_file) \
>>      -plugin-opt=%(lto_wrapper) \
>> -    -plugin-opt=-fresolution=%u.res \
>> -    %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)}	\
>> -    %{static:-plugin-opt=-pass-through=-lc}	\
>> -    } \
>> +    -plugin-opt=-fresolution=%u.res " \
>> +    PLUGIN_PASSTHROUGH_SPEC " } \
>>      %{flto:%<fcompare-debug*} %{fwhopr*:%<fcompare-debug*} \
>>      %{flto} %{fwhopr*} %l " LINK_PIE_SPEC \
>>     "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
> 
> Any reason not to make PLUGIN_PASSTHROUGH_SPEC into a proper spec,
> invoked by %(plugin_passthrough) rather than by preprocessor string
> concatenation?

  Well, "I didn't think of it" is the main reason :)  I don't suppose there's
going to be any call to change or override it on any kind of regular basis, I
very much expect we'll have the default one for ELF targets and an override
for COFF targets and that's all that will ever be needed.  So I didn't think
it ever likely to need a name of its own to refer to it by.

  If you can see some advantage to making it a real spec, feel free to file an
enhancement PR against my name.

    cheers,
      DaveK

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

* Re: Discussion about merging Go frontend
  2010-10-29  6:56               ` Discussion about merging Go frontend Ian Lance Taylor
                                   ` (6 preceding siblings ...)
  2010-11-01 17:36                 ` Tom Tromey
@ 2010-11-06 20:01                 ` Eric Botcazou
  2010-11-16 18:34                   ` simple-object vs. Solaris Ian Lance Taylor
  7 siblings, 1 reply; 68+ messages in thread
From: Eric Botcazou @ 2010-11-06 20:01 UTC (permalink / raw)
  To: Ian Lance Taylor
  Cc: gcc, Dave Korn, Andi Kleen, Andrew Pinski, Mark Mitchell, gcc-patches

> 2010-10-28  Ian Lance Taylor  <iant@google.com>
>
> 	* lto-objfile.c: New file.
> 	* lto-elf.c: Remove file.

This has removed the support for compatible architectures present in lto-elf.c 
and hasn't added any replacement in libiberty, so a bunch of LTO tests fail 
again on 32-bit SPARC/Solaris.

The old code reads:

/* Return true if ELF_MACHINE is compatible with the cached value of the
   architecture and possibly update the latter.  Return false otherwise.

   Note: if you want to add more EM_* cases, you'll need to provide the
   corresponding definitions at the beginning of the file.  */

static bool
is_compatible_architecture (Elf64_Half elf_machine)
{
  if (cached_file_attrs.elf_machine == elf_machine)
    return true;

  switch (cached_file_attrs.elf_machine)
    {
    case EM_SPARC:
      if (elf_machine == EM_SPARC32PLUS)
	{
	  cached_file_attrs.elf_machine = elf_machine;
	  return true;
	}
      break;

    case EM_SPARC32PLUS:
      if (elf_machine == EM_SPARC)
	return true;
      break;

    default:
      break;
    }

  return false;
}

so it was not only accepting object files with compatible architectures in the 
same LTO compilation, but also updating the current architecture for later 
write operations.  This is modelled on the linker.

-- 
Eric Botcazou

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

* [withdrawn] Re: [PATCH] Enable linker plugin for windows [was Re: Discussion about merging Go frontend]
  2010-11-05 22:02                     ` Ian Lance Taylor
  2010-11-05 22:03                       ` Dave Korn
@ 2010-11-16 16:38                       ` Dave Korn
  1 sibling, 0 replies; 68+ messages in thread
From: Dave Korn @ 2010-11-16 16:38 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

On 05/11/2010 21:35, Ian Lance Taylor wrote:
> Dave Korn writes:
> 
>> gcc/ChangeLog:
>>
>> 	* gcc.c (PLUGIN_PASSTHROUGH_SPEC): New macro factored out from
>> 	LINK_COMMAND_SPEC.
>> 	(LINK_COMMAND_SPEC): Use it.
>> 	(static_spec_functions[]): Add pass-through-libs entry.
>> 	(pass_through_libs_spec_func): Add related spec function.
>> 	* config/i386/cygming.h (PLUGIN_PASSTHROUGH_SPEC): Define.
>> 	* doc/tm.texi.in (PLUGIN_PASSTHROUGH_SPEC): Document.
>> 	(LINK_COMMAND_SPEC): Mention it.
>> 	* doc/tm.texi: Regenerate.
>> 	* doc/invoke.texi (pass-through-libs): Mention new spec function.
> 
>> @@ -658,10 +667,8 @@
>>      %{fuse-linker-plugin: \
>>      -plugin %(linker_plugin_file) \
>>      -plugin-opt=%(lto_wrapper) \
>> -    -plugin-opt=-fresolution=%u.res \
>> -    %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)}	\
>> -    %{static:-plugin-opt=-pass-through=-lc}	\
>> -    } \
>> +    -plugin-opt=-fresolution=%u.res " \
>> +    PLUGIN_PASSTHROUGH_SPEC " } \
>>      %{flto:%<fcompare-debug*} %{fwhopr*:%<fcompare-debug*} \
>>      %{flto} %{fwhopr*} %l " LINK_PIE_SPEC \
>>     "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
> 
> Any reason not to make PLUGIN_PASSTHROUGH_SPEC into a proper spec,
> invoked by %(plugin_passthrough) rather than by preprocessor string
> concatenation?
> 
> Ian

  I found a better way to do it(*), since there turned out not to be any need
for a separate spec at all, as the functionality required here by PE-COFF also
solves the problems seen on other platforms as in e.g., PR42690.  Patch withdrawn.

    cheers,
      DaveK
-- 
(*) - http://gcc.gnu.org/ml/gcc-patches/2010-11/msg01688.html

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

* simple-object vs. Solaris
  2010-11-06 20:01                 ` Eric Botcazou
@ 2010-11-16 18:34                   ` Ian Lance Taylor
  2010-11-16 20:12                     ` Dave Korn
  2010-11-17  0:49                     ` Eric Botcazou
  0 siblings, 2 replies; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-16 18:34 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Rainer Orth

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

Eric Botcazou <ebotcazou@adacore.com> writes:

>> 2010-10-28  Ian Lance Taylor  <iant@google.com>
>>
>> 	* lto-objfile.c: New file.
>> 	* lto-elf.c: Remove file.
>
> This has removed the support for compatible architectures present in lto-elf.c 
> and hasn't added any replacement in libiberty, so a bunch of LTO tests fail 
> again on 32-bit SPARC/Solaris.

Does this patch solve the problem?

Ian


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: sparc --]
[-- Type: text/x-diff, Size: 9177 bytes --]

Index: libiberty/simple-object-elf.c
===================================================================
--- libiberty/simple-object-elf.c	(revision 166769)
+++ libiberty/simple-object-elf.c	(working copy)
@@ -115,6 +115,11 @@ typedef struct {
 
 #define ET_REL		1	/* Relocatable file */
 
+/* Values for e_machine field of Ehdr.  */
+
+#define EM_SPARC	  2	/* SUN SPARC */
+#define EM_SPARC32PLUS	 18	/* Sun's "v8plus" */
+
 /* Special section index values.  */
 
 #define SHN_LORESERVE	0xFF00		/* Begin range of reserved indices */
@@ -604,20 +609,52 @@ simple_object_elf_release_read (void *da
 /* Compare two attributes structures.  */
 
 static const char *
-simple_object_elf_attributes_compare (void *data1, void *data2, int *err)
+simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err)
 {
-  struct simple_object_elf_attributes *attrs1 =
-    (struct simple_object_elf_attributes *) data1;
-  struct simple_object_elf_attributes *attrs2 =
-    (struct simple_object_elf_attributes *) data2;
-
-  if (attrs1->ei_data != attrs2->ei_data
-      || attrs1->ei_class != attrs2->ei_class
-      || attrs1->machine != attrs2->machine)
+  struct simple_object_elf_attributes *to =
+    (struct simple_object_elf_attributes *) todata;
+  struct simple_object_elf_attributes *from =
+    (struct simple_object_elf_attributes *) fromdata;
+
+  if (to->ei_data != from->ei_data || to->ei_class != from->ei_class)
     {
       *err = 0;
       return "ELF object format mismatch";
     }
+
+  if (to->machine != from->machine)
+    {
+      int ok;
+
+      /* EM_SPARC and EM_SPARC32PLUS are compatible and force an
+	 output of EM_SPARC32PLUS.  */
+      ok = 0;
+      switch (to->machine)
+	{
+	case EM_SPARC:
+	  if (from->machine == EM_SPARC32PLUS)
+	    {
+	      to->machine = from->machine;
+	      ok = 1;
+	    }
+	  break;
+
+	case EM_SPARC32PLUS:
+	  if (from->machine == EM_SPARC)
+	    ok = 1;
+	  break;
+
+	default:
+	  break;
+	}
+
+      if (!ok)
+	{
+	  *err = 0;
+	  return "ELF machine number mismatch";
+	}
+    }
+
   return NULL;
 }
 
@@ -908,7 +945,7 @@ const struct simple_object_functions sim
   simple_object_elf_find_sections,
   simple_object_elf_fetch_attributes,
   simple_object_elf_release_read,
-  simple_object_elf_attributes_compare,
+  simple_object_elf_attributes_merge,
   simple_object_elf_release_attributes,
   simple_object_elf_start_write,
   simple_object_elf_write_to_file,
Index: libiberty/simple-object-mach-o.c
===================================================================
--- libiberty/simple-object-mach-o.c	(revision 166769)
+++ libiberty/simple-object-mach-o.c	(working copy)
@@ -624,16 +624,16 @@ simple_object_mach_o_release_read (void 
 /* Compare two attributes structures.  */
 
 static const char *
-simple_object_mach_o_attributes_compare (void *data1, void *data2, int *err)
+simple_object_mach_o_attributes_merge (void *todata, void *fromdata, int *err)
 {
-  struct simple_object_mach_o_attributes *attrs1 =
-    (struct simple_object_mach_o_attributes *) data1;
-  struct simple_object_mach_o_attributes *attrs2 =
-    (struct simple_object_mach_o_attributes *) data2;
-
-  if (attrs1->magic != attrs2->magic
-      || attrs1->is_big_endian != attrs2->is_big_endian
-      || attrs1->cputype != attrs2->cputype)
+  struct simple_object_mach_o_attributes *to =
+    (struct simple_object_mach_o_attributes *) todata;
+  struct simple_object_mach_o_attributes *from =
+    (struct simple_object_mach_o_attributes *) fromdata;
+
+  if (to->magic != from->magic
+      || to->is_big_endian != from->is_big_endian
+      || to->cputype != from->cputype)
     {
       *err = 0;
       return "Mach-O object format mismatch";
@@ -1014,7 +1014,7 @@ const struct simple_object_functions sim
   simple_object_mach_o_find_sections,
   simple_object_mach_o_fetch_attributes,
   simple_object_mach_o_release_read,
-  simple_object_mach_o_attributes_compare,
+  simple_object_mach_o_attributes_merge,
   simple_object_mach_o_release_attributes,
   simple_object_mach_o_start_write,
   simple_object_mach_o_write_to_file,
Index: libiberty/simple-object-coff.c
===================================================================
--- libiberty/simple-object-coff.c	(revision 166769)
+++ libiberty/simple-object-coff.c	(working copy)
@@ -457,15 +457,14 @@ simple_object_coff_release_read (void *d
 /* Compare two attributes structures.  */
 
 static const char *
-simple_object_coff_attributes_compare (void *data1, void *data2, int *err)
+simple_object_coff_attributes_merge (void *todata, void *fromdata, int *err)
 {
-  struct simple_object_coff_attributes *attrs1 =
-    (struct simple_object_coff_attributes *) data1;
-  struct simple_object_coff_attributes *attrs2 =
-    (struct simple_object_coff_attributes *) data2;
+  struct simple_object_coff_attributes *to =
+    (struct simple_object_coff_attributes *) todata;
+  struct simple_object_coff_attributes *from =
+    (struct simple_object_coff_attributes *) fromdata;
 
-  if (attrs1->magic != attrs2->magic
-      || attrs1->is_big_endian != attrs2->is_big_endian)
+  if (to->magic != from->magic || to->is_big_endian != from->is_big_endian)
     {
       *err = 0;
       return "COFF object format mismatch";
@@ -797,7 +796,7 @@ const struct simple_object_functions sim
   simple_object_coff_find_sections,
   simple_object_coff_fetch_attributes,
   simple_object_coff_release_read,
-  simple_object_coff_attributes_compare,
+  simple_object_coff_attributes_merge,
   simple_object_coff_release_attributes,
   simple_object_coff_start_write,
   simple_object_coff_write_to_file,
Index: libiberty/simple-object-common.h
===================================================================
--- libiberty/simple-object-common.h	(revision 166769)
+++ libiberty/simple-object-common.h	(working copy)
@@ -123,10 +123,10 @@ struct simple_object_functions
   /* Release the private data for an simple_object_read.  */
   void (*release_read) (void *);
 
-  /* Compare the private data for the attributes of two files.  If
-     they are the same, in the sense that they could be linked
-     together, return NULL.  Otherwise return an error message.  */
-  const char *(*attributes_compare) (void *, void *, int *err);
+  /* Merge the private data for the attributes of two files.  If they
+     could be linked together, return NULL.  Otherwise return an error
+     message.  */
+  const char *(*attributes_merge) (void *, void *, int *err);
 
   /* Release the private data for an simple_object_attributes.  */
   void (*release_attributes) (void *);
Index: libiberty/simple-object.c
===================================================================
--- libiberty/simple-object.c	(revision 166769)
+++ libiberty/simple-object.c	(working copy)
@@ -257,20 +257,19 @@ simple_object_release_read (simple_objec
   XDELETE (sobj);
 }
 
-/* Compare attributes.  */
+/* Merge attributes.  */
 
 const char *
-simple_object_attributes_compare (simple_object_attributes *attrs1,
-				  simple_object_attributes *attrs2,
-				  int *err)
+simple_object_attributes_merge (simple_object_attributes *to,
+				simple_object_attributes *from,
+				int *err)
 {
-  if (attrs1->functions != attrs2->functions)
+  if (to->functions != from->functions)
     {
       *err = 0;
       return "different object file format";
     }
-  return attrs1->functions->attributes_compare (attrs1->data, attrs2->data,
-						err);
+  return to->functions->attributes_merge (to->data, from->data, err);
 }
 
 /* Release an attributes structure.  */
Index: include/simple-object.h
===================================================================
--- include/simple-object.h	(revision 166769)
+++ include/simple-object.h	(working copy)
@@ -117,14 +117,15 @@ extern simple_object_attributes *
 simple_object_fetch_attributes (simple_object_read *simple_object,
 				const char **errmsg, int *err);
 
-/* Compare ATTRS1 and ATTRS2.  If they could be linked together
-   without error, return NULL.  Otherwise, return an error message,
-   set *ERR to an errno value or 0 if there isn't one.  */
+/* Merge the FROM attributes into TO.  If two objects with these
+   attributes could be linked together without error, returns NULL.
+   Otherwise, returns an error message, and sets *ERR to an errno
+   value or 0 if there isn't one.  */
 
 extern const char *
-simple_object_attributes_compare (simple_object_attributes *attrs1,
-			    simple_object_attributes *attrs2,
-			    int *err);
+simple_object_attributes_merge (simple_object_attributes *to,
+				simple_object_attributes *from,
+				int *err);
 
 /* Release all resources associated with ATTRS.  */
 
Index: gcc/lto/lto-object.c
===================================================================
--- gcc/lto/lto-object.c	(revision 166769)
+++ gcc/lto/lto-object.c	(working copy)
@@ -138,8 +138,8 @@ lto_obj_file_open (const char *filename,
 	saved_attributes = attrs;
       else
 	{
-	  errmsg = simple_object_attributes_compare (saved_attributes, attrs,
-						     &err);
+	  errmsg = simple_object_attributes_merge (saved_attributes, attrs,
+						   &err);
 	  if (errmsg != NULL)
 	    goto fail_errmsg;
 	}

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

* Re: simple-object vs. Solaris
  2010-11-16 18:34                   ` simple-object vs. Solaris Ian Lance Taylor
@ 2010-11-16 20:12                     ` Dave Korn
  2010-11-17  0:49                     ` Eric Botcazou
  1 sibling, 0 replies; 68+ messages in thread
From: Dave Korn @ 2010-11-16 20:12 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Eric Botcazou, gcc-patches, Rainer Orth

On 16/11/2010 18:09, Ian Lance Taylor wrote:
> Eric Botcazou writes:
> 
>>> 2010-10-28  Ian Lance Taylor
>>>
>>> 	* lto-objfile.c: New file.
>>> 	* lto-elf.c: Remove file.
>> This has removed the support for compatible architectures present in lto-elf.c 
>> and hasn't added any replacement in libiberty, so a bunch of LTO tests fail 
>> again on 32-bit SPARC/Solaris.
> 
> Does this patch solve the problem?

  Ah, I should have finished reading my incoming mail before I sent that
previous reply!

    cheers,
      DaveK

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

* Re: simple-object vs. Solaris
  2010-11-16 18:34                   ` simple-object vs. Solaris Ian Lance Taylor
  2010-11-16 20:12                     ` Dave Korn
@ 2010-11-17  0:49                     ` Eric Botcazou
  2010-11-17  2:31                       ` Ian Lance Taylor
  1 sibling, 1 reply; 68+ messages in thread
From: Eric Botcazou @ 2010-11-17  0:49 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches, Rainer Orth

> Does this patch solve the problem?

Definitely, thanks!

-- 
Eric Botcazou

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

* Re: simple-object vs. Solaris
  2010-11-17  0:49                     ` Eric Botcazou
@ 2010-11-17  2:31                       ` Ian Lance Taylor
  0 siblings, 0 replies; 68+ messages in thread
From: Ian Lance Taylor @ 2010-11-17  2:31 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Rainer Orth

Eric Botcazou <ebotcazou@adacore.com> writes:

>> Does this patch solve the problem?
>
> Definitely, thanks!

Thanks for testing it.

I also bootstrapped it on x86_64-unknown-linux-gnu and ran all the
lto.exp tests.

I'm a libiberty maintainer and the gcc/lto change is both trivial and
obvious given the other changes.  Committed to mainline with the
following ChangeLog entries.

Ian


include/:

2010-11-16  Ian Lance Taylor  <iant@google.com>

	* simple-object.h (simple_object_attributes_merge): Declare,
	replacing simple_object_attributes_compare.

libiberty/:

2010-11-16  Ian Lance Taylor  <iant@google.com>

	* simple-object.c (simple_object_attributes_merge): Rename from
	simple_object_attributes_compare.  Call merge field.
	* simple-object-common.h (struct simple_object_functions): Rename
	attributes_compare field to attribute_merge.
	* simple-object-elf.c (EM_SPARC): Define.
	(EM_SPARC32PLUS): Define.
	(simple_object_elf_attributes_merge): Renamed from
	simple_object_elf_attributes_compare.  Permit EM_SPARC and
	EM_SPARC32PLUS objects to be merged.
	(simple_object_elf_functions): Update function name.
	* simple-object-coff.c (simple_object_coff_attributes_merge):
	Rename from simple_object_coff_attributes_compare.
	(simple_object_coff_functions): Update function name.
	* simple-object-mach-o.c (simple_object_mach_o_attributes_merge):
	Renamed from simple_object_mach_o_attributes_compare.
	(simple_object_mach_o_functions): Update function name.

gcc/lto/:

2010-11-16  Ian Lance Taylor  <iant@google.com>

	* lto-object.c (lto_obj_file_open): Call
	simple_object_attributes_merge rather than
	simple_object_attributes_compare.

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

end of thread, other threads:[~2010-11-17  1:04 UTC | newest]

Thread overview: 68+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <mcr7hh8qhb5.fsf@google.com>
     [not found] ` <4CC45302.9000702@gmail.com>
     [not found]   ` <mcrhbgbyoef.fsf@google.com>
     [not found]     ` <4CC59F1E.7040505@codesourcery.com>
     [not found]       ` <mcrbp6ixhny.fsf@google.com>
     [not found]         ` <AANLkTikEy7ER+CkQdWo0XHPoBORvbp8JZ226QFM68PZv@mail.gmail.com>
     [not found]           ` <87pquy3yh5.fsf@basil.nowhere.org>
     [not found]             ` <4CC60C5E.6050605@gmail.com>
2010-10-29  6:56               ` Discussion about merging Go frontend Ian Lance Taylor
2010-10-29 13:19                 ` Dave Korn
2010-10-29 13:31                   ` IainS
2010-10-29 14:50                     ` Ian Lance Taylor
2010-10-29 13:45                   ` Jack Howarth
2010-10-29 14:34                     ` Dave Korn
2010-10-29 14:35                     ` Ian Lance Taylor
2010-10-29 15:10                       ` Jack Howarth
2010-10-29 13:51                 ` Richard Guenther
2010-10-29 14:31                   ` Dave Korn
2010-10-29 15:30                 ` Mark Mitchell
2010-10-30  8:07                 ` Richard Henderson
2010-10-30 13:59                   ` Dave Korn
2010-10-31  0:31                     ` Richard Henderson
2010-10-31  3:33                       ` Dave Korn
2010-10-31  7:16                         ` Richard Henderson
2010-10-31  8:47                           ` Dave Korn
2010-10-31 19:43                             ` Ian Lance Taylor
2010-10-31 20:00                   ` Ian Lance Taylor
2010-10-30 16:31                 ` Dave Korn
2010-10-30 20:02                   ` [PATCH] Enable linker plugin for windows [was Re: Discussion about merging Go frontend] Dave Korn
2010-11-05 22:02                     ` Ian Lance Taylor
2010-11-05 22:03                       ` Dave Korn
2010-11-16 16:38                       ` [withdrawn] " Dave Korn
2010-11-02 15:12                   ` Discussion about merging Go frontend Ian Lance Taylor
2010-11-02 22:22                     ` Dave Korn
2010-11-02 22:30                       ` Ian Lance Taylor
2010-11-02 22:50                         ` Dave Korn
2010-11-03  6:09                       ` Ralf Wildenhues
2010-11-03  7:05                         ` Dave Korn
2010-10-30 19:30                 ` Dave Korn
2010-10-31 20:18                   ` Ian Lance Taylor
2010-11-01 17:36                 ` Tom Tromey
2010-11-01 18:23                   ` Ian Lance Taylor
2010-11-02 10:51                     ` Paolo Bonzini
2010-11-02 11:01                       ` Paolo Bonzini
2010-11-01 22:30                   ` Ian Lance Taylor
2010-11-02 15:06                     ` Ian Lance Taylor
2010-11-02 17:58                       ` H.J. Lu
2010-11-02 22:51                         ` Dave Korn
2010-11-03  0:16                           ` Dave Korn
2010-11-03  0:38                             ` Dave Korn
2010-11-03  2:04                               ` Dave Korn
2010-11-03  4:29                                 ` Dave Korn
2010-11-03  4:46                                   ` Dave Korn
2010-11-03  4:36                                 ` Ian Lance Taylor
2010-11-03  4:43                                   ` Dave Korn
2010-11-03  4:47                                     ` Ian Lance Taylor
2010-11-03  5:06                                       ` Dave Korn
2010-11-03  5:40                                         ` Dave Korn
2010-11-03  9:47                                           ` Dave Korn
2010-11-03 16:19                                             ` H.J. Lu
2010-11-03 21:03                                               ` [PATCH] Fix PR46291: broken lto-bootstrap [was Re: Discussion about merging Go frontend] Dave Korn
2010-11-03 21:12                                                 ` Ian Lance Taylor
2010-11-03 21:40                                                   ` [PATCH,take2] " Dave Korn
2010-11-03 22:06                                                     ` Ian Lance Taylor
2010-11-03 23:53                                                       ` Dave Korn
2010-11-05 17:33                                                 ` H.J. Lu
2010-11-02 23:00                       ` Discussion about merging Go frontend Dave Korn
2010-11-02 23:36                         ` Ian Lance Taylor
2010-11-02 17:43                     ` H.J. Lu
2010-11-02 18:01                       ` Ian Lance Taylor
2010-11-02 18:06                         ` H.J. Lu
2010-11-06 20:01                 ` Eric Botcazou
2010-11-16 18:34                   ` simple-object vs. Solaris Ian Lance Taylor
2010-11-16 20:12                     ` Dave Korn
2010-11-17  0:49                     ` Eric Botcazou
2010-11-17  2:31                       ` Ian Lance Taylor

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).