Blob Blame History Raw
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;
+     }
+ }
+ 
  struct bfd_preserve
  {
    void *marker;
*************** bfd_check_format_matches (bfd *abfd, bfd
*** 136,142 ****
      }
  
    if (abfd->format != bfd_unknown)
!     return abfd->format == format;
  
    if (matching != NULL || *bfd_associated_vector != NULL)
      {
--- 163,172 ----
      }
  
    if (abfd->format != bfd_unknown)
!     {
!       bfd_set_lto_type (abfd);
!       return abfd->format == format;
!     }
  
    if (matching != NULL || *bfd_associated_vector != NULL)
      {
*************** bfd_check_format_matches (bfd *abfd, bfd
*** 322,327 ****
--- 352,360 ----
  
        if (matching_vector)
  	free (matching_vector);
+ 
+       bfd_set_lto_type (abfd);
+ 
  
        /* File position has moved, BTW.  */
        return TRUE;
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_ignoresym (struct bfd_link_info *, 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__)} :