Patchwork Discussion about merging Go frontend

login
register
mail settings
Submitter Ian Taylor
Date Nov. 1, 2010, 10:27 p.m.
Message ID <mcr7hgwy90h.fsf@google.com>
Download mbox | patch
Permalink /patch/69852/
State New
Headers show

Comments

Ian Taylor - Nov. 1, 2010, 10:27 p.m.
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).
Ian Taylor - Nov. 2, 2010, 2:56 p.m.
I have committed the simple-object (nee objfile) patches to libiberty,
include, gcc/lto and gcc top level.  Thanks to Dave Korn and Iain Sandoe
for testing and fixes for the COFF and Mach-O support.

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

Please let me know about any problems.

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

This patch breaks gcc on Linux:

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

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

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

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

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

    cheers,
      DaveK
Dave Korn - Nov. 2, 2010, 11:14 p.m.
On 02/11/2010 14:56, Ian Lance Taylor wrote:

> 
> Please let me know about any problems.

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

    cheers,
      DaveK
Ian Taylor - Nov. 2, 2010, 11:18 p.m.
Dave Korn <dave.korn.cygwin@gmail.com> writes:

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

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

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

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

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

ChangeLog:

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

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

gcc/ChangeLog:

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

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

lto-plugin/ChangeLog:

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

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

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

libiberty/ChangeLog:

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

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

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

gcc/ChangeLog:

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

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

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

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

    cheers,
      DaveK
Dave Korn - Nov. 3, 2010, 12:50 a.m.
On 03/11/2010 00:30, Dave Korn wrote:

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

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

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

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

ChangeLog:

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

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

    cheers,
      DaveK
Ian Taylor - Nov. 3, 2010, 4:29 a.m.
Dave Korn <dave.korn.cygwin@gmail.com> writes:

> +  secdata = xmalloc (length);

secdata = XNEWVEC (char *, length);

+  free (secdata);

XDELETEVEC (secdata);


I assume you ran both autoconf and autoheader.

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

Thanks.

Ian
Dave Korn - Nov. 3, 2010, 4:41 a.m.
On 03/11/2010 01:25, Dave Korn wrote:

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

  Something went wrong:

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

  The libc.so in question is a linker script:

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

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

    cheers,
      DaveK
Ian Taylor - Nov. 3, 2010, 4:45 a.m.
Dave Korn <dave.korn.cygwin@gmail.com> writes:

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

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

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

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

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

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

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

> I assume you ran both autoconf and autoheader.

  Yep.  And automake.

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

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

    cheers,
      DaveK
Dave Korn - Nov. 3, 2010, 5:08 a.m.
On 03/11/2010 04:41, Dave Korn wrote:

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

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

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

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

    cheers,
      DaveK
Dave Korn - Nov. 3, 2010, 5:29 a.m.
On 03/11/2010 05:10, Dave Korn wrote:

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

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

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

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

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

I am afraid this caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46291
Ian Taylor - Nov. 3, 2010, 9:10 p.m.
Dave Korn <dave.korn.cygwin@gmail.com> writes:

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

This is OK if bootstrap succeeds.

Thanks.

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

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

lto-plugin/ChangeLog:

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

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

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

    cheers,
      DaveK
Ian Taylor - Nov. 3, 2010, 9:51 p.m.
Dave Korn <dave.korn.cygwin@gmail.com> writes:

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

Yes, this is OK after bootstrap.

Thanks.

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

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

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

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


  OK likewise after it passes bootstrap?

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

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

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

Have you run

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

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

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

Patch

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