[cross-binutils/f19] Move to binutils-2.23.88.0.1 to fix texinfo problem [BZ 913931]

David Howells dhowells at fedoraproject.org
Fri Aug 9 08:35:52 UTC 2013


commit c6dd967422664f358ac366c443b91bb33f929f60
Author: David Howells <dhowells at redhat.com>
Date:   Tue Jun 4 21:00:22 2013 +0100

    Move to binutils-2.23.88.0.1 to fix texinfo problem [BZ 913931]
    
    Move to binutils-2.23.88.0.1 to fix a problem in F19 where texinfo compilation
    fails [BZ 913931]:
    
    ../../../binutils-2.23.51.0.3/bfd/doc/bfd.texinfo:325: unknown command `colophon'
    ../../../binutils-2.23.51.0.3/bfd/doc/bfd.texinfo:336: unknown command `cygnus'

 binutils-2.22.52.0.1-relro-on-by-default.patch     |   10 +-
 binutils-2.23.2-aarch64-em.patch                   |   47 +
 binutils-2.23.2-bfd-texinfo-fixes.patch            |   36 +
 binutils-2.23.2-dwz-alt-debuginfo.patch            |  610 +++++
 binutils-2.23.2-kernel-ld-r.patch                  | 2734 ++++++++++++++++++++
 binutils-2.23.2-ld-texinfo-fixes.patch             |   87 +
 binutils-2.23.51.0.3-arm-ldralt.patch              |  208 --
 binutils-2.23.52.0.1-64-bit-thin-archives.patch    |   25 +
 binutils-2.23.52.0.1-addr2line-dynsymtab.patch     |  144 +
 binutils-2.23.52.0.1-as-doc-texinfo-fixes.patch    |  368 +++
 ...tils-2.23.52.0.1-check-regular-ifunc-refs.patch |   48 +
 cross-binutils.spec                                |   59 +-
 12 files changed, 4153 insertions(+), 223 deletions(-)
---
diff --git a/binutils-2.22.52.0.1-relro-on-by-default.patch b/binutils-2.22.52.0.1-relro-on-by-default.patch
index 83ae415..7028339 100644
--- a/binutils-2.22.52.0.1-relro-on-by-default.patch
+++ b/binutils-2.22.52.0.1-relro-on-by-default.patch
@@ -78,14 +78,14 @@ diff -cpr ../binutils-2.22.52.0.1.orig/ld/testsuite/ld-bootstrap/bootstrap.exp l
   	untested $testname
   	continue
       }
-*** ../binutils-2.22.52.0.2.orig/ld/emultempl/elf32.em	2012-04-30 16:12:52.642766221 +0100
---- ld/emultempl/elf32.em	2012-04-30 16:13:13.869766905 +0100
+*** ../binutils-2.23.2.orig/ld/emultempl/elf32.em	2013-04-24 11:06:47.777176887 +0100
+--- ld/emultempl/elf32.em	2013-04-24 11:07:22.405177847 +0100
 *************** gld${EMULATION_NAME}_before_parse (void)
-*** 106,111 ****
---- 106,112 ----
+*** 105,110 ****
+--- 105,111 ----
     input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
     config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
-    link_info.sharable_sections = `if test "$SHARABLE_SECTIONS" = "yes" ; then echo TRUE ; else echo FALSE ; fi`;
+    config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
 +   link_info.relro = TRUE;
   }
   
