This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Discussion about merging Go frontend


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


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]