diff --git a/binutils-2.23.2-aarch64-em.patch b/binutils-2.23.2-aarch64-em.patch
new file mode 100644
index 0000000..f4aae4c
--- /dev/null
+++ b/binutils-2.23.2-aarch64-em.patch
@@ -0,0 +1,47 @@
+*** ../binutils-2.23.2.orig/ld/emultempl/aarch64elf.em	2013-06-05 09:46:17.499278813 +0100
+--- ld/emultempl/aarch64elf.em	2013-06-05 09:54:36.981292659 +0100
+*************** gld${EMULATION_NAME}_after_allocation (v
+*** 264,270 ****
+  }
+  
+  static void
+! gld${EMULATION_NAME}_finish (void)
+  {
+    if (! link_info.relocatable)
+      {
+--- 264,270 ----
+  }
+  
+  static void
+! gld${EMULATION_NAME}_local_finish (void)
+  {
+    if (! link_info.relocatable)
+      {
+*************** gld${EMULATION_NAME}_finish (void)
+*** 276,282 ****
+  	}
+      }
+  
+!   finish_default ();
+  }
+  
+  /* This is a convenient point to tell BFD about target specific flags.
+--- 276,282 ----
+  	}
+      }
+  
+!   gld${EMULATION_NAME}_finish ();
+  }
+  
+  /* This is a convenient point to tell BFD about target specific flags.
+*************** LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=
+*** 413,416 ****
+  LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
+  
+  # Call the extra arm-elf function
+! LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+--- 413,416 ----
+  LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
+  
+  # Call the extra arm-elf function
+! LDEMUL_FINISH=gld${EMULATION_NAME}_local_finish
diff --git a/binutils-2.23.2-bfd-texinfo-fixes.patch b/binutils-2.23.2-bfd-texinfo-fixes.patch
new file mode 100644
index 0000000..52fc61c
--- /dev/null
+++ b/binutils-2.23.2-bfd-texinfo-fixes.patch
@@ -0,0 +1,36 @@
+*** ../binutils-2.23.2.orig/bfd/doc/bfd.texinfo	2013-05-17 08:53:44.811925730 +0100
+--- bfd/doc/bfd.texinfo	2013-05-17 08:58:10.712933101 +0100
+*************** All of BFD lives in one directory.
+*** 322,328 ****
+  @printindex cp
+  
+  @tex
+! % I think something like @colophon should be in texinfo.  In the
+  % meantime:
+  \long\def\colophon{\hbox to0pt{}\vfill
+  \centerline{The body of this manual is set in}
+--- 322,328 ----
+  @printindex cp
+  
+  @tex
+! % I think something like @@colophon should be in texinfo.  In the
+  % meantime:
+  \long\def\colophon{\hbox to0pt{}\vfill
+  \centerline{The body of this manual is set in}
+*************** All of BFD lives in one directory.
+*** 333,339 ****
+  \centerline{{\sl\fontname\tensl\/}}
+  \centerline{are used for emphasis.}\vfill}
+  \page\colophon
+! % Blame: doc at cygnus.com, 28mar91.
+  @end tex
+  
+  @bye
+--- 333,339 ----
+  \centerline{{\sl\fontname\tensl\/}}
+  \centerline{are used for emphasis.}\vfill}
+  \page\colophon
+! % Blame: doc@@cygnus.com, 28mar91.
+  @end tex
+  
+  @bye
diff --git a/binutils-2.23.2-dwz-alt-debuginfo.patch b/binutils-2.23.2-dwz-alt-debuginfo.patch
new file mode 100644
index 0000000..18605a6
--- /dev/null
+++ b/binutils-2.23.2-dwz-alt-debuginfo.patch
@@ -0,0 +1,610 @@
+diff -rcp ../binutils-2.23.2.orig/bfd/bfd-in2.h bfd/bfd-in2.h
+*** ../binutils-2.23.2.orig/bfd/bfd-in2.h	2013-05-29 15:56:00.512051112 +0100
+--- bfd/bfd-in2.h	2013-05-29 15:58:54.994055949 +0100
+*************** void *bfd_zalloc (bfd *abfd, bfd_size_ty
+*** 1042,1049 ****
+--- 1042,1053 ----
+  unsigned long bfd_calc_gnu_debuglink_crc32
+     (unsigned long crc, const unsigned char *buf, bfd_size_type len);
+  
++ char *bfd_get_alt_debug_link_info (bfd *abfd, unsigned long *crc32_out);
++ 
+  char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir);
+  
++ char *bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir);
++ 
+  struct bfd_section *bfd_create_gnu_debuglink_section
+     (bfd *abfd, const char *filename);
+  
+diff -rcp ../binutils-2.23.2.orig/bfd/dwarf2.c bfd/dwarf2.c
+*** ../binutils-2.23.2.orig/bfd/dwarf2.c	2013-05-29 15:56:00.296051106 +0100
+--- bfd/dwarf2.c	2013-05-29 16:00:03.490057848 +0100
+*************** struct dwarf2_debug
+*** 108,113 ****
+--- 108,123 ----
+    asection *sec;
+    bfd_byte *sec_info_ptr;
+  
++   /* Support for alternate debug info sections created by the DWZ utility:
++      This includes a pointer to an alternate bfd which contains *extra*,
++      possibly duplicate debug sections, and pointers to the loaded
++      .debug_str and .debug_info sections from this bfd.  */
++   bfd *          alt_bfd_ptr;
++   bfd_byte *     alt_dwarf_str_buffer;
++   bfd_size_type  alt_dwarf_str_size;
++   bfd_byte *     alt_dwarf_info_buffer;
++   bfd_size_type  alt_dwarf_info_size;
++ 
+    /* A pointer to the memory block allocated for info_ptr.  Neither
+       info_ptr nor sec_info_ptr are guaranteed to stay pointing to the
+       beginning of the malloc block.  This is used only to free the
+*************** const struct dwarf_debug_section dwarf_d
+*** 287,292 ****
+--- 297,303 ----
+    { ".debug_aranges",		".zdebug_aranges" },
+    { ".debug_frame",		".zdebug_frame" },
+    { ".debug_info",		".zdebug_info" },
++   { ".debug_info",		".zdebug_info" },
+    { ".debug_line",		".zdebug_line" },
+    { ".debug_loc",		".zdebug_loc" },
+    { ".debug_macinfo",		".zdebug_macinfo" },
+*************** const struct dwarf_debug_section dwarf_d
+*** 297,302 ****
+--- 308,314 ----
+    { ".debug_static_func",	".zdebug_static_func" },
+    { ".debug_static_vars",	".zdebug_static_vars" },
+    { ".debug_str",		".zdebug_str", },
++   { ".debug_str",		".zdebug_str", },
+    { ".debug_types",		".zdebug_types" },
+    /* GNU DWARF 1 extensions */
+    { ".debug_sfnames",		".zdebug_sfnames" },
+*************** const struct dwarf_debug_section dwarf_d
+*** 309,320 ****
+--- 321,335 ----
+    { NULL,			NULL },
+  };
+  
++ /* NB/ Numbers in this enum must match up with indicies
++    into the dwarf_debug_sections[] array above.  */
+  enum dwarf_debug_section_enum
+  {
+    debug_abbrev = 0,
+    debug_aranges,
+    debug_frame,
+    debug_info,
++   debug_info_alt,
+    debug_line,
+    debug_loc,
+    debug_macinfo,
+*************** enum dwarf_debug_section_enum
+*** 325,330 ****
+--- 340,346 ----
+    debug_static_func,
+    debug_static_vars,
+    debug_str,
++   debug_str_alt,
+    debug_types,
+    debug_sfnames,
+    debug_srcinfo,
+*************** read_section (bfd *           abfd,
+*** 481,488 ****
+    asection *msec;
+    const char *section_name = sec->uncompressed_name;
+  
+!   /* read_section is a noop if the section has already been read.  */
+!   if (!*section_buffer)
+      {
+        msec = bfd_get_section_by_name (abfd, section_name);
+        if (! msec)
+--- 497,504 ----
+    asection *msec;
+    const char *section_name = sec->uncompressed_name;
+  
+!   /* The section may have already been read.  */
+!   if (*section_buffer == NULL)
+      {
+        msec = bfd_get_section_by_name (abfd, section_name);
+        if (! msec)
+*************** read_indirect_string (struct comp_unit *
+*** 623,628 ****
+--- 639,742 ----
+    return str;
+  }
+  
++ /* Like read_indirect_string but uses a .debug_str located in
++    an alternate filepointed to by the .gnu_debuglink section.
++    Used to impement DW_FORM_GNU_strp_alt.  */
++ 
++ static char *
++ read_alt_indirect_string (struct comp_unit * unit,
++ 			  bfd_byte *         buf,
++ 			  unsigned int *     bytes_read_ptr)
++ {
++   bfd_uint64_t offset;
++   struct dwarf2_debug *stash = unit->stash;
++   char *str;
++ 
++   if (unit->offset_size == 4)
++     offset = read_4_bytes (unit->abfd, buf);
++   else
++     offset = read_8_bytes (unit->abfd, buf);
++ 
++   *bytes_read_ptr = unit->offset_size;
++ 
++   if (stash->alt_bfd_ptr == NULL)
++     {
++       bfd *  debug_bfd;
++       char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR);
++ 
++       if (debug_filename == NULL)
++ 	return NULL;
++ 
++       if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
++ 	  || ! bfd_check_format (debug_bfd, bfd_object))
++ 	{
++ 	  if (debug_bfd)
++ 	    bfd_close (debug_bfd);
++ 
++ 	  /* FIXME: Should we report our failure to follow the debuglink ?  */
++ 	  free (debug_filename);
++ 	  return NULL;
++ 	}
++       stash->alt_bfd_ptr = debug_bfd;
++     }
++   
++   if (! read_section (unit->stash->alt_bfd_ptr,
++ 		      stash->debug_sections + debug_str_alt,
++ 		      NULL, /* FIXME: Do we need to load alternate symbols ?  */
++ 		      offset,
++ 		      &stash->alt_dwarf_str_buffer,
++ 		      &stash->alt_dwarf_str_size))
++     return NULL;
++ 
++   str = (char *) stash->alt_dwarf_str_buffer + offset;
++   if (*str == '\0')
++     return NULL;
++ 
++   return str;
++ }
++ 
++ /* Resolve an alternate reference from UNIT at OFFSET.
++    Returns a pointer into the loaded alternate CU upon success
++    or NULL upon failure.  */
++ 
++ static bfd_byte *
++ read_alt_indirect_ref (struct comp_unit * unit,
++ 		       bfd_uint64_t       offset)
++ {
++   struct dwarf2_debug *stash = unit->stash;
++ 
++   if (stash->alt_bfd_ptr == NULL)
++     {
++       bfd *  debug_bfd;
++       char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR);
++ 
++       if (debug_filename == NULL)
++ 	return FALSE;
++ 
++       if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL
++ 	  || ! bfd_check_format (debug_bfd, bfd_object))
++ 	{
++ 	  if (debug_bfd)
++ 	    bfd_close (debug_bfd);
++ 
++ 	  /* FIXME: Should we report our failure to follow the debuglink ?  */
++ 	  free (debug_filename);
++ 	  return NULL;
++ 	}
++       stash->alt_bfd_ptr = debug_bfd;
++     }
++   
++   if (! read_section (unit->stash->alt_bfd_ptr,
++ 		      stash->debug_sections + debug_info_alt,
++ 		      NULL, /* FIXME: Do we need to load alternate symbols ?  */
++ 		      offset,
++ 		      &stash->alt_dwarf_info_buffer,
++ 		      &stash->alt_dwarf_info_size))
++     return NULL;
++ 
++   return stash->alt_dwarf_info_buffer + offset;
++ }
++ 
+  static bfd_uint64_t
+  read_address (struct comp_unit *unit, bfd_byte *buf)
+  {
+*************** read_attribute_value (struct attribute *
+*** 826,831 ****
+--- 940,946 ----
+        attr->u.val = read_address (unit, info_ptr);
+        info_ptr += unit->addr_size;
+        break;
++     case DW_FORM_GNU_ref_alt:
+      case DW_FORM_sec_offset:
+        if (unit->offset_size == 4)
+  	attr->u.val = read_4_bytes (unit->abfd, info_ptr);
+*************** read_attribute_value (struct attribute *
+*** 875,880 ****
+--- 990,999 ----
+        attr->u.str = read_indirect_string (unit, info_ptr, &bytes_read);
+        info_ptr += bytes_read;
+        break;
++     case DW_FORM_GNU_strp_alt:
++       attr->u.str = read_alt_indirect_string (unit, info_ptr, &bytes_read);
++       info_ptr += bytes_read;
++       break;
+      case DW_FORM_exprloc:
+      case DW_FORM_block:
+        amt = sizeof (struct dwarf_block);
+*************** find_abstract_instance_name (struct comp
+*** 2006,2011 ****
+--- 2125,2141 ----
+  
+        info_ptr = unit->sec_info_ptr + die_ref;
+      }
++   else if (attr_ptr->form == DW_FORM_GNU_ref_alt)
++     {
++       info_ptr = read_alt_indirect_ref (unit, die_ref);
++       if (info_ptr == NULL)
++ 	{
++ 	  (*_bfd_error_handler)
++ 	    (_("Dwarf Error: Unable to read alt ref %u."), die_ref);
++ 	  bfd_set_error (bfd_error_bad_value);
++ 	  return name;
++ 	}
++     }
+    else 
+      info_ptr = unit->info_ptr_unit + die_ref;
+    abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+*************** _bfd_dwarf2_cleanup_debug_info (bfd *abf
+*** 3720,3723 ****
+--- 3850,3859 ----
+      free (stash->dwarf_ranges_buffer);
+    if (stash->info_ptr_memory)
+      free (stash->info_ptr_memory);
++   if (stash->alt_dwarf_str_buffer)
++     free (stash->alt_dwarf_str_buffer);
++   if (stash->alt_dwarf_info_buffer)
++     free (stash->alt_dwarf_info_buffer);
++   if (stash->alt_bfd_ptr)
++     bfd_close (stash->alt_bfd_ptr);
+  }
+diff -rcp ../binutils-2.23.2.orig/bfd/opncls.c bfd/opncls.c
+*** ../binutils-2.23.2.orig/bfd/opncls.c	2013-05-29 15:55:59.990051098 +0100
+--- bfd/opncls.c	2013-05-29 16:01:00.052059415 +0100
+*************** bfd_release (bfd *abfd, void *block)
+*** 1056,1065 ****
+  
+     This facilitates "optional" provision of debugging information, without
+     having to provide two complete copies of every binary object (with and
+!    without debug symbols).
+! */
+  
+- #define GNU_DEBUGLINK	".gnu_debuglink"
+  /*
+  FUNCTION
+  	bfd_calc_gnu_debuglink_crc32
+--- 1056,1066 ----
+  
+     This facilitates "optional" provision of debugging information, without
+     having to provide two complete copies of every binary object (with and
+!    without debug symbols).  */
+! 
+! #define GNU_DEBUGLINK		".gnu_debuglink"
+! #define GNU_DEBUGALTLINK	".gnu_debugaltlink"
+  
+  /*
+  FUNCTION
+  	bfd_calc_gnu_debuglink_crc32
+*************** get_debug_link_info (bfd *abfd, unsigned
+*** 1195,1200 ****
+--- 1196,1249 ----
+  }
+  
+  /*
++ FUNCTION
++ 	bfd_get_alt_debug_link_info
++ 
++ SYNOPSIS
++ 	char *bfd_get_alt_debug_link_info (bfd *abfd, unsigned long *crc32_out);
++ 
++ DESCRIPTION
++ 	Fetch the filename and BuildID value for any alternate debuginfo
++ 	associated with @var{abfd}.  Return NULL if no such info found,
++ 	otherwise return filename and update @var{buildid_out}.  The
++ 	returned filename is allocated with @code{malloc}; freeing it
++ 	is the responsibility of the caller.
++ */
++ 
++ char *
++ bfd_get_alt_debug_link_info (bfd * abfd, unsigned long * buildid_out)
++ {
++   asection *sect;
++   bfd_byte *contents;
++   int buildid_offset;
++   char *name;
++ 
++   BFD_ASSERT (abfd);
++   BFD_ASSERT (buildid_out);
++ 
++   sect = bfd_get_section_by_name (abfd, GNU_DEBUGALTLINK);
++ 
++   if (sect == NULL)
++     return NULL;
++ 
++   if (!bfd_malloc_and_get_section (abfd, sect, & contents))
++     {
++       if (contents != NULL)
++ 	free (contents);
++       return NULL;
++     }
++ 
++   /* BuildID value is stored after the filename, aligned up to 4 bytes.  */
++   name = (char *) contents;
++   buildid_offset = strlen (name) + 1;
++   buildid_offset = (buildid_offset + 3) & ~3;
++ 
++   * buildid_out = bfd_get_32 (abfd, contents + buildid_offset);
++ 
++   return name;
++ }
++ 
++ /*
+  INTERNAL_FUNCTION
+  	separate_debug_file_exists
+  
+*************** separate_debug_file_exists (const char *
+*** 1229,1234 ****
+--- 1278,1314 ----
+    return crc == file_crc;
+  }
+  
++ /*
++ INTERNAL_FUNCTION
++ 	separate_alt_debug_file_exists
++ 
++ SYNOPSIS
++ 	bfd_boolean separate_alt_debug_file_exists
++ 	  (char *name, unsigned long crc32);
++ 
++ DESCRIPTION
++ 	Checks to see if @var{name} is a file and if its BuildID
++ 	matches @var{buildid}.
++ */
++ 
++ static bfd_boolean
++ separate_alt_debug_file_exists (const char *name,
++ 				const unsigned long buildid ATTRIBUTE_UNUSED)
++ {
++   FILE *f;
++ 
++   BFD_ASSERT (name);
++ 
++   f = real_fopen (name, FOPEN_RB);
++   if (f == NULL)
++     return FALSE;
++ 
++   /* FIXME: Add code to check buildid.  */
++ 
++   fclose (f);
++ 
++   return TRUE;
++ }
+  
+  /*
+  INTERNAL_FUNCTION
+*************** SYNOPSIS
+*** 1238,1253 ****
+  	char *find_separate_debug_file (bfd *abfd);
+  
+  DESCRIPTION
+! 	Searches @var{abfd} for a reference to separate debugging
+! 	information, scans various locations in the filesystem, including
+! 	the file tree rooted at @var{debug_file_directory}, and returns a
+! 	filename of such debugging information if the file is found and has
+! 	matching CRC32.  Returns NULL if no reference to debugging file
+! 	exists, or file cannot be found.
+  */
+  
+  static char *
+! find_separate_debug_file (bfd *abfd, const char *debug_file_directory)
+  {
+    char *base;
+    char *dir;
+--- 1318,1341 ----
+  	char *find_separate_debug_file (bfd *abfd);
+  
+  DESCRIPTION
+! 	Searches @var{abfd} for a section called @var{section_name} which
+! 	is expected to contain a reference to a file containing separate
+! 	debugging information.  The function scans various locations in
+! 	the filesystem, including the file tree rooted at
+! 	@var{debug_file_directory}, and returns the first matching
+! 	filename that it finds.  If @var{check_crc} is TRUE then the
+! 	contents of the file must also match the CRC value contained in
+! 	@var{section_name}.  Returns NULL if no valid file could be found.
+  */
+  
++ typedef char *      (* get_func_type) (bfd *, unsigned long *);
++ typedef bfd_boolean (* check_func_type) (const char *, const unsigned long);
++ 
+  static char *
+! find_separate_debug_file (bfd *           abfd,
+! 			  const char *    debug_file_directory,
+! 			  get_func_type   get_func,
+! 			  check_func_type check_func)
+  {
+    char *base;
+    char *dir;
+*************** find_separate_debug_file (bfd *abfd, con
+*** 1268,1274 ****
+        return NULL;
+      }
+  
+!   base = get_debug_link_info (abfd, & crc32);
+    if (base == NULL)
+      return NULL;
+  
+--- 1356,1362 ----
+        return NULL;
+      }
+  
+!   base = get_func (abfd, & crc32);
+    if (base == NULL)
+      return NULL;
+  
+*************** find_separate_debug_file (bfd *abfd, con
+*** 1309,1345 ****
+                    + strlen (base)
+                    + 1);
+    if (debugfile == NULL)
+!     {
+!       free (base);
+!       free (dir);
+!       free (canon_dir);
+!       return NULL;
+!     }
+  
+    /* First try in the same directory as the original file:  */
+    strcpy (debugfile, dir);
+    strcat (debugfile, base);
+  
+!   if (separate_debug_file_exists (debugfile, crc32))
+!     {
+!       free (base);
+!       free (dir);
+!       free (canon_dir);
+!       return debugfile;
+!     }
+  
+    /* Then try in a subdirectory called .debug.  */
+    strcpy (debugfile, dir);
+    strcat (debugfile, ".debug/");
+    strcat (debugfile, base);
+  
+!   if (separate_debug_file_exists (debugfile, crc32))
+!     {
+!       free (base);
+!       free (dir);
+!       free (canon_dir);
+!       return debugfile;
+!     }
+  
+    /* Then try in the global debug dir for Fedora libraries.  */
+    sprintf (debugfile, "%s%s%s", FEDORA_LIB_DEBUG_DIR, dir, base);
+--- 1397,1418 ----
+                    + strlen (base)
+                    + 1);
+    if (debugfile == NULL)
+!     goto found; /* Actually this returns NULL.  */
+  
+    /* First try in the same directory as the original file:  */
+    strcpy (debugfile, dir);
+    strcat (debugfile, base);
+  
+!   if (check_func (debugfile, crc32))
+!     goto found;
+  
+    /* Then try in a subdirectory called .debug.  */
+    strcpy (debugfile, dir);
+    strcat (debugfile, ".debug/");
+    strcat (debugfile, base);
+  
+!   if (check_func (debugfile, crc32))
+!     goto found;
+  
+    /* Then try in the global debug dir for Fedora libraries.  */
+    sprintf (debugfile, "%s%s%s", FEDORA_LIB_DEBUG_DIR, dir, base);
+*************** find_separate_debug_file (bfd *abfd, con
+*** 1371,1389 ****
+    strcat (debugfile, canon_dir);
+    strcat (debugfile, base);
+  
+!   if (separate_debug_file_exists (debugfile, crc32))
+!     {
+!       free (base);
+!       free (dir);
+!       free (canon_dir);
+!       return debugfile;
+!     }
+  
+    free (debugfile);
+    free (base);
+    free (dir);
+    free (canon_dir);
+!   return NULL;
+  }
+  
+  
+--- 1444,1461 ----
+    strcat (debugfile, canon_dir);
+    strcat (debugfile, base);
+  
+!   if (check_func (debugfile, crc32))
+!     goto found;
+  
++   /* Failed to find the file.  */
+    free (debugfile);
++   debugfile = NULL;
++ 
++  found:
+    free (base);
+    free (dir);
+    free (canon_dir);
+!   return debugfile;
+  }
+  
+  
+*************** RETURNS
+*** 1416,1422 ****
+  char *
+  bfd_follow_gnu_debuglink (bfd *abfd, const char *dir)
+  {
+!   return find_separate_debug_file (abfd, dir);
+  }
+  
+  /*
+--- 1488,1530 ----
+  char *
+  bfd_follow_gnu_debuglink (bfd *abfd, const char *dir)
+  {
+!   return find_separate_debug_file (abfd, dir,
+! 				   get_debug_link_info,
+! 				   separate_debug_file_exists);
+! }
+! 
+! /*
+! FUNCTION
+! 	bfd_follow_gnu_debugaltlink
+! 
+! SYNOPSIS
+! 	char *bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir);
+! 
+! DESCRIPTION
+! 
+! 	Takes a BFD and searches it for a .gnu_debugaltlink section.  If this
+! 	section is found, it examines the section for the name of a file
+! 	containing auxiliary debugging information.  It	then searches the
+! 	filesystem for this file in a set of standard locations, including
+! 	the directory tree rooted at @var{dir}, and if found returns the
+! 	full filename.
+! 
+! 	If @var{dir} is NULL, it will search a default path configured into
+! 	libbfd at build time.  [FIXME: This feature is not currently
+! 	implemented].
+! 
+! RETURNS
+! 	<<NULL>> on any errors or failure to locate the debug file,
+! 	otherwise a pointer to a heap-allocated string containing the
+! 	filename.  The caller is responsible for freeing this string.
+! */
+! 
+! char *
+! bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir)
+! {
+!   return find_separate_debug_file (abfd, dir,
+! 				   bfd_get_alt_debug_link_info,
+! 				   separate_alt_debug_file_exists);
+  }
+  
+  /*
+
diff --git a/binutils-2.23.2-kernel-ld-r.patch b/binutils-2.23.2-kernel-ld-r.patch
new file mode 100644
index 0000000..50c2878
--- /dev/null
+++ b/binutils-2.23.2-kernel-ld-r.patch
@@ -0,0 +1,2734 @@
+diff -cpr ../binutils-2.23.2.orig/bfd/bfd.c bfd/bfd.c
+*** ../binutils-2.23.2.orig/bfd/bfd.c	2013-05-14 16:39:24.681717759 +0100
+--- bfd/bfd.c	2013-05-14 16:40:06.988718932 +0100
+*************** CODE_FRAGMENT
+*** 43,48 ****
+--- 43,56 ----
+  .    both_direction = 3
+  .  };
+  .
++ .enum bfd_lto_object_type
++ .  {
++ .    lto_non_object,
++ .    lto_non_ir_object,
++ .    lto_ir_object,
++ .    lto_mixed_object
++ .  };
++ .
+  .struct bfd
+  .{
+  .  {* A unique identifier of the BFD  *}
+*************** CODE_FRAGMENT
+*** 190,195 ****
+--- 198,206 ----
+  .  {* The last section on the section list.  *}
+  .  struct bfd_section *section_last;
+  .
++ .  {* The object-only section on the section list.  *}
++ .  struct bfd_section *object_only_section;
++ .
+  .  {* The number of sections.  *}
+  .  unsigned int section_count;
+  .
+*************** CODE_FRAGMENT
+*** 308,313 ****
+--- 319,327 ----
+  .  {* Set if only required symbols should be added in the link hash table for
+  .     this object.  Used by VMS linkers.  *}
+  .  unsigned int selective_search : 1;
++ .
++ .  {* LTO object type.  *}
++ .  unsigned int lto_type : 2;
+  .};
+  .
+  */
+*************** bfd_demangle (bfd *abfd, const char *nam
+*** 2026,2028 ****
+--- 2040,2075 ----
+  
+    return res;
+  }
++ 
++ /*
++ FUNCTION
++ 	bfd_group_signature
++ 
++ SYNOPSIS
++ 	asymbol *bfd_group_signature (asection *group, asymbol **isympp);
++ 
++ DESCRIPTION
++ 	Return a pointer to the symbol used as a signature for GROUP.
++ */
++ 
++ asymbol *
++ bfd_group_signature (asection *group, asymbol **isympp)
++ {
++   bfd *abfd = group->owner;
++   Elf_Internal_Shdr *ghdr;
++ 
++   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
++     return NULL;
++ 
++   ghdr = &elf_section_data (group)->this_hdr;
++   if (ghdr->sh_link < elf_numsections (abfd))
++     {
++       const struct elf_backend_data *bed = get_elf_backend_data (abfd);
++       Elf_Internal_Shdr *symhdr = elf_elfsections (abfd) [ghdr->sh_link];
++ 
++       if (symhdr->sh_type == SHT_SYMTAB
++ 	  && ghdr->sh_info < symhdr->sh_size / bed->s->sizeof_sym)
++ 	return isympp[ghdr->sh_info - 1];
++     }
++   return NULL;
++ }
+diff -cpr ../binutils-2.23.2.orig/bfd/bfd-in2.h bfd/bfd-in2.h
+*** ../binutils-2.23.2.orig/bfd/bfd-in2.h	2013-05-14 16:39:24.640717758 +0100
+--- bfd/bfd-in2.h	2013-05-14 16:42:03.217722154 +0100
+*************** struct bfd_section *bfd_create_gnu_debug
+*** 1050,1055 ****
+--- 1050,1058 ----
+  bfd_boolean bfd_fill_in_gnu_debuglink_section
+     (bfd *abfd, struct bfd_section *sect, const char *filename);
+  
++ const char *bfd_extract_object_only_section
++    (bfd *abfd);
++ 
+  /* Extracted from libbfd.c.  */
+  
+  /* Byte swapping macros for user section data.  */
+*************** extern asection std_section[4];
+*** 1594,1599 ****
+--- 1597,1605 ----
+    || ((SEC) == bfd_com_section_ptr)            \
+    || ((SEC) == bfd_ind_section_ptr))
+  
++ /* GNU object-only section name.  */
++ #define GNU_OBJECT_ONLY_SECTION_NAME ".gnu_object_only"
++ 
+  /* Macros to handle insertion and deletion of a bfd's sections.  These
+     only handle the list pointers, ie. do not adjust section_count,
+     target_index etc.  */
+*************** enum bfd_direction
+*** 5681,5686 ****
+--- 5687,5700 ----
+      both_direction = 3
+    };
+  
++ enum bfd_lto_object_type
++   {
++     lto_non_object,
++     lto_non_ir_object,
++     lto_ir_object,
++     lto_mixed_object
++   };
++ 
+  struct bfd
+  {
+    /* A unique identifier of the BFD  */
+*************** struct bfd
+*** 5828,5833 ****
+--- 5842,5850 ----
+    /* The last section on the section list.  */
+    struct bfd_section *section_last;
+  
++   /* The object-only section on the section list.  */
++   struct bfd_section *object_only_section;
++ 
+    /* The number of sections.  */
+    unsigned int section_count;
+  
+*************** struct bfd
+*** 5946,5951 ****
+--- 5963,5971 ----
+    /* Set if only required symbols should be added in the link hash table for
+       this object.  Used by VMS linkers.  */
+    unsigned int selective_search : 1;
++ 
++   /* LTO object type.  */
++   unsigned int lto_type : 2;
+  };
+  
+  typedef enum bfd_error
+*************** void bfd_emul_set_commonpagesize (const
+*** 6167,6172 ****
+--- 6187,6194 ----
+  
+  char *bfd_demangle (bfd *, const char *, int);
+  
++ asymbol *bfd_group_signature (asection *group, asymbol **isympp);
++ 
+  /* Extracted from archive.c.  */
+  symindex bfd_get_next_mapent
+     (bfd *abfd, symindex previous, carsym **sym);
+diff -cpr ../binutils-2.23.2.orig/bfd/elf.c bfd/elf.c
+*** ../binutils-2.23.2.orig/bfd/elf.c	2013-05-14 16:39:25.317717777 +0100
+--- bfd/elf.c	2013-05-14 16:40:06.993718932 +0100
+*************** static const struct bfd_elf_special_sect
+*** 2092,2097 ****
+--- 2092,2098 ----
+    { STRING_COMMA_LEN (".gnu.linkonce.b"), -2, SHT_NOBITS,      SHF_ALLOC + SHF_WRITE },
+    { STRING_COMMA_LEN (".gnu.lto_"),       -1, SHT_PROGBITS,    SHF_EXCLUDE },
+    { STRING_COMMA_LEN (".got"),             0, SHT_PROGBITS,    SHF_ALLOC + SHF_WRITE },
++   { STRING_COMMA_LEN (".gnu_object_only"), 0, SHT_GNU_OBJECT_ONLY, SHF_EXCLUDE },
+    { STRING_COMMA_LEN (".gnu.version"),     0, SHT_GNU_versym,  0 },
+    { STRING_COMMA_LEN (".gnu.version_d"),   0, SHT_GNU_verdef,  0 },
+    { STRING_COMMA_LEN (".gnu.version_r"),   0, SHT_GNU_verneed, 0 },
+diff -cpr ../binutils-2.23.2.orig/bfd/elflink.c bfd/elflink.c
+*** ../binutils-2.23.2.orig/bfd/elflink.c	2013-05-14 16:39:25.280717776 +0100
+--- bfd/elflink.c	2013-05-14 16:40:06.997718932 +0100
+*************** elf_link_add_archive_symbols (bfd *abfd,
+*** 5127,5132 ****
+--- 5127,5135 ----
+  	     something wrong with the archive.  */
+  	  if (element->archive_pass != 0)
+  	    {
++ 	      /* Don't load the IR archive member twice.  */
++ 	      if (element->lto_type == lto_ir_object)
++ 		continue;
+  	      bfd_set_error (bfd_error_bad_value);
+  	      goto error_return;
+  	    }
+diff -cpr ../binutils-2.23.2.orig/bfd/format.c bfd/format.c
+*** ../binutils-2.23.2.orig/bfd/format.c	2013-05-14 16:39:24.265717748 +0100
+--- bfd/format.c	2013-05-14 16:40:07.006718933 +0100
+*************** bfd_check_format (bfd *abfd, bfd_format
+*** 95,100 ****
+--- 95,127 ----
+    return bfd_check_format_matches (abfd, format, NULL);
+  }
+  
++ /* Set lto_type in ABFD.  */
++ 
++ static void
++ bfd_set_lto_type (bfd *abfd)
++ {
++   if (abfd->format == bfd_object
++       && abfd->lto_type == lto_non_object
++       && (abfd->flags & (DYNAMIC | EXEC_P)) == 0)
++     {
++       asection *sec;
++       enum bfd_lto_object_type type = lto_non_ir_object;
++       for (sec = abfd->sections; sec != NULL; sec = sec->next)
++ 	{
++ 	  if (strcmp (sec->name, GNU_OBJECT_ONLY_SECTION_NAME) == 0)
++ 	    {
++ 	      type = lto_mixed_object;
++ 	      abfd->object_only_section = sec;
++ 	      break;
++ 	    }
++ 	  else if (type != lto_ir_object
++ 		   && strncmp (sec->name, ".gnu.lto_", 9) == 0)
++ 	    type = lto_ir_object;
++ 	}
++       abfd->lto_type = type;
++     }
++ }
++ 
+  /*
+  FUNCTION
+  	bfd_check_format_matches
+*************** bfd_check_format_matches (bfd *abfd, bfd
+*** 136,142 ****
+      }
+  
+    if (abfd->format != bfd_unknown)
+!     return abfd->format == format;
+  
+    /* Since the target type was defaulted, check them
+       all in the hope that one will be uniquely recognized.  */
+--- 163,172 ----
+      }
+  
+    if (abfd->format != bfd_unknown)
+!     {
+!       bfd_set_lto_type (abfd);
+!       return abfd->format == format;
+!     }
+  
+    /* Since the target type was defaulted, check them
+       all in the hope that one will be uniquely recognized.  */
+*************** bfd_check_format_matches (bfd *abfd, bfd
+*** 322,327 ****
+--- 352,360 ----
+  
+        if (matching_vector)
+  	free (matching_vector);
++ 
++       bfd_set_lto_type (abfd);
++ 
+        return TRUE;			/* File position has moved, BTW.  */
+      }
+  
+diff -cpr ../binutils-2.23.2.orig/bfd/opncls.c bfd/opncls.c
+*** ../binutils-2.23.2.orig/bfd/opncls.c	2013-05-14 16:39:23.701717732 +0100
+--- bfd/opncls.c	2013-05-14 16:40:07.008718933 +0100
+*************** bfd_fill_in_gnu_debuglink_section (bfd *
+*** 1569,1571 ****
+--- 1569,1637 ----
+  
+    return TRUE;
+  }
++ 
++ /*
++ FUNCTION
++ 	bfd_extract_object_only_section
++ 
++ SYNOPSIS
++ 	const char *bfd_extract_object_only_section
++ 	  (bfd *abfd);
++ 
++ DESCRIPTION
++ 
++ 	Takes a @var{ABFD} and extract the .gnu_object_only section into
++ 	a temporary file.
++ 
++ RETURNS
++ 	The name of the temporary file is returned if all is ok.
++ 	Otherwise <<NULL>> is returned and bfd_error is set.
++ */
++ 
++ const char *
++ bfd_extract_object_only_section (bfd *abfd)
++ {
++   asection *sec = abfd->object_only_section;
++   const char *name;
++   FILE *file;
++   bfd_byte *memhunk = NULL;
++   size_t off, size;
++   bfd_error_type err;
++ 
++   /* Get a temporary object-only file.  */
++   name = make_temp_file (".obj-only.o");
++ 
++   /* Open the object-only file.  */
++   file = real_fopen (name, FOPEN_WB);
++   if (!bfd_get_full_section_contents (abfd, sec, &memhunk))
++     {
++       err = bfd_get_error ();
++ 
++ loser:
++       free (memhunk);
++       fclose (file);
++       unlink (name);
++       bfd_set_error (err);
++       return NULL;
++     }
++ 
++   off = 0;
++   size = sec->size;
++   while (off != size)
++     {
++       size_t written, nwrite = size - off;
++ 
++       written = fwrite (memhunk + off, 1, nwrite, file);
++       if (written < nwrite && ferror (file))
++ 	{
++ 	  err = bfd_error_system_call;
++ 	  goto loser;
++ 	}
++ 
++       off += written;
++     }
++ 
++   free (memhunk);
++   fclose (file);
++   return name;
++ }
+diff -cpr ../binutils-2.23.2.orig/bfd/plugin.c bfd/plugin.c
+*** ../binutils-2.23.2.orig/bfd/plugin.c	2013-05-14 16:39:25.137717772 +0100
+--- bfd/plugin.c	2013-05-14 16:40:07.010718933 +0100
+*************** register_claim_file (ld_plugin_claim_fil
+*** 130,135 ****
+--- 130,268 ----
+    return LDPS_OK;
+  }
+  
++ static asection bfd_plugin_fake_text_section
++   = BFD_FAKE_SECTION (bfd_plugin_fake_text_section, 0, 0, ".text", 0);
++ static asection bfd_plugin_fake_common_section
++   = BFD_FAKE_SECTION (bfd_plugin_fake_common_section, SEC_IS_COMMON, 0,
++ 		      NULL, 0);
++ 
++ /* Get symbols from object only section.  */
++ 
++ static void
++ bfd_plugin_get_symbols_in_object_only (bfd *abfd)
++ {
++   struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
++   const char *object_only_file;
++   bfd *nbfd;
++   long storage;
++   long object_only_nsyms, added_nsyms, i;
++   asymbol **object_only_syms, **added_syms;
++ 
++   plugin_data->object_only_syms = NULL;
++   plugin_data->object_only_nsyms = 0;
++ 
++   if (abfd->sections == NULL && abfd->my_archive == NULL)
++     {
++       nbfd = bfd_openr (abfd->filename, NULL);
++       if (nbfd == NULL || !bfd_check_format (nbfd, bfd_object))
++ 	{
++ 	  (*_bfd_error_handler)
++ 	    (_("%s: failed to open to extract object only section: %s"),
++ 	     abfd->filename, bfd_errmsg (bfd_get_error ()));
++ 	  bfd_close (nbfd);
++ 	  return;
++ 	}
++     }
++   else
++     {
++       if (!bfd_check_format (abfd, bfd_object))
++ 	{
++ 	  (*_bfd_error_handler)
++ 	    (_("%B: invalid file to extract object only section: %s"),
++ 	     abfd, bfd_errmsg (bfd_get_error ()));
++ 	  return;
++ 	}
++       nbfd = abfd;
++     }
++ 
++   if (nbfd->lto_type == lto_mixed_object
++       && (nbfd->flags & HAS_SYMS) != 0)
++     {
++       object_only_file = bfd_extract_object_only_section (nbfd);
++       if (object_only_file == NULL)
++ 	(*_bfd_error_handler)
++ 	  (_("%B: failed to extract object only section: %s"),
++ 	   abfd, bfd_errmsg (bfd_get_error ()));
++     }
++   else
++     object_only_file = NULL;
++ 
++   /* Close the new bfd we just opened.  */
++   if (nbfd != abfd)
++     bfd_close (nbfd);
++ 
++   /* Return if there is no object only section or there is no
++      symbol in object only section.  */
++   if (!object_only_file)
++     return;
++ 
++   /* Open the file containing object only section.  */
++   nbfd = bfd_openr (object_only_file, NULL);
++   if (!bfd_check_format (nbfd, bfd_object))
++     {
++       (*_bfd_error_handler)
++ 	(_("%B: failed to open object only section: %s"),
++ 	 abfd, bfd_errmsg (bfd_get_error ()));
++       goto quit;
++     }
++ 
++   storage = bfd_get_symtab_upper_bound (nbfd);
++   if (storage <= 0)
++     {
++       if (storage < 0)
++ 	(*_bfd_error_handler)
++ 	  (_("%B: failed to get symbol table in object only section: %s"),
++ 	   abfd, bfd_errmsg (bfd_get_error ()));
++ 
++       goto quit;
++     }
++ 
++   object_only_syms = (asymbol **) bfd_malloc (storage);
++   object_only_nsyms = bfd_canonicalize_symtab (nbfd, object_only_syms);
++ 
++   /* FIXME: We waste some spaces if not all symbols are copied.  */
++   added_syms = (asymbol **) bfd_alloc (abfd, storage);
++   added_nsyms = 0;
++ 
++   /* Copy only global symbols from object only section.  */
++   for (i = 0; i < object_only_nsyms; i++)
++     {
++       asection *sec = object_only_syms[i]->section;
++       flagword flags = object_only_syms[i]->flags;
++       asymbol *s;
++ 
++       if (bfd_is_com_section (sec))
++ 	sec = &bfd_plugin_fake_common_section;
++       else if (bfd_is_und_section (sec))
++ 	;
++       else if ((flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0)
++ 	sec = &bfd_plugin_fake_text_section;
++       else
++ 	continue;
++ 
++       s = bfd_alloc (abfd, sizeof (asymbol)); 
++       BFD_ASSERT (s);
++       added_syms[added_nsyms++] = s;
++ 
++       s->section = sec;
++       s->the_bfd = abfd;
++       s->name = xstrdup (object_only_syms[i]->name);
++       s->value = 0;
++       s->flags = flags;
++       s->udata.p = NULL;
++     }
++ 
++   plugin_data->object_only_syms = added_syms;
++   plugin_data->object_only_nsyms = added_nsyms;
++ 
++   free (object_only_syms);
++ 
++ quit:
++   /* Close and remove the object only section file.  */
++   bfd_close (nbfd);
++   unlink (object_only_file);
++ }
++ 
+  static enum ld_plugin_status
+  add_symbols (void * handle,
+  	     int nsyms,
+*************** add_symbols (void * handle,
+*** 142,148 ****
+    plugin_data->nsyms = nsyms;
+    plugin_data->syms = syms;
+  
+!   if (nsyms != 0)
+      abfd->flags |= HAS_SYMS;
+  
+    abfd->tdata.plugin_data = plugin_data;
+--- 275,283 ----
+    plugin_data->nsyms = nsyms;
+    plugin_data->syms = syms;
+  
+!   bfd_plugin_get_symbols_in_object_only (abfd);
+! 
+!   if ((nsyms + plugin_data->object_only_nsyms) != 0)
+      abfd->flags |= HAS_SYMS;
+  
+    abfd->tdata.plugin_data = plugin_data;
+*************** static long
+*** 389,395 ****
+  bfd_plugin_get_symtab_upper_bound (bfd *abfd)
+  {
+    struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
+!   long nsyms = plugin_data->nsyms;
+  
+    BFD_ASSERT (nsyms >= 0);
+  
+--- 524,531 ----
+  bfd_plugin_get_symtab_upper_bound (bfd *abfd)
+  {
+    struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
+!   /* Add symbols from object only section.  */
+!   long nsyms = plugin_data->nsyms + plugin_data->object_only_nsyms;
+  
+    BFD_ASSERT (nsyms >= 0);
+  
+*************** bfd_plugin_canonicalize_symtab (bfd *abf
+*** 423,434 ****
+    struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
+    long nsyms = plugin_data->nsyms;
+    const struct ld_plugin_symbol *syms = plugin_data->syms;
+!   static asection fake_section;
+!   static asection fake_common_section;
+!   int i;
+! 
+!   fake_section.name = ".text";
+!   fake_common_section.flags = SEC_IS_COMMON;
+  
+    for (i = 0; i < nsyms; i++)
+      {
+--- 559,565 ----
+    struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
+    long nsyms = plugin_data->nsyms;
+    const struct ld_plugin_symbol *syms = plugin_data->syms;
+!   int i, j;
+  
+    for (i = 0; i < nsyms; i++)
+      {
+*************** bfd_plugin_canonicalize_symtab (bfd *abf
+*** 441,450 ****
+        s->name = syms[i].name;
+        s->value = 0;
+        s->flags = convert_flags (&syms[i]);
+        switch (syms[i].def)
+  	{
+  	case LDPK_COMMON:
+! 	  s->section = &fake_common_section;
+  	  break;
+  	case LDPK_UNDEF:
+  	case LDPK_WEAKUNDEF:
+--- 572,582 ----
+        s->name = syms[i].name;
+        s->value = 0;
+        s->flags = convert_flags (&syms[i]);
++       s->udata.p = NULL;
+        switch (syms[i].def)
+  	{
+  	case LDPK_COMMON:
+! 	  s->section = &bfd_plugin_fake_common_section;
+  	  break;
+  	case LDPK_UNDEF:
+  	case LDPK_WEAKUNDEF:
+*************** bfd_plugin_canonicalize_symtab (bfd *abf
+*** 452,466 ****
+  	  break;
+  	case LDPK_DEF:
+  	case LDPK_WEAKDEF:
+! 	  s->section = &fake_section;
+  	  break;
+  	default:
+  	  BFD_ASSERT (0);
+  	}
+- 
+-       s->udata.p = (void *) &syms[i];
+      }
+  
+    return nsyms;
+  }
+  
+--- 584,601 ----
+  	  break;
+  	case LDPK_DEF:
+  	case LDPK_WEAKDEF:
+! 	  s->section = &bfd_plugin_fake_text_section;
+  	  break;
+  	default:
+  	  BFD_ASSERT (0);
+  	}
+      }
+  
++   /* Copy symbols from object only section.  */
++   nsyms += plugin_data->object_only_nsyms;
++   for (j = 0; j < plugin_data->object_only_nsyms; j++, i++)
++     alocation[i] = plugin_data->object_only_syms[j];
++ 
+    return nsyms;
+  }
+  
+diff -cpr ../binutils-2.23.2.orig/bfd/plugin.h bfd/plugin.h
+*** ../binutils-2.23.2.orig/bfd/plugin.h	2013-05-14 16:39:25.481717782 +0100
+--- bfd/plugin.h	2013-05-14 16:40:07.010718933 +0100
+*************** typedef struct plugin_data_struct
+*** 30,35 ****
+--- 30,37 ----
+  {
+    int nsyms;
+    const struct ld_plugin_symbol *syms;
++   int object_only_nsyms;
++   asymbol **object_only_syms;
+  }
+  plugin_data_struct;
+  
+diff -cpr ../binutils-2.23.2.orig/bfd/section.c bfd/section.c
+*** ../binutils-2.23.2.orig/bfd/section.c	2013-05-14 16:39:26.180717801 +0100
+--- bfd/section.c	2013-05-14 16:43:06.082723897 +0100
+*************** CODE_FRAGMENT
+*** 571,576 ****
+--- 571,579 ----
+  .  || ((SEC) == bfd_com_section_ptr)		\
+  .  || ((SEC) == bfd_ind_section_ptr))
+  .
++ .{* GNU object-only section name.  *}
++ .#define GNU_OBJECT_ONLY_SECTION_NAME ".gnu_object_only"
++ .
+  .{* Macros to handle insertion and deletion of a bfd's sections.  These
+  .   only handle the list pointers, ie. do not adjust section_count,
+  .   target_index etc.  *}
+diff -cpr ../binutils-2.23.2.orig/binutils/objcopy.c binutils/objcopy.c
+*** ../binutils-2.23.2.orig/binutils/objcopy.c	2013-05-14 16:39:36.214718079 +0100
+--- binutils/objcopy.c	2013-05-14 16:45:04.631727183 +0100
+*************** is_specified_symbol (const char *name, h
+*** 943,972 ****
+    return htab_find (htab, name) != NULL;
+  }
+  
+- /* Return a pointer to the symbol used as a signature for GROUP.  */
+- 
+- static asymbol *
+- group_signature (asection *group)
+- {
+-   bfd *abfd = group->owner;
+-   Elf_Internal_Shdr *ghdr;
+- 
+-   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+-     return NULL;
+- 
+-   ghdr = &elf_section_data (group)->this_hdr;
+-   if (ghdr->sh_link < elf_numsections (abfd))
+-     {
+-       const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+-       Elf_Internal_Shdr *symhdr = elf_elfsections (abfd) [ghdr->sh_link];
+- 
+-       if (symhdr->sh_type == SHT_SYMTAB
+- 	  && ghdr->sh_info < symhdr->sh_size / bed->s->sizeof_sym)
+- 	return isympp[ghdr->sh_info - 1];
+-     }
+-   return NULL;
+- }
+- 
+  /* Return TRUE if the section is a DWO section.  */
+  
+  static bfd_boolean
+--- 943,948 ----
+*************** is_strip_section (bfd *abfd ATTRIBUTE_UN
+*** 1034,1040 ****
+        /* PR binutils/3181
+  	 If we are going to strip the group signature symbol, then
+  	 strip the group section too.  */
+!       gsym = group_signature (sec);
+        if (gsym != NULL)
+  	gname = gsym->name;
+        else
+--- 1010,1016 ----
+        /* PR binutils/3181
+  	 If we are going to strip the group signature symbol, then
+  	 strip the group section too.  */
+!       gsym = bfd_group_signature (sec, isympp);
+        if (gsym != NULL)
+  	gname = gsym->name;
+        else
+*************** setup_section (bfd *ibfd, sec_ptr isecti
+*** 2633,2639 ****
+  
+    if ((isection->flags & SEC_GROUP) != 0)
+      {
+!       asymbol *gsym = group_signature (isection);
+  
+        if (gsym != NULL)
+  	{
+--- 2609,2615 ----
+  
+    if ((isection->flags & SEC_GROUP) != 0)
+      {
+!       asymbol *gsym = bfd_group_signature (isection, isympp);
+  
+        if (gsym != NULL)
+  	{
+diff -cpr ../binutils-2.23.2.orig/binutils/readelf.c binutils/readelf.c
+*** ../binutils-2.23.2.orig/binutils/readelf.c	2013-05-14 16:39:35.668718064 +0100
+--- binutils/readelf.c	2013-05-14 16:40:07.022718933 +0100
+*************** get_section_type_name (unsigned int sh_t
+*** 3101,3106 ****
+--- 3101,3107 ----
+      case 0x7ffffffd:		return "AUXILIARY";
+      case 0x7fffffff:		return "FILTER";
+      case SHT_GNU_LIBLIST:	return "GNU_LIBLIST";
++     case SHT_GNU_OBJECT_ONLY:	return "GNU_OBJECT_ONLY";
+  
+      default:
+        if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
+diff -cpr ../binutils-2.23.2.orig/include/bfdlink.h include/bfdlink.h
+*** ../binutils-2.23.2.orig/include/bfdlink.h	2013-05-14 16:39:19.745717623 +0100
+--- include/bfdlink.h	2013-05-14 16:40:07.023718933 +0100
+*************** struct bfd_link_info
+*** 380,385 ****
+--- 380,391 ----
+    /* TRUE if ok to have multiple definition.  */
+    unsigned int allow_multiple_definition: 1;
+  
++   /* TRUE if .gnu_object_only section should be created.  */
++   unsigned int emit_gnu_object_only: 1;
++ 
++   /* TRUE if .gnu_object_only section is being created.  */
++   unsigned int emitting_gnu_object_only: 1;
++ 
+    /* TRUE if ok to have version with no definition.  */
+    unsigned int allow_undefined_version: 1;
+  
+diff -cpr ../binutils-2.23.2.orig/include/elf/common.h include/elf/common.h
+*** ../binutils-2.23.2.orig/include/elf/common.h	2013-05-14 16:39:19.628717619 +0100
+--- include/elf/common.h	2013-05-14 16:40:07.023718933 +0100
+***************
+*** 472,477 ****
+--- 472,478 ----
+  #define SHT_GNU_ATTRIBUTES 0x6ffffff5	/* Object attributes */
+  #define SHT_GNU_HASH	0x6ffffff6	/* GNU style symbol hash table */
+  #define SHT_GNU_LIBLIST	0x6ffffff7	/* List of prelink dependencies */
++ #define SHT_GNU_OBJECT_ONLY 0x6ffffff8	/* Object only */
+  
+  /* The next three section types are defined by Solaris, and are named
+     SHT_SUNW*.  We use them in GNU code, so we also define SHT_GNU*
+diff -cpr ../binutils-2.23.2.orig/ld/emultempl/alphaelf.em ld/emultempl/alphaelf.em
+*** ../binutils-2.23.2.orig/ld/emultempl/alphaelf.em	2013-05-14 16:39:37.461718114 +0100
+--- ld/emultempl/alphaelf.em	2013-05-14 16:40:07.030718933 +0100
+*************** alpha_finish (void)
+*** 100,106 ****
+    if (limit_32bit)
+      elf_elfheader (link_info.output_bfd)->e_flags |= EF_ALPHA_32BIT;
+  
+!   finish_default ();
+  }
+  EOF
+  
+--- 100,106 ----
+    if (limit_32bit)
+      elf_elfheader (link_info.output_bfd)->e_flags |= EF_ALPHA_32BIT;
+  
+!   gld${EMULATION_NAME}_finish ();
+  }
+  EOF
+  
+diff -cpr ../binutils-2.23.2.orig/ld/emultempl/armelf.em ld/emultempl/armelf.em
+*** ../binutils-2.23.2.orig/ld/emultempl/armelf.em	2013-05-14 16:39:37.458718114 +0100
+--- ld/emultempl/armelf.em	2013-05-14 16:40:07.033718933 +0100
+*************** gld${EMULATION_NAME}_after_allocation (v
+*** 366,372 ****
+  }
+  
+  static void
+! gld${EMULATION_NAME}_finish (void)
+  {
+    struct bfd_link_hash_entry * h;
+  
+--- 366,372 ----
+  }
+  
+  static void
+! arm_finish (void)
+  {
+    struct bfd_link_hash_entry * h;
+  
+*************** gld${EMULATION_NAME}_finish (void)
+*** 389,395 ****
+  	}
+      }
+  
+!   finish_default ();
+  
+    if (thumb_entry_symbol)
+      {
+--- 389,395 ----
+  	}
+      }
+  
+!   gld${EMULATION_NAME}_finish ();
+  
+    if (thumb_entry_symbol)
+      {
+*************** LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=
+*** 690,693 ****
+  LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
+  
+  # Call the extra arm-elf function
+! LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+--- 690,693 ----
+  LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
+  
+  # Call the extra arm-elf function
+! LDEMUL_FINISH=arm_finish
+diff -cpr ../binutils-2.23.2.orig/ld/emultempl/elf32.em ld/emultempl/elf32.em
+*** ../binutils-2.23.2.orig/ld/emultempl/elf32.em	2013-05-14 16:39:37.465718114 +0100
+--- ld/emultempl/elf32.em	2013-05-14 16:40:07.035718933 +0100
+*************** static void gld${EMULATION_NAME}_before_
+*** 68,73 ****
+--- 68,74 ----
+  static void gld${EMULATION_NAME}_after_allocation (void);
+  static lang_output_section_statement_type *gld${EMULATION_NAME}_place_orphan
+    (asection *, const char *, int);
++ static void gld${EMULATION_NAME}_finish (void);
+  EOF
+  
+  if [ "x${USE_LIBPATH}" = xyes ] ; then
+*************** output_rel_find (asection *sec, int isdy
+*** 1764,1769 ****
+--- 1765,1772 ----
+    return last;
+  }
+  
++ static int orphan_init_done = 0;
++ 
+  /* Place an orphan section.  We use this to put random SHF_ALLOC
+     sections in the right segment.  */
+  
+*************** gld${EMULATION_NAME}_place_orphan (asect
+*** 1772,1778 ****
+  				   const char *secname,
+  				   int constraint)
+  {
+!   static struct orphan_save hold[] =
+      {
+        { ".text",
+  	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
+--- 1775,1781 ----
+  				   const char *secname,
+  				   int constraint)
+  {
+!   static struct orphan_save orig_hold[] =
+      {
+        { ".text",
+  	SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
+*************** gld${EMULATION_NAME}_place_orphan (asect
+*** 1799,1804 ****
+--- 1802,1808 ----
+  	SEC_HAS_CONTENTS,
+  	0, 0, 0, 0 },
+      };
++   static struct orphan_save hold[ARRAY_SIZE (orig_hold)];
+    enum orphan_save_index
+      {
+        orphan_text = 0,
+*************** gld${EMULATION_NAME}_place_orphan (asect
+*** 1810,1816 ****
+        orphan_sdata,
+        orphan_nonalloc
+      };
+-   static int orphan_init_done = 0;
+    struct orphan_save *place;
+    lang_output_section_statement_type *after;
+    lang_output_section_statement_type *os;
+--- 1814,1819 ----
+*************** gld${EMULATION_NAME}_place_orphan (asect
+*** 1887,1901 ****
+  
+    if (!orphan_init_done)
+      {
+!       struct orphan_save *ho;
+  
+        for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
+  	if (ho->name != NULL)
+  	  {
+  	    ho->os = lang_output_section_find (ho->name);
+  	    if (ho->os != NULL && ho->os->flags == 0)
+  	      ho->os->flags = ho->flags;
+  	  }
+        orphan_init_done = 1;
+      }
+  
+--- 1890,1911 ----
+  
+    if (!orphan_init_done)
+      {
+!       struct orphan_save *ho, *horig;
+  
+        for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
++       for (ho = hold, horig = orig_hold;
++ 	   ho < hold + ARRAY_SIZE (hold);
++ 	   ++ho, ++horig)
++ 	{
++ 	  *ho = *horig;
++ 	  if (ho->name != NULL)
+  	if (ho->name != NULL)
+  	  {
+  	    ho->os = lang_output_section_find (ho->name);
+  	    if (ho->os != NULL && ho->os->flags == 0)
+  	      ho->os->flags = ho->flags;
+  	  }
++ 	}
+        orphan_init_done = 1;
+      }
+  
+*************** gld${EMULATION_NAME}_place_orphan (asect
+*** 1965,1970 ****
+--- 1975,2001 ----
+  EOF
+  fi
+  
++ fragment <<EOF
++ 
++ /* Final emulation specific call.  */
++ 
++ static void
++ gld${EMULATION_NAME}_finish (void)
++ {
++ EOF
++ if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
++ fragment <<EOF
++   /* Support the object-only output.  */
++   if (link_info.emit_gnu_object_only)
++     orphan_init_done = 0;
++ 
++ EOF
++ fi
++ fragment <<EOF
++   finish_default ();
++ }
++ EOF
++ 
+  if test x"$LDEMUL_AFTER_ALLOCATION" != xgld"$EMULATION_NAME"_after_allocation; then
+  fragment <<EOF
+  
+*************** struct ld_emulation_xfer_struct ld_${EMU
+*** 2497,2503 ****
+    ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
+    "${EMULATION_NAME}",
+    "${OUTPUT_FORMAT}",
+!   ${LDEMUL_FINISH-finish_default},
+    ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
+    ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
+    ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
+--- 2528,2534 ----
+    ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
+    "${EMULATION_NAME}",
+    "${OUTPUT_FORMAT}",
+!   ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish},
+    ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
+    ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive},
+    ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
+diff -cpr ../binutils-2.23.2.orig/ld/emultempl/ppc64elf.em ld/emultempl/ppc64elf.em
+*** ../binutils-2.23.2.orig/ld/emultempl/ppc64elf.em	2013-05-14 16:39:37.454718113 +0100
+--- ld/emultempl/ppc64elf.em	2013-05-14 16:40:07.044718934 +0100
+*************** gld${EMULATION_NAME}_after_allocation (v
+*** 533,539 ****
+  /* Final emulation specific call.  */
+  
+  static void
+! gld${EMULATION_NAME}_finish (void)
+  {
+    /* e_entry on PowerPC64 points to the function descriptor for
+       _start.  If _start is missing, default to the first function
+--- 533,539 ----
+  /* Final emulation specific call.  */
+  
+  static void
+! ppc_finish (void)
+  {
+    /* e_entry on PowerPC64 points to the function descriptor for
+       _start.  If _start is missing, default to the first function
+*************** gld${EMULATION_NAME}_finish (void)
+*** 565,571 ****
+      }
+  
+    ppc64_elf_restore_symbols (&link_info);
+!   finish_default ();
+  }
+  
+  
+--- 565,571 ----
+      }
+  
+    ppc64_elf_restore_symbols (&link_info);
+!   gld${EMULATION_NAME}_finish ();
+  }
+  
+  
+*************** PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LI
+*** 867,872 ****
+  #
+  LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation
+  LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
+! LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+  LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=ppc_create_output_section_statements
+  LDEMUL_NEW_VERS_PATTERN=gld${EMULATION_NAME}_new_vers_pattern
+--- 867,872 ----
+  #
+  LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation
+  LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
+! LDEMUL_FINISH=ppc_finish
+  LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=ppc_create_output_section_statements
+  LDEMUL_NEW_VERS_PATTERN=gld${EMULATION_NAME}_new_vers_pattern
+diff -cpr ../binutils-2.23.2.orig/ld/emultempl/spuelf.em ld/emultempl/spuelf.em
+*** ../binutils-2.23.2.orig/ld/emultempl/spuelf.em	2013-05-14 16:39:37.453718113 +0100
+--- ld/emultempl/spuelf.em	2013-05-14 16:40:07.045718934 +0100
+*************** spu_elf_relink (void)
+*** 416,422 ****
+  /* Final emulation specific call.  */
+  
+  static void
+! gld${EMULATION_NAME}_finish (void)
+  {
+    if (is_spu_target ())
+      {
+--- 416,422 ----
+  /* Final emulation specific call.  */
+  
+  static void
+! spu_finish (void)
+  {
+    if (is_spu_target ())
+      {
+*************** gld${EMULATION_NAME}_finish (void)
+*** 432,438 ****
+  	einfo ("%P: --auto-overlay ignored with zero local store range\n");
+      }
+  
+!   finish_default ();
+  }
+  
+  static char *
+--- 432,438 ----
+  	einfo ("%P: --auto-overlay ignored with zero local store range\n");
+      }
+  
+!   gld${EMULATION_NAME}_finish ();
+  }
+  
+  static char *
+*************** PARSE_AND_LIST_ARGS_CASES='
+*** 832,836 ****
+  
+  LDEMUL_AFTER_OPEN=spu_after_open
+  LDEMUL_BEFORE_ALLOCATION=spu_before_allocation
+! LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+  LDEMUL_CHOOSE_TARGET=gld${EMULATION_NAME}_choose_target
+--- 832,836 ----
+  
+  LDEMUL_AFTER_OPEN=spu_after_open
+  LDEMUL_BEFORE_ALLOCATION=spu_before_allocation
+! LDEMUL_FINISH=spu_finish
+  LDEMUL_CHOOSE_TARGET=gld${EMULATION_NAME}_choose_target
+diff -cpr ../binutils-2.23.2.orig/ld/ldfile.c ld/ldfile.c
+*** ../binutils-2.23.2.orig/ld/ldfile.c	2013-05-14 16:39:37.164718105 +0100
+--- ld/ldfile.c	2013-05-14 16:40:07.046718934 +0100
+*************** success:
+*** 319,325 ****
+--- 319,327 ----
+  	  plugin_maybe_claim (&file, entry);
+  	}
+      }
++   else
+  #endif /* ENABLE_PLUGINS */
++     cmdline_check_object_only_section (entry->the_bfd, FALSE);
+  
+    /* It opened OK, the format checked out, and the plugins have had
+       their chance to claim it, so this is success.  */
+diff -cpr ../binutils-2.23.2.orig/ld/ldlang.c ld/ldlang.c
+*** ../binutils-2.23.2.orig/ld/ldlang.c	2013-05-14 16:39:39.704718176 +0100
+--- ld/ldlang.c	2013-05-14 17:03:54.030758491 +0100
+***************
+*** 38,43 ****
+--- 38,44 ----
+  #include "ldctor.h"
+  #include "ldfile.h"
+  #include "ldemul.h"
++ #include "ldwrite.h"
+  #include "fnmatch.h"
+  #include "demangle.h"
+  #include "hashtab.h"
+***************
+*** 46,51 ****
+--- 47,55 ----
+  #include "plugin.h"
+  #endif /* ENABLE_PLUGINS */
+  
++ /* FIXME: Put it here to avoid NAME conflict from ldgram.h.  */
++ #include "elf-bfd.h"
++ 
+  #ifndef offsetof
+  #define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER))
+  #endif
+*************** static struct bfd_hash_table lang_define
+*** 69,74 ****
+--- 73,81 ----
+  static lang_statement_list_type *stat_save[10];
+  static lang_statement_list_type **stat_save_ptr = &stat_save[0];
+  static struct unique_sections *unique_section_list;
++ static cmdline_list_type cmdline_object_only_file_list;
++ static cmdline_list_type cmdline_object_only_archive_list;
++ static cmdline_list_type cmdline_temp_object_only_list;
+  
+  /* Forward declarations.  */
+  static void exp_init_os (etree_type *);
+*************** static void lang_record_phdrs (void);
+*** 89,94 ****
+--- 96,105 ----
+  static void lang_do_version_exports_section (void);
+  static void lang_finalize_version_expr_head
+    (struct bfd_elf_version_expr_head *);
++ static void cmdline_lists_init (void);
++ static void cmdline_get_object_only_input_files (void);
++ static void print_cmdline_list (cmdline_union_type *);
++ static bfd_boolean cmdline_on_object_only_archive_list_p (bfd *);
+  
+  /* Exported variables.  */
+  const char *output_target;
+*************** output_section_statement_table_free (voi
+*** 1204,1217 ****
+  /* Build enough state so that the parser can build its tree.  */
+  
+  void
+! lang_init (void)
+  {
+!   obstack_begin (&stat_obstack, 1000);
+  
+    stat_ptr = &statement_list;
+  
+    output_section_statement_table_init ();
+  
+    lang_list_init (stat_ptr);
+  
+    lang_list_init (&input_file_chain);
+--- 1215,1231 ----
+  /* Build enough state so that the parser can build its tree.  */
+  
+  void
+! lang_init (bfd_boolean object_only)
+  {
+!   if (!object_only)
+!     obstack_begin (&stat_obstack, 1000);
+  
+    stat_ptr = &statement_list;
+  
+    output_section_statement_table_init ();
+  
++   cmdline_lists_init ();
++ 
+    lang_list_init (stat_ptr);
+  
+    lang_list_init (&input_file_chain);
+*************** lang_init (void)
+*** 1230,1239 ****
+       simpler to re-use working machinery than using a linked list in terms
+       of code-complexity here in ld, besides the initialization which just
+       looks like other code here.  */
+!   if (!bfd_hash_table_init_n (&lang_definedness_table,
+! 			      lang_definedness_newfunc,
+! 			      sizeof (struct lang_definedness_hash_entry),
+! 			      3))
+      einfo (_("%P%F: can not create hash table: %E\n"));
+  }
+  
+--- 1244,1254 ----
+       simpler to re-use working machinery than using a linked list in terms
+       of code-complexity here in ld, besides the initialization which just
+       looks like other code here.  */
+!   if (!object_only
+!       && !bfd_hash_table_init_n (&lang_definedness_table,
+! 				 lang_definedness_newfunc,
+! 				 sizeof (struct lang_definedness_hash_entry),
+! 				 3))
+      einfo (_("%P%F: can not create hash table: %E\n"));
+  }
+  
+*************** load_symbols (lang_input_statement_type
+*** 2769,2774 ****
+--- 2784,2795 ----
+  		  loaded = FALSE;
+  		}
+  
++ 	      if (link_info.emitting_gnu_object_only)
++ 		{
++ 		  if (!cmdline_on_object_only_archive_list_p (member))
++ 		    continue;
++ 		}
++ 
+  	      subsbfd = member;
+  	      if (!(*link_info.callbacks
+  		    ->add_archive_element) (&link_info, member,
+*************** lang_process (void)
+*** 6659,6665 ****
+--- 6680,6716 ----
+  	  open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
+  	}
+      }
++   else
+  #endif /* ENABLE_PLUGINS */
++     if (link_info.relocatable)
++     {
++       /* Check if .gnu_object_only section should be created.  */
++       bfd *p;
++       int object_type;
++ 
++       object_type = 0;
++       for (p = link_info.input_bfds; p != (bfd *) NULL; p = p->link_next)
++ 	{
++ 	  object_type |= 1 << p->lto_type;
++ 	  if ((object_type & (1 << lto_mixed_object)) != 0
++ 	      || ((object_type
++ 		   & (1 << lto_non_ir_object
++ 		      | 1 << lto_ir_object))
++ 		  == (1 << lto_non_ir_object | 1 << lto_ir_object)))
++ 	    {
++ 	      link_info.emit_gnu_object_only = TRUE;
++ 	      break;
++ 	    }
++ 	}
++ 
++       if (trace_files
++ 	  && (cmdline_object_only_file_list.head
++ 	      || cmdline_object_only_archive_list.head))
++ 	{
++ 	  print_cmdline_list (cmdline_object_only_file_list.head);
++ 	  print_cmdline_list (cmdline_object_only_archive_list.head);
++ 	}
++     }
+  
+    link_info.gc_sym_list = &entry_symbol;
+    if (entry_symbol.name == NULL)
+*************** lang_ld_feature (char *str)
+*** 8059,8061 ****
+--- 8111,9071 ----
+        p = q;
+      }
+  }
++ 
++ static void
++ cmdline_lists_init (void)
++ {
++   cmdline_object_only_file_list.tail
++     = &cmdline_object_only_file_list.head;
++   cmdline_object_only_archive_list.tail
++     = &cmdline_object_only_archive_list.head;
++   cmdline_temp_object_only_list.tail
++     = &cmdline_temp_object_only_list.head;
++ }
++ 
++ /* Allocate an item with TYPE and DATA.  */
++ 
++ static cmdline_union_type *
++ cmdline_list_new (cmdline_enum_type type, void *data)
++ {
++   cmdline_union_type *new_opt;
++ 
++   new_opt = (cmdline_union_type *) stat_alloc (sizeof (*new_opt));
++   new_opt->header.type = type;
++   switch (type)
++     {
++     default:
++       break;
++     case cmdline_is_file_enum:
++       new_opt->file.filename = (const char *) data;
++       break;
++     case cmdline_is_bfd_enum:
++       new_opt->abfd.abfd = (bfd *) data;
++       break;
++     }
++   return new_opt;
++ }
++ 
++ /* Append an item with TYPE and DATA to LIST.  */
++ 
++ static void
++ cmdline_list_append (cmdline_list_type *list, cmdline_enum_type type,
++ 		     void *data)
++ {
++   cmdline_union_type *new_opt = cmdline_list_new (type, data);
++   new_opt->header.next = NULL;
++   *list->tail = new_opt;
++   list->tail = &new_opt->header.next;
++ }
++ 
++ static void
++ print_cmdline_list (cmdline_union_type *c)
++ {
++   for (; c != NULL; c = c->header.next)
++     switch (c->header.type)
++       {
++       default:
++ 	abort ();
++       case cmdline_is_file_enum:
++ 	info_msg (" %s", c->file.filename);
++ 	break;
++       case cmdline_is_bfd_enum:
++ 	info_msg (" [%B]", c->abfd.abfd);
++ 	break;
++       }
++ 
++   info_msg ("\n");
++ }
++ 
++ /* Return TRUE if ABFD is on cmdline_object_only_archive_list.  */
++ 
++ static bfd_boolean
++ cmdline_on_object_only_archive_list_p (bfd *abfd)
++ {
++   cmdline_union_type *c, *next;
++   bfd *archive, *obfd, *oarchive;
++   ufile_ptr origin = abfd->origin;
++ 
++   archive = bfd_my_archive (abfd);
++   for (c = cmdline_object_only_archive_list.head; c != NULL; c = next)
++     {
++       if (c->header.type != cmdline_is_bfd_enum)
++ 	abort ();
++ 
++       next = c->header.next;
++       obfd = c->abfd.abfd;
++       oarchive = bfd_my_archive (obfd);
++ 
++       /* The list is grouped by archive file name and sorted by member
++ 	 origin.  */
++       if (strcmp (archive->filename, oarchive->filename) != 0)
++ 	continue;
++ 
++       if (origin == obfd->origin)
++ 	return TRUE;
++       else if (origin < obfd->origin)
++ 	return FALSE;
++     }
++ 
++   return FALSE;
++ }
++ 
++ /* Append an item with TYPE and DATA to cmdline_object_only_file_list
++    or cmdline_object_only_archive_list if needed.  */
++ 
++ static void
++ cmdline_object_only_list_append (cmdline_enum_type type, void *data)
++ {
++   cmdline_union_type *c;
++   cmdline_union_type *new_opt, *next, **prev;
++   bfd *abfd, *archive;
++   bfd *obfd, *oarchive;
++   bfd *nbfd, *narchive;
++   ufile_ptr origin, norigin;
++ 
++   /* Put it on cmdline_object_only_file_list if it isn't an archive
++      member.  */
++   switch (type)
++     {
++     default:
++       abort ();
++     case cmdline_is_bfd_enum:
++       abfd = (bfd *) data;
++       archive = bfd_my_archive (abfd);
++       if (archive)
++ 	break;
++     case cmdline_is_file_enum:
++       cmdline_list_append (&cmdline_object_only_file_list, type, data);
++       return;
++     }
++ 
++   /* Put archive member on cmdline_object_only_archive_list and sort
++      the list by archive name and archive member origin.  */
++   new_opt = (cmdline_union_type *) stat_alloc (sizeof (*new_opt));
++   new_opt->header.type = cmdline_is_bfd_enum;
++   new_opt->header.next = NULL;
++   new_opt->abfd.abfd = (bfd *) data;
++ 
++   c = cmdline_object_only_archive_list.head;
++   if (c == NULL)
++     {
++       cmdline_object_only_archive_list.head = new_opt;
++       cmdline_object_only_archive_list.tail = &new_opt->header.next;
++       return;
++     }
++ 
++   prev = NULL;
++   origin = abfd->origin;
++   for (; c != NULL; c = next)
++     {
++       if (c->header.type != cmdline_is_bfd_enum)
++ 	abort ();
++ 
++       next = c->header.next;
++ 
++       obfd = c->abfd.abfd;
++       oarchive = bfd_my_archive (obfd);
++ 
++       if (strcmp (archive->filename, oarchive->filename) == 0)
++ 	{
++ 	  bfd_boolean after;
++ 
++ 	  if (origin < obfd->origin)
++ 	    {
++ 	      /* Insert it before the current.  */
++ 	      new_opt->header.next = c;
++ 	      if (prev)
++ 		*prev = new_opt;
++ 	      else
++ 		cmdline_object_only_archive_list.head = new_opt;
++ 	      return;
++ 	    }
++ 
++ 	  after = TRUE;
++ 
++ 	  /* Check origin.  */
++ 	  while (next)
++ 	    {
++ 	      if (next->header.type != cmdline_is_bfd_enum)
++ 		abort ();
++ 
++ 	      nbfd = next->abfd.abfd;
++ 	      norigin = nbfd->origin;
++ 	      if (origin > norigin)
++ 		{
++ 		  /* Insert it after NEXT.  */
++ 		  break;
++ 		}
++ 
++ 	      narchive = bfd_my_archive (nbfd);
++ 	      if (strcmp (archive->filename, narchive->filename) != 0)
++ 		{
++ 		  /* Insert it befor NEXT.  */
++ 		  after = FALSE;
++ 		  break;
++ 		}
++ 
++ 	      c = next;
++ 	      next = next->header.next;
++ 	    }
++ 
++ 	  if (after && next)
++ 	    {
++ 	      c = next;
++ 	      next = next->header.next;
++ 	    }
++ 
++ 	  if (*cmdline_object_only_archive_list.tail == c->header.next)
++ 	    cmdline_object_only_archive_list.tail
++ 	      = &new_opt->header.next;
++ 
++ 	  prev = &c->header.next;
++ 	  new_opt->header.next = next;
++ 	  *prev = new_opt;
++ 	  return;
++ 	}
++ 
++       prev = &c->header.next;
++     }
++ 
++   *cmdline_object_only_archive_list.tail = new_opt;
++   cmdline_object_only_archive_list.tail = &new_opt->header.next;
++ }
++ 
++ 
++ static void
++ cmdline_get_object_only_input_files (void)
++ {
++   cmdline_union_type *c, *next;
++   bfd *abfd, *archive;
++   bfd *nbfd, *narchive;
++ 
++   /* Add files first.  */
++   for (c = cmdline_object_only_file_list.head;
++        c != NULL; c = c->header.next)
++     switch (c->header.type)
++       {
++       default:
++ 	abort ();
++       case cmdline_is_file_enum:
++ 	lang_add_input_file (c->file.filename,
++ 			     lang_input_file_is_file_enum, NULL);
++ 	break;
++       case cmdline_is_bfd_enum:
++ 	abfd = c->abfd.abfd;
++ 	if (bfd_my_archive (abfd))
++ 	  abort ();
++ 	lang_add_input_file (abfd->filename,
++ 			     lang_input_file_is_file_enum, NULL);
++ 	break;
++       }
++ 
++   /* Add archive members next.  */
++   for (c = cmdline_object_only_archive_list.head; c != NULL; c = next)
++     {
++       if (c->header.type != cmdline_is_bfd_enum)
++ 	abort ();
++ 
++       next = c->header.next;
++ 
++       abfd = c->abfd.abfd;
++       archive = bfd_my_archive (abfd);
++    
++       /* Add the first archive of the archive member group.  */
++       lang_add_input_file (archive->filename,
++ 			   lang_input_file_is_file_enum, NULL);
++ 
++       /* Skip the rest members in the archive member group.  */
++       do
++ 	{
++ 	  if (!next)
++ 	    break;
++ 
++ 	  if (next->header.type != cmdline_is_bfd_enum)
++ 	    abort ();
++ 
++ 	  next = next->header.next;
++ 	  if (!next)
++ 	    break;
++ 	  nbfd = next->abfd.abfd;
++ 	  narchive = bfd_my_archive (nbfd);
++ 	}
++       while (strcmp (archive->filename, narchive->filename) == 0);
++     }
++ }
++ 
++ struct cmdline_arg
++ {
++   bfd *obfd;
++   asymbol **isympp;
++   int status;
++ };
++ 
++ /* Create a section in OBFD with the same
++    name and attributes as ISECTION in IBFD.  */
++ 
++ static void
++ setup_section (bfd *ibfd, sec_ptr isection, void *p)
++ {
++   struct cmdline_arg *arg = (struct cmdline_arg *) p;
++   bfd *obfd = arg->obfd;
++   asymbol **isympp = arg->isympp;
++   const char *name = isection->name;
++   sec_ptr osection;
++   const char *err;
++ 
++   /* Skip the object-only section.  */
++   if (ibfd->object_only_section == isection)
++     return;
++ 
++   /* If we have already failed earlier on, do not keep on generating
++      complaints now.  */
++   if (arg->status)
++     return;
++ 
++   osection = bfd_make_section_anyway_with_flags (obfd, name,
++ 						 isection->flags);
++ 
++   if (osection == NULL)
++     {
++       err = _("failed to create output section");
++       goto loser;
++     }
++ 
++   osection->size = isection->size;
++   osection->vma = isection->vma;
++   osection->lma = isection->lma;
++   osection->alignment_power = isection->alignment_power;
++ 
++   /* Copy merge entity size.  */
++   osection->entsize = isection->entsize;
++ 
++   /* This used to be mangle_section; we do here to avoid using
++      bfd_get_section_by_name since some formats allow multiple
++      sections with the same name.  */
++   isection->output_section = osection;
++   isection->output_offset = 0;
++ 
++   if ((isection->flags & SEC_GROUP) != 0)
++     {
++       asymbol *gsym = bfd_group_signature (isection, isympp);
++ 
++       if (gsym != NULL)
++ 	{
++ 	  gsym->flags |= BSF_KEEP;
++ 	  if (ibfd->xvec->flavour == bfd_target_elf_flavour)
++ 	    elf_group_id (isection) = gsym;
++ 	}
++     }
++ 
++   /* Allow the BFD backend to copy any private data it understands
++      from the input section to the output section.  */
++   if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
++     {
++       err = _("failed to copy private data");
++       goto loser;
++     }
++ 
++   /* All went well.  */
++   return;
++ 
++ loser:
++   arg->status = 1;
++   einfo (_("%P%F: setup_section: %s: %s\n"), err, name);
++ }
++ 
++ /* Copy the data of input section ISECTION of IBFD
++    to an output section with the same name in OBFD.
++    If stripping then don't copy any relocation info.  */
++ 
++ static void
++ copy_section (bfd *ibfd, sec_ptr isection, void *p)
++ {
++   struct cmdline_arg *arg = (struct cmdline_arg *) p;
++   bfd *obfd = arg->obfd;
++   asymbol **isympp = arg->isympp;
++   arelent **relpp;
++   long relcount;
++   sec_ptr osection;
++   bfd_size_type size;
++   long relsize;
++   flagword flags;
++   const char *err;
++ 
++   /* Skip the object-only section.  */
++   if (ibfd->object_only_section == isection)
++     return;
++ 
++   /* If we have already failed earlier on, do not keep on generating
++      complaints now.  */
++   if (arg->status)
++     return;
++ 
++   flags = bfd_get_section_flags (ibfd, isection);
++   if ((flags & SEC_GROUP) != 0)
++     return;
++ 
++   osection = isection->output_section;
++   size = bfd_get_section_size (isection);
++ 
++   if (size == 0 || osection == 0)
++     return;
++ 
++   relsize = bfd_get_reloc_upper_bound (ibfd, isection);
++ 
++   if (relsize < 0)
++     {
++       /* Do not complain if the target does not support relocations.  */
++       if (relsize == -1
++ 	  && bfd_get_error () == bfd_error_invalid_operation)
++ 	relsize = 0;
++       else
++ 	{
++ 	  err = bfd_errmsg (bfd_get_error ());
++ 	  goto loser;
++ 	}
++     }
++ 
++   if (relsize == 0)
++     bfd_set_reloc (obfd, osection, NULL, 0);
++   else
++     {
++       relpp = (arelent **) xmalloc (relsize);
++       relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
++       if (relcount < 0)
++ 	{
++ 	  err = _("relocation count is negative");
++ 	  goto loser;
++ 	}
++ 
++       bfd_set_reloc (obfd, osection,
++ 		     relcount == 0 ? NULL : relpp, relcount);
++       if (relcount == 0)
++ 	free (relpp);
++     }
++ 
++   if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
++     {
++       bfd_byte *memhunk = NULL;
++ 
++       if (!bfd_get_full_section_contents (ibfd, isection, &memhunk))
++ 	{
++ 	  err = bfd_errmsg (bfd_get_error ());
++ 	  goto loser;
++ 	}
++ 
++       if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
++ 	{
++ 	  err = bfd_errmsg (bfd_get_error ());
++ 	  goto loser;
++ 	}
++       free (memhunk);
++     }
++ 
++   /* All went well.  */
++   return;
++ 
++ loser:
++   einfo (_("%P%F: copy_section: %s: %s\n"), err, isection->name);
++ }
++ /* Open the temporary bfd created in the same directory as PATH.  */
++ 
++ static bfd *
++ cmdline_fopen_temp (const char *path, const char *target,
++ 		    const char *mode)
++ {
++ #define template "ldXXXXXX"
++   const char *slash = strrchr (path, '/');
++   char *tmpname;
++   size_t len;
++   int fd;
++ 
++ #ifdef HAVE_DOS_BASED_FILE_SYSTEM
++   {
++     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
++     char *bslash = strrchr (path, '\\');
++ 
++     if (slash == NULL || (bslash != NULL && bslash > slash))
++       slash = bslash;
++     if (slash == NULL && path[0] != '\0' && path[1] == ':')
++       slash = path + 1;
++   }
++ #endif
++ 
++   if (slash != (char *) NULL)
++     {
++       len = slash - path;
++       tmpname = (char *) xmalloc (len + sizeof (template) + 2);
++       memcpy (tmpname, path, len);
++ 
++ #ifdef HAVE_DOS_BASED_FILE_SYSTEM
++       /* If tmpname is "X:", appending a slash will make it a root
++ 	 directory on drive X, which is NOT the same as the current
++ 	 directory on drive X.  */
++       if (len == 2 && tmpname[1] == ':')
++ 	tmpname[len++] = '.';
++ #endif
++       tmpname[len++] = '/';
++     }
++   else
++     {
++       tmpname = (char *) xmalloc (sizeof (template));
++       len = 0;
++     }
++ 
++   memcpy (tmpname + len, template, sizeof (template));
++ #undef template
++ 
++ #ifdef HAVE_MKSTEMP
++   fd = mkstemp (tmpname);
++ #else
++   tmpname = mktemp (tmpname);
++   if (tmpname == NULL)
++     return NULL;
++   fd = open (tmpname, O_RDWR | O_CREAT | O_EXCL, 0600);
++ #endif
++   if (fd == -1)
++     return NULL;
++   return bfd_fopen (tmpname, target, mode, fd);
++ }
++ 
++ /* Add the object-only section.  */
++ 
++ static void
++ cmdline_add_object_only_section (bfd_byte *contents, size_t size)
++ {
++   bfd_vma start;
++   flagword flags;
++   enum bfd_architecture iarch;
++   unsigned int imach;
++   long symcount;
++   long symsize;
++   asymbol **isympp = NULL;
++   asymbol **osympp = NULL;
++   bfd *obfd = NULL, *ibfd;
++   const char *err;
++   struct arg
++     {
++       bfd *obfd;
++       asymbol **isympp;
++       int status;
++     } arg;
++   char **matching;
++   const char *ofilename = NULL;
++   asection *sec;
++ 
++   ibfd = bfd_openr (output_filename, output_target);
++   if (!ibfd)
++     {
++       err = bfd_errmsg (bfd_get_error ());
++       goto loser;
++     }
++ 
++   if (!bfd_check_format_matches (ibfd, bfd_object, &matching))
++     {
++       err = bfd_errmsg (bfd_get_error ());
++       goto loser;
++     }
++ 
++   obfd = cmdline_fopen_temp (output_filename, output_target, "w");
++   if (!obfd)
++     {
++       err = bfd_errmsg (bfd_get_error ());
++       goto loser;
++     }
++   ofilename = bfd_get_filename (obfd);
++ 
++   if (!bfd_set_format (obfd, bfd_object))
++     {
++       err = bfd_errmsg (bfd_get_error ());
++       goto loser;
++     }
++ 
++   /* Copy the start address, flags and architecture of input file to
++      output file.  */
++   flags = bfd_get_file_flags (ibfd);
++   start = bfd_get_start_address (ibfd);
++   iarch = bfd_get_arch (ibfd);
++   imach = bfd_get_mach (ibfd);
++   if (!bfd_set_start_address (obfd, start)
++       || !bfd_set_file_flags (obfd, flags)
++       || !bfd_set_arch_mach (obfd, iarch, imach))
++     {
++       err = bfd_errmsg (bfd_get_error ());
++       goto loser;
++     }
++ 	
++   symsize = bfd_get_symtab_upper_bound (ibfd);
++   if (symsize < 0)
++     {
++       err = bfd_errmsg (bfd_get_error ());
++       goto loser;
++     }
++ 
++   isympp = (asymbol **) xmalloc (symsize);
++   symcount = bfd_canonicalize_symtab (ibfd, isympp);
++   if (symcount < 0)
++     {
++       err = bfd_errmsg (bfd_get_error ());
++       goto loser;
++     }
++ 
++   arg.obfd = obfd;
++   arg.isympp = isympp;
++   arg.status = 0;
++ 
++   /* BFD mandates that all output sections be created and sizes set before
++      any output is done.  Thus, we traverse all sections multiple times.  */
++   bfd_map_over_sections (ibfd, setup_section, &arg);
++ 
++   if (arg.status)
++     {
++       err = _("error setting up sections");
++       goto loser;
++     }
++ 
++   /* Allow the BFD backend to copy any private data it understands
++      from the input section to the output section.  */
++   if (! bfd_copy_private_header_data (ibfd, obfd))
++     {
++       err = _("error copying private header data");
++       goto loser;
++     }
++ 
++   /* Create the object-only section.  */
++   sec = bfd_make_section_with_flags (obfd,
++ 				     GNU_OBJECT_ONLY_SECTION_NAME,
++ 				     (SEC_HAS_CONTENTS
++ 				      | SEC_READONLY
++ 				      | SEC_DATA
++ 				      | SEC_LINKER_CREATED));
++   if (sec == NULL)
++     {
++       err = _("can't create object-only section");
++       goto loser;
++     }
++ 
++   if (! bfd_set_section_size (obfd, sec, size))
++     {
++       err = _("can't set object-only section size");
++       goto loser;
++     }
++ 
++   if (ibfd->object_only_section)
++     {
++       /* Filter out the object-only section symbol.  */
++       long src_count = 0, dst_count = 0;
++       asymbol **from, **to;
++ 
++       osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
++       from = isympp;
++       to = osympp;
++       for (; src_count < symcount; src_count++)
++ 	{
++ 	  asymbol *sym = from[src_count];
++ 	  if (bfd_get_section (sym) != ibfd->object_only_section)
++ 	    to[dst_count++] = sym;
++ 	}
++       to[dst_count] = NULL;
++       symcount = dst_count;
++       bfd_set_symtab (obfd, osympp, symcount);
++     }
++   else
++     bfd_set_symtab (obfd, isympp, symcount);
++ 
++   /* This has to happen after the symbol table has been set.  */
++   bfd_map_over_sections (ibfd, copy_section, &arg);
++ 
++   if (arg.status)
++     {
++       err = _("error copying sections");
++       goto loser;
++     }
++ 
++   /* Copy the object-only section to the output.  */
++   if (! bfd_set_section_contents (obfd, sec, contents, 0, size))
++     {
++       err = _("error adding object-only section");
++       goto loser;
++     }
++ 
++   /* Allow the BFD backend to copy any private data it understands
++      from the input BFD to the output BFD.  This is done last to
++      permit the routine to look at the filtered symbol table, which is
++      important for the ECOFF code at least.  */
++   if (! bfd_copy_private_bfd_data (ibfd, obfd))
++     {
++       err = _("error copying private BFD data");
++       goto loser;
++     }
++ 
++   if (!bfd_close (obfd))
++     {
++       unlink (ofilename);
++       einfo (_("%P%F: failed to finish output with object-only section\n"));
++     }
++ 
++   /* Must be freed after bfd_close ().  */
++   free (isympp);
++   if (osympp)
++     free (osympp);
++ 
++   if (rename (ofilename, output_filename))
++     {
++       unlink (ofilename);
++       einfo (_("%P%F: failed to rename output with object-only section\n"));
++     }
++ 
++   return;
++ 
++ loser:
++   if (isympp)
++     free (isympp);
++   if (osympp)
++     free (osympp);
++   if (obfd)
++     bfd_close (obfd);
++   if (ofilename)
++     unlink (ofilename);
++   einfo (_("%P%F: failed to add object-only section: %s\n"), err);
++ }
++ 
++ /* Emit the final output with object-only section.  */
++ 
++ void
++ cmdline_emit_object_only_section (void)
++ {
++   const char *saved_output_filename = output_filename;
++   int fd;
++   size_t size, off;
++   bfd_byte *contents;
++   struct stat st;
++ 
++   /* Get a temporary object-only file.  */
++   output_filename = make_temp_file (".obj-only.o");
++ 
++   had_output_filename = FALSE;
++   link_info.input_bfds = NULL;
++   link_info.input_bfds_tail = &link_info.input_bfds;
++ 
++   lang_init (TRUE);
++ 
++   ld_parse_linker_script ();
++ 
++   /* Set up the object-only output. */
++   lang_final ();
++ 
++   /* Open the object-only file for output.  */
++   lang_for_each_statement (ldlang_open_output);
++ 
++   ldemul_create_output_section_statements ();
++ 
++   if (!bfd_section_already_linked_table_init ())
++     einfo (_("%P%F: Failed to create hash table\n"));
++ 
++   /* Call cmdline_on_object_only_archive_list_p to check which member
++      should be loaded.  */
++   input_flags.whole_archive = TRUE;
++ 
++   /* Set it to avoid adding more to cmdline lists.  */
++   link_info.emitting_gnu_object_only = TRUE;
++ 
++   cmdline_get_object_only_input_files ();
++ 
++   open_input_bfds (statement_list.head, FALSE);
++ 
++   ldemul_after_open ();
++ 
++   bfd_section_already_linked_table_free ();
++ 
++   /* Make sure that we're not mixing architectures.  We call this
++      after all the input files have been opened, but before we do any
++      other processing, so that any operations merge_private_bfd_data
++      does on the output file will be known during the rest of the
++      link.  */
++   lang_check ();
++ 
++   /* Size up the common data.  */
++   lang_common ();
++ 
++   /* Update wild statements.  */
++   update_wild_statements (statement_list.head);
++ 
++   /* Run through the contours of the script and attach input sections
++      to the correct output sections.  */
++   map_input_to_output_sections (statement_list.head, NULL, NULL);
++ 
++   /* Find any sections not attached explicitly and handle them.  */
++   lang_place_orphans ();
++ 
++   /* Do anything special before sizing sections.  This is where ELF
++      and other back-ends size dynamic sections.  */
++   ldemul_before_allocation ();
++ 
++   /* Size up the sections.  */
++   lang_size_sections (NULL, ! RELAXATION_ENABLED);
++ 
++   /* See if anything special should be done now we know how big
++      everything is.  This is where relaxation is done.  */
++   ldemul_after_allocation ();
++ 
++   ldemul_finish ();
++ 
++   /* Make sure that the section addresses make sense.  */
++   if (command_line.check_section_addresses)
++     lang_check_section_addresses ();
++ 
++   lang_end ();
++   
++   ldwrite ();
++ 
++   lang_finish ();
++ 
++   if (! bfd_close (link_info.output_bfd))
++     einfo (_("%P%F:%s: final close failed on object-only output: %E\n"),
++ 	   output_filename);
++ 
++   /* Read in the object-only file.  */
++   fd = open (output_filename, O_RDONLY | O_BINARY);
++   if (fd < 0)
++     {
++       bfd_set_error (bfd_error_system_call);
++       einfo (_("%P%F:%s: cannot open object-only output: %E"),
++ 	     output_filename);
++     }
++ 
++   /* Get the object-only file size.  */
++   if (fstat (fd, &st) != 0)
++     {
++       bfd_set_error (bfd_error_system_call);
++       einfo (_("%P%F:%s: cannot stat object-only output: %E"),
++ 	     output_filename);
++     }
++ 
++   size = st.st_size;
++   off = 0;
++   contents = (bfd_byte *) xmalloc (size);
++   while (off != size)
++     {
++       ssize_t got;
++ 
++       got = read (fd, contents + off, size - off);
++       if (got < 0)
++ 	{
++ 	  bfd_set_error (bfd_error_system_call);
++ 	  einfo (_("%P%F:%s: read failed on object-only output: %E"),
++ 		 output_filename);
++ 	}
++ 
++       off += got;
++     }
++ 
++   close (fd);
++ 
++   /* Remove the temporary object-only file.  */ 
++   unlink (output_filename);
++ 
++   output_filename = saved_output_filename;
++ 
++   cmdline_add_object_only_section (contents, size);
++ 
++   free (contents);
++ }
++ 
++ /* Extract the object-only section.  */
++ 
++ static const char *
++ cmdline_extract_object_only_section (bfd *abfd)
++ {
++   const char *name = bfd_extract_object_only_section (abfd);
++ 
++   if (name == NULL)
++     einfo (_("%P%F: cannot extract object-only section from %B: %E"),
++ 	   abfd);
++ 
++   /* It should be removed after it is done.  */
++   cmdline_list_append (&cmdline_temp_object_only_list,
++ 		       cmdline_is_file_enum, (void *) name);
++ 
++   return name;
++ }
++ 
++ /* Check and handle the object-only section.   */
++ 
++ void
++ cmdline_check_object_only_section (bfd *abfd, bfd_boolean lto)
++ {
++   const char *filename;
++ 
++   if (link_info.emitting_gnu_object_only
++       || abfd->format != bfd_object)
++     return;
++ 
++   if (lto)
++     {
++       /* For LTO link, we only need to extract object-only section
++ 	 from the mixed object, add it to input, and put it on LTO
++ 	 claimed output.  */
++       switch (abfd->lto_type)
++ 	{
++ 	default:
++ 	  abort ();
++ 	case lto_mixed_object:
++ 	  filename = cmdline_extract_object_only_section (abfd);
++ 	  lang_add_input_file (filename,
++ 			       lang_input_file_is_file_enum, NULL);
++ 	  break;
++ 	case lto_non_ir_object:
++ 	case lto_ir_object:
++ 	  break;
++ 	}
++     }
++   else if (link_info.relocatable)
++     {
++       /* For non-LTO relocatable link, we need to append non-IR object
++ 	 file and the object file in object-only section to the object
++ 	 only list.  */
++       switch (abfd->lto_type)
++ 	{
++ 	default:
++ 	  abort ();
++ 	case lto_mixed_object:
++ 	  filename = cmdline_extract_object_only_section (abfd);
++ 	  cmdline_object_only_list_append (cmdline_is_file_enum,
++ 					  (void *) filename);
++ 	  break;
++ 	case lto_non_ir_object:
++ 	  cmdline_object_only_list_append (cmdline_is_bfd_enum, abfd);
++ 	  break;
++ 	case lto_ir_object:
++ 	  break;
++ 	}
++     }
++ }
++ 
++ /* Remove temporary object-only files.  */
++ 
++ void
++ cmdline_remove_object_only_files (void)
++ {
++   cmdline_union_type *c;
++ 
++ #ifdef ENABLE_PLUGINS
++   if (plugin_save_temps)
++     return;
++ #endif
++ 
++   c = cmdline_temp_object_only_list.head;
++   for (; c != NULL; c = c->header.next)
++     switch (c->header.type)
++       {
++       default:
++ 	abort ();
++       case cmdline_is_file_enum:
++ 	unlink (c->file.filename);
++ 	break;
++       }
++ }
++
++
++ 
+diff -cpr ../binutils-2.23.2.orig/ld/ldlang.h ld/ldlang.h
+*** ../binutils-2.23.2.orig/ld/ldlang.h	2013-05-14 16:39:36.861718097 +0100
+--- ld/ldlang.h	2013-05-14 16:40:07.053718934 +0100
+*************** extern lang_statement_list_type input_fi
+*** 488,494 ****
+  extern int lang_statement_iteration;
+  
+  extern void lang_init
+!   (void);
+  extern void lang_finish
+    (void);
+  extern lang_memory_region_type * lang_memory_region_lookup
+--- 488,494 ----
+  extern int lang_statement_iteration;
+  
+  extern void lang_init
+!   (bfd_boolean);
+  extern void lang_finish
+    (void);
+  extern lang_memory_region_type * lang_memory_region_lookup
+*************** ldlang_override_segment_assignment
+*** 664,667 ****
+--- 664,708 ----
+  extern void
+  lang_ld_feature (char *);
+  
++ typedef enum
++ {
++   cmdline_is_file_enum,
++   cmdline_is_bfd_enum
++ } cmdline_enum_type;
++ 
++ typedef struct cmdline_header_struct
++ {
++   union cmdline_union *next;
++   cmdline_enum_type type;
++ } cmdline_header_type;
++ 
++ typedef struct cmdline_file_struct
++ {
++   cmdline_header_type header;
++   const char *filename;
++ } cmdline_file_type;
++ 
++ typedef struct cmdline_bfd_struct
++ {
++   cmdline_header_type header;
++   bfd *abfd;
++ } cmdline_bfd_type;
++ 
++ typedef union cmdline_union
++ {
++   cmdline_header_type header;
++   cmdline_file_type file;
++   cmdline_bfd_type abfd;
++ } cmdline_union_type;
++ 
++ typedef struct cmdline_list
++ {
++   cmdline_union_type *head;
++   cmdline_union_type **tail;
++ } cmdline_list_type;
++ 
++ extern void cmdline_emit_object_only_section (void);
++ extern void cmdline_check_object_only_section (bfd *, bfd_boolean);
++ extern void cmdline_remove_object_only_files (void);
++ 
+  #endif
+diff -cpr ../binutils-2.23.2.orig/ld/ldlex.h ld/ldlex.h
+*** ../binutils-2.23.2.orig/ld/ldlex.h	2013-05-14 16:39:39.789718178 +0100
+--- ld/ldlex.h	2013-05-14 16:47:18.651730898 +0100
+*************** enum option_values
+*** 133,138 ****
+--- 133,139 ----
+  #ifdef ENABLE_PLUGINS
+    OPTION_PLUGIN,
+    OPTION_PLUGIN_OPT,
++   OPTION_PLUGIN_SAVE_TEMPS,
+  #endif /* ENABLE_PLUGINS */
+    OPTION_DEFAULT_SCRIPT,
+    OPTION_PRINT_OUTPUT_FORMAT,
+diff -cpr ../binutils-2.23.2.orig/ld/ldmain.c ld/ldmain.c
+*** ../binutils-2.23.2.orig/ld/ldmain.c	2013-05-14 16:39:36.862718097 +0100
+--- ld/ldmain.c	2013-05-14 16:40:07.055718934 +0100
+*************** main (int argc, char **argv)
+*** 219,224 ****
+--- 219,227 ----
+  
+    xatexit (ld_cleanup);
+  
++   /* Remove temporary object-only files.  */
++   xatexit (cmdline_remove_object_only_files);
++ 
+    /* Set up the sysroot directory.  */
+    ld_sysroot = get_sysroot (argc, argv);
+    if (*ld_sysroot)
+*************** main (int argc, char **argv)
+*** 295,301 ****
+    default_target = ldemul_choose_target (argc, argv);
+    config.maxpagesize = bfd_emul_get_maxpagesize (default_target);
+    config.commonpagesize = bfd_emul_get_commonpagesize (default_target);
+!   lang_init ();
+    ldemul_before_parse ();
+    lang_has_input_file = FALSE;
+    parse_args (argc, argv);
+--- 298,304 ----
+    default_target = ldemul_choose_target (argc, argv);
+    config.maxpagesize = bfd_emul_get_maxpagesize (default_target);
+    config.commonpagesize = bfd_emul_get_commonpagesize (default_target);
+!   lang_init (FALSE);
+    ldemul_before_parse ();
+    lang_has_input_file = FALSE;
+    parse_args (argc, argv);
+*************** main (int argc, char **argv)
+*** 310,343 ****
+  
+    ldemul_set_symbols ();
+  
+!   /* If we have not already opened and parsed a linker script,
+!      try the default script from command line first.  */
+!   if (saved_script_handle == NULL
+!       && command_line.default_script != NULL)
+!     {
+!       ldfile_open_command_file (command_line.default_script);
+!       parser_input = input_script;
+!       yyparse ();
+!     }
+! 
+!   /* If we have not already opened and parsed a linker script
+!      read the emulation's appropriate default script.  */
+!   if (saved_script_handle == NULL)
+!     {
+!       int isfile;
+!       char *s = ldemul_get_script (&isfile);
+! 
+!       if (isfile)
+! 	ldfile_open_default_command_file (s);
+!       else
+! 	{
+! 	  lex_string = s;
+! 	  lex_redirect (s, _("built in linker script"), 1);
+! 	}
+!       parser_input = input_script;
+!       yyparse ();
+!       lex_string = NULL;
+!     }
+  
+    if (verbose)
+      {
+--- 313,319 ----
+  
+    ldemul_set_symbols ();
+  
+!   ld_parse_linker_script ();
+  
+    if (verbose)
+      {
+*************** main (int argc, char **argv)
+*** 444,449 ****
+--- 420,427 ----
+        if (! bfd_close (link_info.output_bfd))
+  	einfo (_("%F%B: final close failed: %E\n"), link_info.output_bfd);
+  
++       link_info.output_bfd = NULL;
++ 
+        /* If the --force-exe-suffix is enabled, and we're making an
+  	 executable file and it doesn't end in .exe, copy it to one
+  	 which does.  */
+*************** main (int argc, char **argv)
+*** 490,495 ****
+--- 468,476 ----
+  	}
+      }
+  
++   if (link_info.emit_gnu_object_only)
++     cmdline_emit_object_only_section ();
++ 
+    END_PROGRESS (program_name);
+  
+    if (config.stats)
+*************** add_archive_element (struct bfd_link_inf
+*** 779,785 ****
+--- 760,768 ----
+  	    }
+  	}
+      }
++   else
+  #endif /* ENABLE_PLUGINS */
++     cmdline_check_object_only_section (input->the_bfd, FALSE);
+  
+    ldlang_add_file (input);
+  
+*************** warning_callback (struct bfd_link_info *
+*** 1152,1158 ****
+      einfo ("%P: %s%s\n", _("warning: "), warning);
+    else if (symbol == NULL)
+      einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
+!   else
+      {
+        struct warning_callback_info cinfo;
+  
+--- 1135,1141 ----
+      einfo ("%P: %s%s\n", _("warning: "), warning);
+    else if (symbol == NULL)
+      einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
+!   else if ((abfd->flags & BFD_PLUGIN) == 0)
+      {
+        struct warning_callback_info cinfo;
+  
+*************** notice (struct bfd_link_info *info,
+*** 1459,1461 ****
+--- 1442,1479 ----
+  
+    return TRUE;
+  }
++ 
++ /* Parse the linker script.   */
++ 
++ void
++ ld_parse_linker_script ()
++ {
++   /* If we have not already opened and parsed a linker script,
++      try the default script from command line first.  */
++   if (saved_script_handle == NULL
++       && command_line.default_script != NULL)
++     {
++       ldfile_open_command_file (command_line.default_script);
++       parser_input = input_script;
++       yyparse ();
++     }
++ 
++   /* If we have not already opened and parsed a linker script
++      read the emulation's appropriate default script.  */
++   if (saved_script_handle == NULL)
++     {
++       int isfile;
++       char *s = ldemul_get_script (&isfile);
++ 
++       if (isfile)
++ 	ldfile_open_default_command_file (s);
++       else
++ 	{
++ 	  lex_string = s;
++ 	  lex_redirect (s, _("built in linker script"), 1);
++ 	}
++       parser_input = input_script;
++       yyparse ();
++       lex_string = NULL;
++     }
++ }
+diff -cpr ../binutils-2.23.2.orig/ld/ldmain.h ld/ldmain.h
+*** ../binutils-2.23.2.orig/ld/ldmain.h	2013-05-14 16:39:39.810718179 +0100
+--- ld/ldmain.h	2013-05-14 16:40:07.055718934 +0100
+*************** extern void add_ysym (const char *);
+*** 43,46 ****
+--- 43,48 ----
+  extern void add_wrap (const char *);
+  extern void add_keepsyms_file (const char *);
+  
++ extern void ld_parse_linker_script (void);
++ 
+  #endif
+diff -cpr ../binutils-2.23.2.orig/ld/lexsup.c ld/lexsup.c
+*** ../binutils-2.23.2.orig/ld/lexsup.c	2013-05-14 16:39:36.709718093 +0100
+--- ld/lexsup.c	2013-05-14 16:40:07.058718934 +0100
+*************** static const struct ld_option ld_options
+*** 168,173 ****
+--- 168,176 ----
+      '\0', N_("PLUGIN"), N_("Load named plugin"), ONE_DASH },
+    { {"plugin-opt", required_argument, NULL, OPTION_PLUGIN_OPT},
+      '\0', N_("ARG"), N_("Send arg to last-loaded plugin"), ONE_DASH },
++   { {"plugin-save-temps", no_argument, NULL, OPTION_PLUGIN_SAVE_TEMPS},
++     '\0', NULL, N_("Store plugin intermediate files permanently"),
++     ONE_DASH },
+    { {"flto", optional_argument, NULL, OPTION_IGNORE},
+      '\0', NULL, N_("Ignored for GCC LTO option compatibility"),
+      ONE_DASH },
+*************** parse_args (unsigned argc, char **argv)
+*** 958,963 ****
+--- 961,969 ----
+  	  if (plugin_opt_plugin_arg (optarg))
+  	    einfo(_("%P%F: bad -plugin-opt option\n"));
+  	  break;
++ 	case OPTION_PLUGIN_SAVE_TEMPS:
++ 	  plugin_save_temps = TRUE;
++ 	  break;
+  #endif /* ENABLE_PLUGINS */
+  	case 'q':
+  	  link_info.emitrelocations = TRUE;
+diff -cpr ../binutils-2.23.2.orig/ld/plugin.c ld/plugin.c
+*** ../binutils-2.23.2.orig/ld/plugin.c	2013-05-14 16:39:37.435718113 +0100
+--- ld/plugin.c	2013-05-14 16:48:59.039733681 +0100
+***************
+*** 39,44 ****
+--- 39,47 ----
+  /* Report plugin symbols.  */
+  bfd_boolean report_plugin_symbols;
+  
++ /* Store plugin intermediate files permanently.  */
++ bfd_boolean plugin_save_temps;
++ 
+  /* The suffix to append to the name of the real (claimed) object file
+     when generating a dummy BFD to hold the IR symbols sent from the
+     plugin.  For cosmetic use only; appears in maps, crefs etc.  */
+*************** plugin_opt_plugin_arg (const char *arg)
+*** 217,222 ****
+--- 220,236 ----
+    if (!last_plugin)
+      return set_plugin_error (_("<no plugin>"));
+  
++   /* Ignore -pass-through= from GCC driver.  */
++   if (*arg == '-')
++     {
++       const char *p;
++       for (p = arg + 1; p; p++)
++ 	if (*p != '-')
++ 	  break;
++       if (strncmp (p, "pass-through=", 13) == 0)
++ 	return 0;
++     }
++ 
+    newarg = xmalloc (sizeof *newarg);
+    newarg->arg = arg;
+    newarg->next = NULL;
+*************** plugin_maybe_claim (struct ld_plugin_inp
+*** 876,881 ****
+--- 890,898 ----
+    close (file->fd);
+    if (claimed)
+      {
++       /* Check object only section.  */
++       cmdline_check_object_only_section (entry->the_bfd, TRUE);
++ 
+        /* Discard the real file's BFD and substitute the dummy one.  */
+  
+        /* BFD archive handling caches elements so we can't call
+*************** plugin_call_cleanup (void)
+*** 929,942 ****
+      {
+        if (curplug->cleanup_handler && !curplug->cleanup_done)
+  	{
+! 	  enum ld_plugin_status rv;
+! 	  curplug->cleanup_done = TRUE;
+! 	  called_plugin = curplug;
+! 	  rv = (*curplug->cleanup_handler) ();
+! 	  called_plugin = NULL;
+! 	  if (rv != LDPS_OK)
+! 	    info_msg (_("%P: %s: error in plugin cleanup: %d (ignored)\n"),
+! 		      curplug->name, rv);
+  	  dlclose (curplug->dlhandle);
+  	}
+        curplug = curplug->next;
+--- 946,962 ----
+      {
+        if (curplug->cleanup_handler && !curplug->cleanup_done)
+  	{
+! 	  if (!plugin_save_temps)
+! 	    {
+! 	      enum ld_plugin_status rv;
+! 	      curplug->cleanup_done = TRUE;
+! 	      called_plugin = curplug;
+! 	      rv = (*curplug->cleanup_handler) ();
+! 	      called_plugin = NULL;
+! 	      if (rv != LDPS_OK)
+! 		info_msg (_("%P: %s: error in plugin cleanup: %d (ignored)\n"),
+! 			  curplug->name, rv);
+! 	    }
+  	  dlclose (curplug->dlhandle);
+  	}
+        curplug = curplug->next;
+diff -cpr ../binutils-2.23.2.orig/ld/plugin.h ld/plugin.h
+*** ../binutils-2.23.2.orig/ld/plugin.h	2013-05-14 16:39:39.705718176 +0100
+--- ld/plugin.h	2013-05-14 16:40:07.059718934 +0100
+***************
+*** 24,29 ****
+--- 24,32 ----
+  /* Report plugin symbols.  */
+  extern bfd_boolean report_plugin_symbols;
+  
++ /* Store plugin intermediate files permanently.  */
++ extern bfd_boolean plugin_save_temps;
++ 
+  /* Set at all symbols read time, to avoid recursively offering the plugin
+     its own newly-added input files and libs to claim.  */
+  extern bfd_boolean no_more_claiming;
+diff -cpr ../binutils-2.23.2.orig/ld/scripttempl/armbpabi.sc ld/scripttempl/armbpabi.sc
+*** ../binutils-2.23.2.orig/ld/scripttempl/armbpabi.sc	2013-05-14 16:39:39.758718177 +0100
+--- ld/scripttempl/armbpabi.sc	2013-05-14 16:54:15.657742458 +0100
+*************** INTERP=".interp       0 : { *(.interp) }
+*** 30,36 ****
+  PLT=".plt          ${RELOCATING-0} : { *(.plt) }"
+  RODATA=".rodata       ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
+  DATARELRO=".data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro .data.rel.ro.*) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink)  *(.gnu.lto_*) }"
+  if test -z "${NO_SMALL_DATA}"; then
+    SBSS=".sbss         ${RELOCATING-0} :
+    {
+--- 30,36 ----
+  PLT=".plt          ${RELOCATING-0} : { *(.plt) }"
+  RODATA=".rodata       ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
+  DATARELRO=".data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro .data.rel.ro.*) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
+  if test -z "${NO_SMALL_DATA}"; then
+    SBSS=".sbss         ${RELOCATING-0} :
+    {
+diff -cpr ../binutils-2.23.2.orig/ld/scripttempl/elf32sh-symbian.sc ld/scripttempl/elf32sh-symbian.sc
+*** ../binutils-2.23.2.orig/ld/scripttempl/elf32sh-symbian.sc	2013-05-14 16:39:39.759718177 +0100
+--- ld/scripttempl/elf32sh-symbian.sc	2013-05-14 16:40:07.062718934 +0100
+*************** fi
+*** 83,89 ****
+      PLT=".plt            : { *(.plt) } :dynamic :dyn"
+  DYNAMIC=".dynamic        : { *(.dynamic) } :dynamic :dyn"
+   RODATA=".rodata    ALIGN(4) : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.directive)  *(.gnu.lto_*) }"
+  test -z "$GOT" && GOT=".got          ${RELOCATING-0} : { *(.got.plt) *(.got) } :dynamic :dyn"
+  INIT_ARRAY=".init_array   ${RELOCATING-0} :
+    {
+--- 83,89 ----
+      PLT=".plt            : { *(.plt) } :dynamic :dyn"
+  DYNAMIC=".dynamic        : { *(.dynamic) } :dynamic :dyn"
+   RODATA=".rodata    ALIGN(4) : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.directive)  *(.gnu.lto_*) *(.gnu_object_only) }"
+  test -z "$GOT" && GOT=".got          ${RELOCATING-0} : { *(.got.plt) *(.got) } :dynamic :dyn"
+  INIT_ARRAY=".init_array   ${RELOCATING-0} :
+    {
+diff -cpr ../binutils-2.23.2.orig/ld/scripttempl/elf64hppa.sc ld/scripttempl/elf64hppa.sc
+*** ../binutils-2.23.2.orig/ld/scripttempl/elf64hppa.sc	2013-05-14 16:39:39.733718177 +0100
+--- ld/scripttempl/elf64hppa.sc	2013-05-14 16:55:16.076744133 +0100
+*************** fi
+*** 127,133 ****
+  DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
+  RODATA=".rodata       ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
+  DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink)  *(.gnu.lto_*) }"
+  if test -z "${NO_SMALL_DATA}"; then
+    SBSS=".sbss         ${RELOCATING-0} :
+    {
+--- 127,133 ----
+  DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
+  RODATA=".rodata       ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
+  DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
+  if test -z "${NO_SMALL_DATA}"; then
+    SBSS=".sbss         ${RELOCATING-0} :
+    {
+diff -cpr ../binutils-2.23.2.orig/ld/scripttempl/elf.sc ld/scripttempl/elf.sc
+*** ../binutils-2.23.2.orig/ld/scripttempl/elf.sc	2013-05-14 16:39:39.755718177 +0100
+--- ld/scripttempl/elf.sc	2013-05-14 16:54:44.618743261 +0100
+*************** RELA_IPLT=".rela.iplt    ${RELOCATING-0}
+*** 158,164 ****
+  DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
+  RODATA=".${RODATA_NAME}       ${RELOCATING-0} : { *(.${RODATA_NAME}${RELOCATING+ .${RODATA_NAME}.* .gnu.linkonce.r.*}) }"
+  DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }"
+  if test -z "${NO_SMALL_DATA}"; then
+    SBSS=".${SBSS_NAME}         ${RELOCATING-0} :
+    {
+--- 158,164 ----
+  DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
+  RODATA=".${RODATA_NAME}       ${RELOCATING-0} : { *(.${RODATA_NAME}${RELOCATING+ .${RODATA_NAME}.* .gnu.linkonce.r.*}) }"
+  DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
+  if test -z "${NO_SMALL_DATA}"; then
+    SBSS=".${SBSS_NAME}         ${RELOCATING-0} :
+    {
+diff -cpr ../binutils-2.23.2.orig/ld/scripttempl/elfxtensa.sc ld/scripttempl/elfxtensa.sc
+*** ../binutils-2.23.2.orig/ld/scripttempl/elfxtensa.sc	2013-05-14 16:39:39.754718177 +0100
+--- ld/scripttempl/elfxtensa.sc	2013-05-14 16:55:44.908744932 +0100
+*************** fi
+*** 140,146 ****
+  DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
+  RODATA=".rodata       ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
+  DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink)  *(.gnu.lto_*) }"
+  INIT_LIT=".init.literal 0 : { *(.init.literal)	}"
+  INIT=".init         0 : { *(.init)		}"
+  FINI_LIT=".fini.literal 0 : { *(.fini.literal)	}"
+--- 140,146 ----
+  DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
+  RODATA=".rodata       ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
+  DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
+  INIT_LIT=".init.literal 0 : { *(.init.literal)	}"
+  INIT=".init         0 : { *(.init)		}"
+  FINI_LIT=".fini.literal 0 : { *(.fini.literal)	}"
+diff -cpr ../binutils-2.23.2.orig/ld/scripttempl/mep.sc ld/scripttempl/mep.sc
+*** ../binutils-2.23.2.orig/ld/scripttempl/mep.sc	2013-05-14 16:39:39.755718177 +0100
+--- ld/scripttempl/mep.sc	2013-05-14 16:56:08.605745589 +0100
+*************** fi
+*** 114,120 ****
+  DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
+  RODATA=".rodata       ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
+  DATARELRO=".data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro .data.rel.ro.*) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink)  *(.gnu.lto_*) }"
+  if test -z "${NO_SMALL_DATA}"; then
+    SBSS=".sbss         ${RELOCATING-0} :
+    {
+--- 114,120 ----
+  DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
+  RODATA=".rodata       ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
+  DATARELRO=".data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro .data.rel.ro.*) }"
+! DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
+  if test -z "${NO_SMALL_DATA}"; then
+    SBSS=".sbss         ${RELOCATING-0} :
+    {
+diff -cpr ../binutils-2.23.2.orig/ld/scripttempl/pep.sc ld/scripttempl/pep.sc
+*** ../binutils-2.23.2.orig/ld/scripttempl/pep.sc	2013-05-14 16:39:39.755718177 +0100
+--- ld/scripttempl/pep.sc	2013-05-14 16:40:07.064718934 +0100
+*************** SECTIONS
+*** 154,159 ****
+--- 154,160 ----
+      *(.drectve)
+      ${RELOCATING+ *(.note.GNU-stack)}
+      ${RELOCATING+ *(.gnu.lto_*)}
++     ${RELOCATING+ *(.gnu_object_only)}
+    }
+  
+    .idata ${RELOCATING+BLOCK(__section_alignment__)} :
+diff -cpr ../binutils-2.23.2.orig/ld/scripttempl/pe.sc ld/scripttempl/pe.sc
+*** ../binutils-2.23.2.orig/ld/scripttempl/pe.sc	2013-05-14 16:39:39.758718177 +0100
+--- ld/scripttempl/pe.sc	2013-05-14 16:40:07.064718934 +0100
+*************** SECTIONS
+*** 148,153 ****
+--- 148,154 ----
+      *(.drectve)
+      ${RELOCATING+ *(.note.GNU-stack)}
+      ${RELOCATING+ *(.gnu.lto_*)}
++     ${RELOCATING+ *(.gnu_object_only)}
+    }
+  
+    .idata ${RELOCATING+BLOCK(__section_alignment__)} :
diff --git a/binutils-2.23.2-ld-texinfo-fixes.patch b/binutils-2.23.2-ld-texinfo-fixes.patch
new file mode 100644
index 0000000..3c9e458
--- /dev/null
+++ b/binutils-2.23.2-ld-texinfo-fixes.patch
@@ -0,0 +1,87 @@
+*** ../binutils-2.23.2.orig/ld/ld.texinfo	2013-04-25 16:44:07.538768821 +0100
+--- ld/ld.texinfo	2013-04-25 16:47:27.040774352 +0100
+*************** in the section entitled ``GNU Free Docum
+*** 142,153 ****
+  @ifset ARM
+  * ARM::				ld and the ARM family
+  @end ifset
+- @ifset HPPA
+- * HPPA ELF32::                  ld and HPPA 32-bit ELF
+- @end ifset
+  @ifset M68HC11
+  * M68HC11/68HC12::              ld and the Motorola 68HC11 and 68HC12 families
+  @end ifset
+  @ifset M68K
+  * M68K::                        ld and Motorola 68K family
+  @end ifset
+--- 142,153 ----
+  @ifset ARM
+  * ARM::				ld and the ARM family
+  @end ifset
+  @ifset M68HC11
+  * M68HC11/68HC12::              ld and the Motorola 68HC11 and 68HC12 families
+  @end ifset
++ @ifset HPPA
++ * HPPA ELF32::                  ld and HPPA 32-bit ELF
++ @end ifset
+  @ifset M68K
+  * M68K::                        ld and Motorola 68K family
+  @end ifset
+*************** functionality are not listed.
+*** 5998,6003 ****
+--- 5998,6006 ----
+  @ifset I960
+  * i960::                        @command{ld} and the Intel 960 family
+  @end ifset
++ @ifset M68HC11
++ * M68HC11/68HC12::		@code{ld} and the Motorola 68HC11 and 68HC12 families
++ @end ifset
+  @ifset ARM
+  * ARM::				@command{ld} and the ARM family
+  @end ifset
+*************** functionality are not listed.
+*** 6013,6021 ****
+  @ifset MSP430
+  * MSP430::			@command{ld} and MSP430
+  @end ifset
+- @ifset M68HC11
+- * M68HC11/68HC12::		@code{ld} and the Motorola 68HC11 and 68HC12 families
+- @end ifset
+  @ifset POWERPC
+  * PowerPC ELF32::		@command{ld} and PowerPC 32-bit ELF Support
+  @end ifset
+--- 6016,6021 ----
+*************** If you have more than one @code{SECT} st
+*** 7863,7869 ****
+  @printindex cp
+  
+  @tex
+! % I think something like @colophon should be in texinfo.  In the
+  % meantime:
+  \long\def\colophon{\hbox to0pt{}\vfill
+  \centerline{The body of this manual is set in}
+--- 7863,7869 ----
+  @printindex cp
+  
+  @tex
+! % I think something like @@colophon should be in texinfo.  In the
+  % meantime:
+  \long\def\colophon{\hbox to0pt{}\vfill
+  \centerline{The body of this manual is set in}
+*************** If you have more than one @code{SECT} st
+*** 7874,7880 ****
+  \centerline{{\sl\fontname\tensl\/}}
+  \centerline{are used for emphasis.}\vfill}
+  \page\colophon
+! % Blame: doc at cygnus.com, 28mar91.
+  @end tex
+  
+  @bye
+--- 7874,7880 ----
+  \centerline{{\sl\fontname\tensl\/}}
+  \centerline{are used for emphasis.}\vfill}
+  \page\colophon
+! % Blame: doc@@cygnus.com, 28mar91.
+  @end tex
+  
+  @bye
diff --git a/binutils-2.23.52.0.1-64-bit-thin-archives.patch b/binutils-2.23.52.0.1-64-bit-thin-archives.patch
new file mode 100644
index 0000000..5415750
--- /dev/null
+++ b/binutils-2.23.52.0.1-64-bit-thin-archives.patch
@@ -0,0 +1,25 @@
+*** ../binutils-2.23.52.0.1.orig/bfd/archive64.c	2013-03-01 17:20:39.873535502 +0000
+--- bfd/archive64.c	2013-03-01 17:22:30.410538566 +0000
+*************** bfd_elf64_archive_write_armap (bfd *arch
+*** 210,218 ****
+  	  if (bfd_bwrite (buf, 8, arch) != 8)
+  	    return FALSE;
+  	}
+        /* Add size of this archive entry */
+!       archive_member_file_ptr += (arelt_size (current)
+! 				  + sizeof (struct ar_hdr));
+        /* remember about the even alignment */
+        archive_member_file_ptr += archive_member_file_ptr % 2;
+      }
+--- 210,220 ----
+  	  if (bfd_bwrite (buf, 8, arch) != 8)
+  	    return FALSE;
+  	}
++ 
+        /* Add size of this archive entry */
+!       archive_member_file_ptr += sizeof (struct ar_hdr);
+!       if (! bfd_is_thin_archive (arch))
+! 	archive_member_file_ptr += arelt_size (current);
+        /* remember about the even alignment */
+        archive_member_file_ptr += archive_member_file_ptr % 2;
+      }
diff --git a/binutils-2.23.52.0.1-addr2line-dynsymtab.patch b/binutils-2.23.52.0.1-addr2line-dynsymtab.patch
new file mode 100644
index 0000000..d434e3f
--- /dev/null
+++ b/binutils-2.23.52.0.1-addr2line-dynsymtab.patch
@@ -0,0 +1,144 @@
+*** ../binutils-2.23.52.0.1/binutils/addr2line.c	2013-02-27 20:28:03.000000000 +0000
+--- binutils/addr2line.c	2013-03-13 16:46:36.109519735 +0000
+*************** slurp_symtab (bfd *abfd)
+*** 130,135 ****
+--- 130,146 ----
+      symcount = bfd_canonicalize_symtab (abfd, syms);
+    if (symcount < 0)
+      bfd_fatal (bfd_get_filename (abfd));
++ 
++   /* If there are no symbols left after canonicalization and
++      we have not tried the dynamic symbols then give them a go.  */
++   if (symcount == 0
++       && ! dynamic
++       && (storage = bfd_get_dynamic_symtab_upper_bound (abfd)) > 0)
++     {
++       free (syms);
++       syms = xmalloc (storage);
++       symcount = bfd_canonicalize_dynamic_symtab (abfd, syms);
++     }
+  }
+  
+  /* These global variables are used to pass information between
+*** ../binutils-2.23.52.0.1.orig/bfd/opncls.c	2013-03-14 11:25:30.338306122 +0000
+--- bfd/opncls.c	2013-03-14 12:20:21.686397360 +0000
+*************** find_separate_debug_file (bfd *abfd, con
+*** 1297,1302 ****
+--- 1297,1304 ----
+        bfd_malloc (strlen (debug_file_directory) + 1
+                    + (canon_dirlen > dirlen ? canon_dirlen : dirlen)
+                    + strlen (".debug/")
++ #define FEDORA_LIB_DEBUG_DIR "/usr/lib/debug/"
++ 		  + strlen (FEDORA_LIB_DEBUG_DIR) + strlen ("usr/")
+                    + strlen (base)
+                    + 1);
+    if (debugfile == NULL)
+*************** find_separate_debug_file (bfd *abfd, con
+*** 1332,1337 ****
+--- 1334,1359 ----
+        return debugfile;
+      }
+  
++   /* Then try in the global debug dir for Fedora libraries.  */
++   sprintf (debugfile, "%s%s%s", FEDORA_LIB_DEBUG_DIR, dir, base);
++   if (separate_debug_file_exists (debugfile, crc32))
++     {
++       free (base);
++       free (dir);
++       free (canon_dir);
++       return debugfile;
++     }
++ 
++   /* Then try in the usr subdirectory of the global debug dir for Fedora libraries.  */
++   sprintf (debugfile, "%s/usr%s%s", FEDORA_LIB_DEBUG_DIR, dir, base);
++   if (separate_debug_file_exists (debugfile, crc32))
++     {
++       free (base);
++       free (dir);
++       free (canon_dir);
++       return debugfile;
++     }
++   
+    /* Then try in the global debugfile directory.  */
+    strcpy (debugfile, debug_file_directory);
+    dirlen = strlen (debug_file_directory) - 1;
+*** ../binutils-2.23.52.0.1.orig/bfd/dwarf2.c	2013-03-14 11:25:30.608306129 +0000
+--- bfd/dwarf2.c	2013-03-14 13:14:18.102487075 +0000
+*************** find_line (bfd *abfd,
+*** 3339,3346 ****
+--- 3339,3349 ----
+    struct dwarf2_debug *stash;
+    /* What address are we looking for?  */
+    bfd_vma addr;
++   /* What is the address without relocation ?  */
++   bfd_vma unrelocated_addr;
+    struct comp_unit* each;
+    bfd_vma found = FALSE;
++   bfd_vma possible_find = FALSE;
+    bfd_boolean do_line;
+  
+    *filename_ptr = NULL;
+*************** find_line (bfd *abfd,
+*** 3380,3385 ****
+--- 3383,3394 ----
+    else
+      abort ();
+  
++   /* If we are dealing with PIC code then the debug information
++      will be based on unrelocated addresses.  Since we cannot be
++      sure if this is a PIC address we test both with and without
++      relocation.  */
++   unrelocated_addr = addr;
++ 
+    if (section->output_section)
+      addr += section->output_section->vma + section->output_offset;
+    else
+*************** find_line (bfd *abfd,
+*** 3442,3447 ****
+--- 3451,3466 ----
+  						   stash));
+  	  if (found)
+  	    goto done;
++ 
++ 	  if (! possible_find)
++ 	    possible_find = ((each->arange.high == 0
++ 			      || comp_unit_contains_address (each, unrelocated_addr))
++ 			     && comp_unit_find_nearest_line (each, unrelocated_addr,
++ 							     filename_ptr,
++ 							     functionname_ptr,
++ 							     linenumber_ptr,
++ 							     discriminator_ptr,
++ 							     stash));
+  	}
+      }
+  
+*************** find_line (bfd *abfd,
+*** 3535,3540 ****
+--- 3554,3569 ----
+  						     discriminator_ptr,
+  						     stash));
+  
++ 	  if (! found && ! do_line && ! possible_find)
++ 	    possible_find = ((each->arange.high == 0
++ 			      || comp_unit_contains_address (each, unrelocated_addr))
++ 			     && comp_unit_find_nearest_line (each, unrelocated_addr,
++ 							     filename_ptr,
++ 							     functionname_ptr,
++ 							     linenumber_ptr,
++ 							     discriminator_ptr,
++ 							     stash));
++ 
+  	  if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
+  	      == stash->sec->size)
+  	    {
+*************** find_line (bfd *abfd,
+*** 3552,3557 ****
+--- 3581,3588 ----
+    if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+      unset_sections (stash);
+  
++   if (! found)
++     return possible_find;
+    return found;
+  }
+  
diff --git a/binutils-2.23.52.0.1-as-doc-texinfo-fixes.patch b/binutils-2.23.52.0.1-as-doc-texinfo-fixes.patch
new file mode 100644
index 0000000..688bd5e
--- /dev/null
+++ b/binutils-2.23.52.0.1-as-doc-texinfo-fixes.patch
@@ -0,0 +1,368 @@
+diff -cp ../binutils-2.23.52.0.1.orig/gas/doc/c-arm.texi gas/doc/c-arm.texi
+*** ../binutils-2.23.52.0.1.orig/gas/doc/c-arm.texi	2013-03-04 08:25:32.039931945 +0000
+--- gas/doc/c-arm.texi	2013-03-04 08:27:37.462927978 +0000
+*************** ARM and THUMB instructions had their own
+*** 390,418 ****
+  @code{unified} syntax, which can be selected via the @code{.syntax}
+  directive, and has the following main features:
+  
+! @table @bullet
+! @item
+  Immediate operands do not require a @code{#} prefix.
+  
+! @item
+  The @code{IT} instruction may appear, and if it does it is validated
+  against subsequent conditional affixes.  In ARM mode it does not
+  generate machine code, in THUMB mode it does.
+  
+! @item
+  For ARM instructions the conditional affixes always appear at the end
+  of the instruction.  For THUMB instructions conditional affixes can be
+  used, but only inside the scope of an @code{IT} instruction.
+  
+! @item
+  All of the instructions new to the V6T2 architecture (and later) are
+  available.  (Only a few such instructions can be written in the
+  @code{divided} syntax).
+  
+! @item
+  The @code{.N} and @code{.W} suffixes are recognized and honored.
+  
+! @item
+  All instructions set the flags if and only if they have an @code{s}
+  affix.
+  @end table
+--- 390,418 ----
+  @code{unified} syntax, which can be selected via the @code{.syntax}
+  directive, and has the following main features:
+  
+! @table @code
+! @item 1
+  Immediate operands do not require a @code{#} prefix.
+  
+! @item 2
+  The @code{IT} instruction may appear, and if it does it is validated
+  against subsequent conditional affixes.  In ARM mode it does not
+  generate machine code, in THUMB mode it does.
+  
+! @item 3
+  For ARM instructions the conditional affixes always appear at the end
+  of the instruction.  For THUMB instructions conditional affixes can be
+  used, but only inside the scope of an @code{IT} instruction.
+  
+! @item 4
+  All of the instructions new to the V6T2 architecture (and later) are
+  available.  (Only a few such instructions can be written in the
+  @code{divided} syntax).
+  
+! @item 5
+  The @code{.N} and @code{.W} suffixes are recognized and honored.
+  
+! @item 6
+  All instructions set the flags if and only if they have an @code{s}
+  affix.
+  @end table
+*************** Either @samp{#} or @samp{$} can be used
+*** 451,478 ****
+  @cindex register names, ARM
+  *TODO* Explain about ARM register naming, and the predefined names.
+  
+- @node ARM-Neon-Alignment
+- @subsection NEON Alignment Specifiers
+- 
+- @cindex alignment for NEON instructions
+- Some NEON load/store instructions allow an optional address
+- alignment qualifier.
+- The ARM documentation specifies that this is indicated by
+- @samp{@@ @var{align}}. However GAS already interprets
+- the @samp{@@} character as a "line comment" start,
+- so @samp{: @var{align}} is used instead.  For example:
+- 
+- @smallexample
+-         vld1.8 @{q0@}, [r0, :128]
+- @end smallexample
+- 
+- @node ARM Floating Point
+- @section Floating Point
+- 
+- @cindex floating point, ARM (@sc{ieee})
+- @cindex ARM floating point (@sc{ieee})
+- The ARM family uses @sc{ieee} floating-point numbers.
+- 
+  @node ARM-Relocations
+  @subsection ARM relocation generation
+  
+--- 451,456 ----
+*************** respectively.  For example to load the 3
+*** 519,524 ****
+--- 497,524 ----
+          MOVT r0, #:upper16:foo
+  @end smallexample
+  
++ @node ARM-Neon-Alignment
++ @subsection NEON Alignment Specifiers
++ 
++ @cindex alignment for NEON instructions
++ Some NEON load/store instructions allow an optional address
++ alignment qualifier.
++ The ARM documentation specifies that this is indicated by
++ @samp{@@ @var{align}}. However GAS already interprets
++ the @samp{@@} character as a "line comment" start,
++ so @samp{: @var{align}} is used instead.  For example:
++ 
++ @smallexample
++         vld1.8 @{q0@}, [r0, :128]
++ @end smallexample
++ 
++ @node ARM Floating Point
++ @section Floating Point
++ 
++ @cindex floating point, ARM (@sc{ieee})
++ @cindex ARM floating point (@sc{ieee})
++ The ARM family uses @sc{ieee} floating-point numbers.
++ 
+  @node ARM Directives
+  @section ARM Machine Directives
+  
+*** ../binutils-2.23.2.orig/gas/doc/c-arc.texi	2013-04-24 11:06:46.573176853 +0100
+--- gas/doc/c-arc.texi	2013-04-24 11:13:18.257187711 +0100
+*************** The extension instructions are not macro
+*** 220,226 ****
+  encodings for use of these instructions according to the specification
+  by the user.  The parameters are:
+  
+! @table @bullet
+  @item @var{name}
+  Name of the extension instruction 
+  
+--- 220,226 ----
+  encodings for use of these instructions according to the specification
+  by the user.  The parameters are:
+  
+! @table @code
+  @item @var{name}
+  Name of the extension instruction 
+  
+*** ../binutils-2.23.2.orig/gas/doc/c-cr16.texi	2013-04-24 11:06:46.576176853 +0100
+--- gas/doc/c-cr16.texi	2013-04-24 11:14:25.456189574 +0100
+*************** Operand expression type qualifier is an
+*** 44,69 ****
+  CR16 target operand qualifiers and its size (in bits):
+  
+  @table @samp
+! @item Immediate Operand
+! - s ---- 4 bits
+! @item 
+! - m ---- 16 bits, for movb and movw instructions.
+! @item 
+! - m ---- 20 bits, movd instructions.
+! @item 
+! - l ---- 32 bits
+! 
+! @item Absolute Operand
+! - s ---- Illegal specifier for this operand.
+! @item  
+! - m ---- 20 bits, movd instructions.
+! 
+! @item Displacement Operand
+! - s ---- 8 bits
+! @item
+! - m ---- 16 bits
+! @item 
+! - l ---- 24 bits
+  @end table
+  
+  For example:
+--- 44,76 ----
+  CR16 target operand qualifiers and its size (in bits):
+  
+  @table @samp
+! @item Immediate Operand: s
+! 4 bits.
+! 
+! @item Immediate Operand: m
+! 16 bits, for movb and movw instructions.
+! 
+! @item Immediate Operand: m
+! 20 bits, movd instructions.
+! 
+! @item Immediate Operand: l
+! 32 bits.
+! 
+! @item Absolute Operand: s
+! Illegal specifier for this operand.
+! 
+! @item Absolute Operand: m
+! 20 bits, movd instructions.
+! 
+! @item Displacement Operand: s
+! 8 bits.
+! 
+! @item Displacement Operand: m
+! 16 bits.
+! 
+! @item Displacement Operand: l
+! 24 bits.
+! 
+  @end table
+  
+  For example:
+*** ../binutils-2.23.2.orig/gas/doc/c-tic54x.texi	2013-04-24 11:06:46.571176853 +0100
+--- gas/doc/c-tic54x.texi	2013-04-24 11:15:13.653190910 +0100
+*************** In this example, x is replaced with SYM2
+*** 109,115 ****
+  is replaced with x.  At this point, x has already been encountered
+  and the substitution stops.
+  
+! @smallexample @code
+   .asg   "x",SYM1 
+   .asg   "SYM1",SYM2
+   .asg   "SYM2",x
+--- 109,115 ----
+  is replaced with x.  At this point, x has already been encountered
+  and the substitution stops.
+  
+! @smallexample
+   .asg   "x",SYM1 
+   .asg   "SYM1",SYM2
+   .asg   "SYM2",x
+*************** Substitution may be forced in situations
+*** 126,132 ****
+  ambiguous by placing colons on either side of the subsym.  The following
+  code: 
+  
+! @smallexample @code
+   .eval  "10",x
+  LAB:X:  add     #x, a
+  @end smallexample
+--- 126,132 ----
+  ambiguous by placing colons on either side of the subsym.  The following
+  code: 
+  
+! @smallexample
+   .eval  "10",x
+  LAB:X:  add     #x, a
+  @end smallexample
+*************** The @code{LDX} pseudo-op is provided for
+*** 309,315 ****
+  of a label or address.  For example, if an address @code{_label} resides
+  in extended program memory, the value of @code{_label} may be loaded as
+  follows:
+! @smallexample @code
+   ldx     #_label,16,a    ; loads extended bits of _label
+   or      #_label,a       ; loads lower 16 bits of _label
+   bacc    a               ; full address is in accumulator A
+--- 309,315 ----
+  of a label or address.  For example, if an address @code{_label} resides
+  in extended program memory, the value of @code{_label} may be loaded as
+  follows:
+! @smallexample
+   ldx     #_label,16,a    ; loads extended bits of _label
+   or      #_label,a       ; loads lower 16 bits of _label
+   bacc    a               ; full address is in accumulator A
+diff -cp ../binutils-2.23.2.orig/gas/doc/c-mips.texi gas/doc/c-mips.texi
+*** ../binutils-2.23.2.orig/gas/doc/c-mips.texi	2013-04-25 16:43:35.115767923 +0100
+--- gas/doc/c-mips.texi	2013-04-26 08:07:10.338304064 +0100
+*************** the @samp{mad} and @samp{madu} instructi
+*** 234,240 ****
+  instructions around accesses to the @samp{HI} and @samp{LO} registers.
+  @samp{-no-m4650} turns off this option.
+  
+! @itemx -m3900
+  @itemx -no-m3900
+  @itemx -m4100
+  @itemx -no-m4100
+--- 234,240 ----
+  instructions around accesses to the @samp{HI} and @samp{LO} registers.
+  @samp{-no-m4650} turns off this option.
+  
+! @item -m3900
+  @itemx -no-m3900
+  @itemx -m4100
+  @itemx -no-m4100
+diff -cp ../binutils-2.23.2.orig/gas/doc/c-score.texi gas/doc/c-score.texi
+*** ../binutils-2.23.2.orig/gas/doc/c-score.texi	2013-04-25 16:43:35.043767921 +0100
+--- gas/doc/c-score.texi	2013-04-26 08:07:37.975304830 +0100
+*************** implicitly with the @code{gp} register.
+*** 37,43 ****
+  @item -EB
+  Assemble code for a big-endian cpu
+  
+! @itemx -EL
+  Assemble code for a little-endian cpu
+  
+  @item -FIXDD 
+--- 37,43 ----
+  @item -EB
+  Assemble code for a big-endian cpu
+  
+! @item -EL
+  Assemble code for a little-endian cpu
+  
+  @item -FIXDD 
+*************** Assemble code for no warning message for
+*** 49,61 ****
+  @item -SCORE5
+  Assemble code for target is SCORE5
+  
+! @itemx -SCORE5U
+  Assemble code for target is SCORE5U
+  
+! @itemx -SCORE7
+  Assemble code for target is SCORE7, this is default setting
+  
+! @itemx -SCORE3
+  Assemble code for target is SCORE3
+  
+  @item -march=score7
+--- 49,61 ----
+  @item -SCORE5
+  Assemble code for target is SCORE5
+  
+! @item -SCORE5U
+  Assemble code for target is SCORE5U
+  
+! @item -SCORE7
+  Assemble code for target is SCORE7, this is default setting
+  
+! @item -SCORE3
+  Assemble code for target is SCORE3
+  
+  @item -march=score7
+diff -cp ../binutils-2.23.2.orig/gas/doc/c-tic54x.texi gas/doc/c-tic54x.texi
+*** ../binutils-2.23.2.orig/gas/doc/c-tic54x.texi	2013-04-25 16:43:35.042767921 +0100
+--- gas/doc/c-tic54x.texi	2013-04-26 08:08:02.418305508 +0100
+*************** LAB:X:  add     #x, a
+*** 133,139 ****
+  
+  When assembled becomes:
+  
+! @smallexample @code
+  LAB10  add     #10, a
+  @end smallexample
+  
+--- 133,139 ----
+  
+  When assembled becomes:
+  
+! @smallexample 
+  LAB10  add     #10, a
+  @end smallexample
+  
+*************** Assign @var{name} the string @var{string
+*** 345,351 ****
+  performed on @var{string} before assignment.
+  
+  @cindex @code{eval} directive, TIC54X
+! @itemx .eval @var{string}, @var{name}
+  Evaluate the contents of string @var{string} and assign the result as a
+  string to the subsym @var{name}.  String replacement is performed on
+  @var{string} before assignment. 
+--- 345,351 ----
+  performed on @var{string} before assignment.
+  
+  @cindex @code{eval} directive, TIC54X
+! @item .eval @var{string}, @var{name}
+  Evaluate the contents of string @var{string} and assign the result as a
+  string to the subsym @var{name}.  String replacement is performed on
+  @var{string} before assignment. 
diff --git a/binutils-2.23.52.0.1-check-regular-ifunc-refs.patch b/binutils-2.23.52.0.1-check-regular-ifunc-refs.patch
new file mode 100644
index 0000000..c9bfd64
--- /dev/null
+++ b/binutils-2.23.52.0.1-check-regular-ifunc-refs.patch
@@ -0,0 +1,48 @@
+*** ../binutils-2.23.52.0.1.orig/bfd/elf-ifunc.c	2013-04-17 15:53:49.662586029 +0100
+--- bfd/elf-ifunc.c	2013-04-17 15:55:55.269589511 +0100
+*************** _bfd_elf_allocate_ifunc_dyn_relocs (stru
+*** 187,209 ****
+  
+    htab = elf_hash_table (info);
+  
+    /* Support garbage collection against STT_GNU_IFUNC symbols.  */
+    if (h->plt.refcount <= 0 && h->got.refcount <= 0)
+      {
+-       /* When building shared library, we need to handle the case
+-          where it is marked with regular reference, but not non-GOT
+- 	 reference.  It may happen if we didn't see STT_GNU_IFUNC
+- 	 symbol at the time when checking relocations.  */
+-       if (info->shared
+- 	  && !h->non_got_ref
+- 	  && h->ref_regular)
+- 	for (p = *head; p != NULL; p = p->next)
+- 	  if (p->count)
+- 	    {
+- 	      h->non_got_ref = 1;
+- 	      goto keep;
+- 	    }
+- 
+        h->got = htab->init_got_offset;
+        h->plt = htab->init_plt_offset;
+        *head = NULL;
+--- 187,206 ----
+  
+    htab = elf_hash_table (info);
+  
++   /* When building a shared library, we need to handle the case where it is
++      marked with a regular reference, but not a non-GOT reference since the
++      non-GOT reference bit may not be set here.  */
++   if (info->shared && !h->non_got_ref && h->ref_regular)
++     for (p = *head; p != NULL; p = p->next)
++       if (p->count)
++ 	{
++ 	  h->non_got_ref = 1;
++ 	  goto keep;
++ 	}
++ 
+    /* Support garbage collection against STT_GNU_IFUNC symbols.  */
+    if (h->plt.refcount <= 0 && h->got.refcount <= 0)
+      {
+        h->got = htab->init_got_offset;
+        h->plt = htab->init_plt_offset;
+        *head = NULL;
diff --git a/cross-binutils.spec b/cross-binutils.spec
index 624ad20..729fbe3 100644
--- a/cross-binutils.spec
+++ b/cross-binutils.spec
@@ -45,16 +45,31 @@
 
 Summary: A GNU collection of cross-compilation binary utilities
 Name: %{cross}-binutils
-Version: 2.23.51.0.3
-Release: 2%{?dist}
+# Note - this version number is a lie.  It should actually be 2.23.2 since
+# that is the version of the base sources.  But we have decided to switch
+# from tracking the Linux Kernel binutils releases to tracking the FSF
+# binutils releases half way through the FSF binutils release cycle.  The
+# version prior to this change was 2.23.52.0.1, but if we just set the new
+# version definition to be 2.23.2 then we would have a regression in the
+# binutils rpm numbers, which would break the rpm update mechanism.  So
+# instead we create a bogus, higher, version number here.  Once the next
+# official binutils release happens (2.24.0) we will be able to restore
+# Version to an honest value and everything will be good again.
+Version: 2.23.88.0.1
+%define srcdir binutils-2.23.2
+Release: 1%{?dist}
 License: GPLv3+
 Group: Development/Tools
 URL: http://sources.redhat.com/binutils
 
-Source: ftp://ftp.kernel.org/pub/linux/devel/binutils/binutils-%{version}.tar.xz
-# The ftp.kernel.org/pub/linux/devel/binutils/ page is (temporarily) unavailable
-# so we use the GNU site instead.
-# Source: http://ftp.gnu.org/gnu/binutils/binutils-%{version}.tar.bz2
+# Note - see comment about the definition of Version above.  Once Version is
+# restored to a proper value the definition of Source below should be changed
+# to use %{version} instead of 2.23.2
+#
+# Note - the Linux Kernel binutils releases are too unstable and contain too
+# many controversial patches so we stick with the official FSF version
+# instead.
+Source: http://ftp.gnu.org/gnu/binutils/binutils-2.23.2.tar.bz2
 Source2: binutils-2.19.50.0.1-output-format.sed
 Patch01: binutils-2.20.51.0.2-libtool-lib64.patch
 Patch02: binutils-2.20.51.0.10-ppc64-pie.patch
@@ -69,8 +84,22 @@ Patch08: binutils-2.22.52.0.1-relro-on-by-default.patch
 Patch09: binutils-2.22.52.0.1-export-demangle.h.patch
 # Disable checks that config.h has been included before system headers.  BZ #845084
 Patch10: binutils-2.22.52.0.4-no-config-h-check.patch
-# Renames ARM LDRALT insn to LDALT.  BZ# 869025
-Patch11: binutils-2.23.51.0.3-arm-ldralt.patch
+# Fix the creation of the index table in 64-bit thin archives.
+Patch11: binutils-2.23.52.0.1-64-bit-thin-archives.patch
+# Fix errors reported by version 5.0 of texinfo in gas documentation
+Patch12: binutils-2.23.52.0.1-as-doc-texinfo-fixes.patch
+# Fix addr2line to use the dynamic symbol table if it could not find any ordinary symbols.
+Patch13: binutils-2.23.52.0.1-addr2line-dynsymtab.patch
+# Check regular references without non-GOT references when building shared libraries.
+Patch14: binutils-2.23.52.0.1-check-regular-ifunc-refs.patch
+# Fix errors reported by version 5.0 of texinfo in ld documentation
+Patch15: binutils-2.23.2-ld-texinfo-fixes.patch
+Patch16: binutils-2.23.2-kernel-ld-r.patch
+Patch17: binutils-2.23.2-bfd-texinfo-fixes.patch
+# Add support for the alternate debug info files created by the DWZ program.
+Patch18: binutils-2.23.2-dwz-alt-debuginfo.patch
+# Correct bug introduced by patch 16
+Patch19: binutils-2.23.2-aarch64-em.patch
 
 Buildroot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
 BuildRequires: texinfo >= 4.0, gettext, flex, bison, zlib-devel
@@ -171,7 +200,6 @@ Cross-build binary image generation, manipulation and query tools. \
 ###############################################################################
 %prep
 
-%define srcdir binutils-%{version}
 %setup -q -n %{srcdir} -c
 cd %{srcdir}
 %patch01 -p0 -b .libtool-lib64~
@@ -190,7 +218,15 @@ cd %{srcdir}
 %endif
 %patch09 -p0 -b .export-demangle-h~
 %patch10 -p0 -b .no-config-h-check~
-%patch11 -p0 -b .arm-ldralt~
+%patch11 -p0 -b .64bit-thin-archives~
+%patch12 -p0 -b .gas-texinfo~
+%patch13 -p0 -b .addr2line~
+%patch14 -p0 -b .check-ifunc~
+%patch15 -p0 -b .ld-texinfo~
+%patch16 -p0 -b .kernel-ld-r~
+%patch17 -p0 -b .bfd-texinfo~
+%patch18 -p0 -b .dwz~
+%patch19 -p0 -b .aarch64~
 
 # We cannot run autotools as there is an exact requirement of autoconf-2.59.
 
@@ -629,6 +665,9 @@ rm -rf %{buildroot}
 %do_files xtensa-linux-gnu	%{build_xtensa}
 
 %changelog
+* Tue Jun 4 2013 David Howells <dhowells at redhat.com> - 2.23.88.0.1-1
+- Update to binutils-2.22.88.0.1 to fix F19 texinfo issues [BZ 912921].
+
 * Tue Jun 4 2013 David Howells <dhowells at redhat.com> - 2.23.51.0.3-2
 - Backport cleanups from the RHEL-6.4 cross-compiler.
 - Backport some macroisation from the RHEL-6.4 cross-compiler.


More information about the scm-commits mailing list