]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Merge remote-tracking branch 'origin/hjl/linux/master' into hjl/linux/applied
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 27 Jan 2014 17:15:45 +0000 (09:15 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 27 Jan 2014 17:15:45 +0000 (09:15 -0800)
Remove binutils-pr16322.patch and binutils-pr16317.patch, which have
been upstreamed.  Apply binutils-pr16496.patch.  Update
binutils-lto-mixed.patch.

40 files changed:
1  2 
ChangeLog.lto-mixed
ChangeLog.pr16496
bfd/archive.c
bfd/bfd-in2.h
bfd/elf-bfd.h
bfd/elf.c
bfd/elf32-i386.c
bfd/elf32-mips.c
bfd/elf64-x86-64.c
bfd/elfcode.h
bfd/elflink.c
bfd/elfn32-mips.c
bfd/opncls.c
bfd/plugin.c
binutils/objcopy.c
binutils/objdump.c
binutils/readelf.c
gas/doc/as.texinfo
gas/testsuite/gas/elf/elf.exp
ld/emulparams/elf32_x86_64.sh
ld/emulparams/elf_i386.sh
ld/emultempl/aarch64elf.em
ld/emultempl/armelf.em
ld/emultempl/elf32.em
ld/emultempl/ppc64elf.em
ld/emultempl/spuelf.em
ld/ld.texinfo
ld/ldlang.c
ld/ldlang.h
ld/ldmain.c
ld/testsuite/ld-cris/weakref3.d
ld/testsuite/ld-cris/weakref4.d
ld/testsuite/ld-elf/pr16496a.c
ld/testsuite/ld-elf/pr16496a.map
ld/testsuite/ld-elf/pr16496b.c
ld/testsuite/ld-elf/pr16496b.od
ld/testsuite/ld-elf/shared.exp
ld/testsuite/ld-elfvers/vers24.rd
ld/testsuite/ld-plugin/lto.exp
ld/testsuite/ld-plugin/pr12365b.c

index b14ef5d0a8a6289afafb9f9f8f4d7f36e7d1b3c2,0000000000000000000000000000000000000000..f3ca7be5d356748b7e0854a705a72b0eeaa84d10
mode 100644,000000..100644
--- /dev/null
@@@ -1,310 -1,0 +1,315 @@@
 +bfd/
 +
 +2013-02-15  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * ldlang.c (lang_finish): Take a bfd_boolean argument to support
 +      object-only output.
 +      (cmdline_emit_object_only_section): Pass TRUE to lang_finish.
 +
 +      * ldlang.h (lang_finish): Updated.
 +
 +      * ldmain.c (main): Pass FALSE to lang_finish.
 +
 +2012-10-25  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      PR ld/14747
 +      * elflink.c (_bfd_elf_fix_symbol_flags): Check symbol for linker
 +      created section instead.
 +
 +2012-10-25  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      PR ld/14747
 +      * elflink.c (_bfd_elf_fix_symbol_flags): Never mark
 +      _GLOBAL_OFFSET_TABLE_, _PROCEDURE_LINKAGE_TABLE_ nor _DYNAMIC
 +      undefined.
 +
 +2012-06-28  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      PR ld/14272
 +      * elflink.c (_bfd_elf_fix_symbol_flags): Mark the plugin symbol
 +      undefined if it is referenced from a non-IR file.
 +
 +2012-06-04  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * plugin.c (add_symbols): Set tdata.plugin_data before calling
 +      bfd_plugin_get_symbols_in_object_only.
 +
 +2011-10-16  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * plugin.c (add_symbols): Call
 +      bfd_plugin_get_symbols_in_object_only.
 +      (bfd_plugin_get_symtab_upper_bound): Don't call
 +      bfd_plugin_get_symbols_in_object_only.
 +
 +2011-10-16  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * plugin.c (bfd_plugin_get_symbols_in_object_only): Optimized.
 +
 +2011-10-16  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * plugin.c (bfd_plugin_get_symbols_in_object_only): Properly
 +      remove the object only section file.
 +
 +2011-10-15  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      PR ld/13298
 +      * opncls.c (bfd_extract_object_only_section): New.
 +
 +      * plugin.c (add_symbols): Initialize object_only_syms and
 +      object_only_nsyms.
 +      (bfd_plugin_fake_text_section): New.
 +      (bfd_plugin_fake_common_section): Likewise.
 +      (bfd_plugin_get_symbols_in_object_only): Likewise.
 +      (bfd_plugin_get_symtab_upper_bound): Call
 +      bfd_plugin_get_symbols_in_object_only and add symbols from
 +      object only section.
 +      (bfd_plugin_canonicalize_symtab): Remove fake_section and
 +      fake_common_section.  Use bfd_plugin_fake_text_section and
 +      bfd_plugin_fake_common_section.  Set udata.p to NULL.  Copy
 +      symbols from object only section.
 +
 +      * plugin.h (plugin_data_struct): Add object_only_nsyms and
 +      object_only_syms.
 +
 +      * bfd-in2.h: Regenerated.
 +
 +2011-05-14  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      PR ld/12758
 +      * elflink.c (elf_link_add_archive_symbols): Don't load the IR
 +      archive member twice.
 +
 +2011-04-19  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * bfd.c (bfd_lto_object_type): New.
 +      (bfd): Add object_only_section and lto_type.
 +      (bfd_group_signature): New.
 +
 +      * elf.c (special_sections_g): Add .gnu_object_only.
 +
 +      * format.c (bfd_set_lto_type): New.
 +      (bfd_check_format_matches): Use it.
 +
 +      * section.c (GNU_OBJECT_ONLY_SECTION_NAME): New.
 +
 +      * bfd-in2.h: Regenerated.
 +
 +binutils/
 +
 +2011-04-19  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * objcopy.c (group_signature): Removed.
 +      (is_strip_section): Replace group_signature with
 +      bfd_group_signature.
 +      (setup_section): Likewise.
 +
 +      * readelf.c (get_section_type_name): Handle SHT_GNU_OBJECT_ONLY.
 +
 +gas/testsuite/
 +
 +2011-04-19  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * gas/elf/section9.s: Add the .gnu_object_only test.
 +      * gas/elf/section9.d: Updated.
 +
 +include/
 +
 +2011-04-19  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * bfdlink.h (bfd_link_info): Add emit_gnu_object_only and
 +      emitting_gnu_object_only.
 +
 +include/elf/
 +
 +2011-04-19  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * common.h (SHT_GNU_OBJECT_ONLY): New.
 +
 +ld/
 +
++2014-01-11  H.J. Lu  <hongjiu.lu@intel.com>
++
++      * ldlang.c (cmdline_add_object_only_section): Save BFD filename
++      to be used after bfd_close ().
++
 +2012-10-20  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * ldlang.c (lang_process): Replace trace_file_tries with
 +      verbose.
 +
 +2012-08-14  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * emultempl/aarch64elf.em (gld${EMULATION_NAME}_finish): Renamed
 +      to ...
 +      (aarch64_finish): This.  Replace finish_default with
 +      gld${EMULATION_NAME}_finish.
 +      (LDEMUL_FINISH): Set to aarch64_finish.
 +
 +2011-10-15  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      PR ld/13298
 +      * ldlang.c (cmdline_extract_object_only_section): Call
 +      bfd_extract_object_only_section.
 +
 +2011-05-17  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * ldlang.c (cmdline_remove_object_only_files): Return if
 +      ENABLE_PLUGINS is undefined or plugin_save_temps is true.
 +
 +2011-05-15  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * ldlex.h (option_values): Add OPTION_PLUGIN_SAVE_TEMPS.
 +      * lexsup.c (ld_options): Add -plugin-save-temps.
 +      (parse_args): Handle OPTION_PLUGIN_SAVE_TEMPS.
 +
 +      * plugin.c (plugin_save_temps): New.
 +      (plugin_call_cleanup): Don't call plugin cleanup_handler if
 +      plugin_save_temps is true.
 +
 +      * plugin.h (plugin_save_temps): New.
 +
 +2011-05-14  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      PR ld/12760
 +      * ldmain.c (warning_callback): Don't warn plugin dummy.
 +
 +2011-04-19  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      * emultempl/alphaelf.em (alpha_finish): Replace finish_default
 +      with gld${EMULATION_NAME}_finish.
 +
 +      * emultempl/armelf.em (gld${EMULATION_NAME}_finish): Renamed
 +      to ...
 +      (arm_finish): This.  Replace finish_default with
 +      gld${EMULATION_NAME}_finish.
 +      (LDEMUL_FINISH): Set to arm_finish.
 +
 +      * emultempl/elf32.em (gld${EMULATION_NAME}_finish): New.
 +      (orphan_init_done): Likewise.
 +      (ld_${EMULATION_NAME}_emulation): Use gld${EMULATION_NAME}_finish.
 +      (gld${EMULATION_NAME}_place_orphan): Initialize hold.
 +
 +      * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Renamed
 +      to ...
 +      (ppc_finish): This.  Replace finish_default with
 +      gld${EMULATION_NAME}_finish.
 +      (LDEMUL_FINISH): Set to ppc_finish.
 +
 +      * emultempl/spuelf.em (gld${EMULATION_NAME}_finish): Renamed
 +      to ...
 +      (spu_finish): This.  Replace finish_default with
 +      gld${EMULATION_NAME}_finish.
 +      (LDEMUL_FINISH): Set to spu_finish.
 +
 +      * ldfile.c (ldfile_try_open_bfd): Call
 +      cmdline_check_object_only_section.
 +
 +      * ldlang.c: Include "ldwrite.h" and elf-bfd.h.
 +      * ldlang.c (cmdline_object_only_file_list): New.
 +      (cmdline_object_only_archive_list): Likewise.
 +      (cmdline_temp_object_only_list): Likewise.
 +      (cmdline_lists_init): Likewise.
 +      (cmdline_list_new): Likewise.
 +      (cmdline_list_append): Likewise.
 +      (print_cmdline_list): Likewise.
 +      (cmdline_on_object_only_archive_list_p): Likewise.
 +      (cmdline_object_only_list_append): Likewise.
 +      (cmdline_get_object_only_input_files): Likewise.
 +      (cmdline_arg): Likewise.
 +      (setup_section): Likewise.
 +      (copy_section): Likewise.
 +      (cmdline_fopen_temp): Likewise.
 +      (cmdline_add_object_only_section): Likewise.
 +      (cmdline_emit_object_only_section): Likewise.
 +      (cmdline_extract_object_only_section): Likewise.
 +      (cmdline_check_object_only_section): Likewise.
 +      (cmdline_remove_object_only_files): Likewise.
 +      (lang_init): Take a bfd_boolean argument to supprt object-only
 +      output.  Call cmdline_lists_init.
 +      (load_symbols): Call cmdline_on_object_only_archive_list_p
 +      to check if an archive member should be loaded.
 +      (lang_process): Handle object-only link.
 +
 +      * ldlang.h (lang_init): Take a bfd_boolean argument.
 +      (cmdline_enum_type): New.
 +      (cmdline_header_type): Likewise.
 +      (cmdline_file_type): Likewise.
 +      (cmdline_bfd_type): Likewise.
 +      (cmdline_union_type): Likewise.
 +      (cmdline_list_type): Likewise.
 +      (cmdline_emit_object_only_section): Likewise.
 +      (cmdline_check_object_only_section): Likewise.
 +      (cmdline_remove_object_only_files): Likewise.
 +
 +      * ldmain.c (main): Call xatexit with
 +      cmdline_remove_object_only_files.  Pass FALSE to lang_init.
 +      Use ld_parse_linker_script.  Set link_info.output_bfd to NULL
 +      after close.  Call cmdline_emit_object_only_section if needed.
 +      (add_archive_element): Call cmdline_check_object_only_section.
 +      (ld_parse_linker_script): New.
 +
 +      * ldmain.h (ld_parse_linker_script): New.
 +
 +      * plugin.c (plugin_opt_plugin_arg): Ignore -pass-through=.
 +      (plugin_maybe_claim): Call cmdline_check_object_only_section
 +      on claimed IR files.
 +
 +      * scripttempl/armbpabi.sc: Also discard .gnu_object_only
 +      sections.
 +      * scripttempl/elf.sc: Likewise.
 +      * scripttempl/elf32sh-symbian.sc: Likewise.
 +      * scripttempl/elf64hppa.sc: Likewise.
 +      * scripttempl/elfxtensa.sc: Likewise.
 +      * scripttempl/mep.sc: Likewise.
 +      * scripttempl/pe.sc: Likewise.
 +      * scripttempl/pep.sc: Likewise.
 +
 +ld/testsuite/
 +
 +2012-12-05  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      PR ld/14918
 +      * ld-plugin/lto.exp (lto_link_elf_tests): Add PR ld/14918 test.
 +
 +      * ld-plugin/pr14918.c: New file.
 +      * ld-plugin/pr14918.d: Likewise.
 +
 +2011-01-22  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      PR ld/12365
 +      * ld-plugin/pr12365a.c: New file.
 +      * ld-plugin/pr12365b.c: Likewise.
 +      * ld-plugin/pr12365c.c: Likewise.
 +
 +      * ld-plugin/lto.exp (lto_link_tests): Prepare for the PR ld/12365
 +      test.
 +      Run the PR ld/12365 test.
 +
 +2011-01-22  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      PR ld/12430
 +      * ld-plugin/lto-10.out: New file.
 +      * ld-plugin/lto-10a.c: Likewise.
 +      * ld-plugin/lto-10b.c: Likewise.
 +      * ld-plugin/lto-10r.d: Likewise.
 +
 +      * ld-plugin/lto.exp (lto_link_tests): Prepare for "LTO 10".
 +      (lto_run_tests): Add "LTO 10".
 +      Run lto-10r and create tmpdir/lto-10.o.
 +
 +2011-01-22  H.J. Lu  <hongjiu.lu@intel.com>
 +
 +      PR ld/12291
 +      * ld-plugin/lto-4.out: Likewise.
 +      * ld-plugin/lto-4a.c: Likewise.
 +      * ld-plugin/lto-4b.c: Likewise.
 +      * ld-plugin/lto-4c.c: Likewise.
 +      * ld-plugin/lto-4r-a.d: Likewise.
 +      * ld-plugin/lto-4r-b.d: Likewise.
 +      * ld-plugin/lto-4r-c.d: Likewise.
 +      * ld-plugin/lto-4r-d.d: Likewise.
 +
 +      * ld-plugin/lto.exp (lto_link_tests): Prepare for "LTO 4[acd]"
 +      and "lto-4r-[abcd]" tests.
 +      (lto_run_tests): Add "LTO 4[acd]" tests.
 +      Build liblto-4.a.  Run "lto-4r-[abcd]" tests.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ef188ab809be6a02d2bb49a56f23c56684095862
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,46 @@@
++bfd/
++
++2014-01-24  H.J. Lu  <hongjiu.lu@intel.com>
++
++      PR binutils/16496
++      * elf-bfd.h (bfd_elf_get_symbol_version_string): New.
++      * elf.c (bfd_elf_get_symbol_version_string): New.  Extracted
++      from bfd_elf_print_symbol.
++      (bfd_elf_print_symbol): Use it.
++
++binutils/
++
++2014-01-24  H.J. Lu  <hongjiu.lu@intel.com>
++
++      PR binutils/16496
++      * objdump.c (objdump_print_symname): Call
++      bfd_elf_get_symbol_version_string to get ELF symbol version
++      string.  Append version string if needed.
++
++      * readelf.c (versioned_symbol_info): New enum.
++      (get_symbol_version_string): New.  Extracted from
++      process_symbol_table.
++      (dump_relocations): Add a new argument to indicate if dynamic
++      symbol table is used.  Use get_symbol_version_string to get
++      symbol version string for dynamic symbol.  Append version string
++      if needed.
++      (process_relocs): Updated dump_relocations call.
++      (process_symbol_table): Use get_symbol_version_string.
++
++ld/testsuite/
++
++2014-01-24  H.J. Lu  <hongjiu.lu@intel.com>
++
++      PR binutils/16496
++      * ld-cris/weakref3.d: Add symbol version string to versioned
++      symbol names in dynamic relocation.
++      * ld-cris/weakref4.d: Likewise.
++      * ld-elfvers/vers24.rd: Likewise.
++
++      * ld-elf/pr16496a.c: New file.
++      * ld-elf/pr16496a.map: Likewise.
++      * ld-elf/pr16496b.c: Likewise.
++      * ld-elf/pr16496b.od: Likewise.
++
++      * ld-elf/shared.exp (build_tests): Add libpr16496a.so and
++      libpr16496b.so tests.
diff --cc bfd/archive.c
Simple merge
diff --cc bfd/bfd-in2.h
Simple merge
diff --cc bfd/elf-bfd.h
index 521ce1eeed3f5102dfdba4992fedba515d2f5d37,0aab5fa065a6b64a0f25b650c1e753a89e1c3b7c..f8d80e79705a5c1f6f8be9017933bd406986fd33
@@@ -1767,6 -1767,6 +1768,8 @@@ extern bfd_boolean _bfd_elf_copy_privat
    (bfd *, bfd *);
  extern bfd_boolean _bfd_elf_print_private_bfd_data
    (bfd *, void *);
++const char * bfd_elf_get_symbol_version_string
++  (bfd *, asymbol *, bfd_boolean *);
  extern void bfd_elf_print_symbol
    (bfd *, void *, asymbol *, bfd_print_symbol_type);
  
diff --cc bfd/elf.c
index 560d19be1338df214b72fb83085ff0fab927868b,c0303fc21a6d57855d9afa9d4938f1ca8d733426..21a4b304a7fedc61ac5769246d38eb63a0e0ec23
+++ b/bfd/elf.c
@@@ -1396,6 -1396,6 +1396,53 @@@ _bfd_elf_print_private_bfd_data (bfd *a
    return FALSE;
  }
  
++/* Get version string.  */
++
++const char *
++bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
++                                 bfd_boolean *hidden)
++{
++  const char *version_string = NULL;
++  if (elf_dynversym (abfd) != 0
++      && (elf_dynverdef (abfd) != 0 || elf_dynverref (abfd) != 0))
++    {
++      unsigned int vernum = ((elf_symbol_type *) symbol)->version;
++
++      *hidden = (vernum & VERSYM_HIDDEN) != 0;
++      vernum &= VERSYM_VERSION;
++
++      if (vernum == 0)
++      version_string = "";
++      else if (vernum == 1)
++      version_string = "Base";
++      else if (vernum <= elf_tdata (abfd)->cverdefs)
++      version_string =
++        elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
++      else
++      {
++        Elf_Internal_Verneed *t;
++
++        version_string = "";
++        for (t = elf_tdata (abfd)->verref;
++             t != NULL;
++             t = t->vn_nextref)
++          {
++            Elf_Internal_Vernaux *a;
++
++            for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
++              {
++                if (a->vna_other == vernum)
++                  {
++                    version_string = a->vna_nodename;
++                    break;
++                  }
++              }
++          }
++      }
++    }
++  return version_string;
++}
++
  /* Display ELF-specific fields of a symbol.  */
  
  void
@@@ -1422,6 -1422,6 +1469,8 @@@ bfd_elf_print_symbol (bfd *abfd
        const struct elf_backend_data *bed;
        unsigned char st_other;
        bfd_vma val;
++      const char *version_string;
++      bfd_boolean hidden;
  
        section_name = symbol->section ? symbol->section->name : "(*none*)";
  
        bfd_fprintf_vma (abfd, file, val);
  
        /* If we have version information, print it.  */
--      if (elf_dynversym (abfd) != 0
--          && (elf_dynverdef (abfd) != 0
--              || elf_dynverref (abfd) != 0))
++      version_string = bfd_elf_get_symbol_version_string (abfd,
++                                                          symbol,
++                                                          &hidden);
++      if (version_string)
          {
--          unsigned int vernum;
--          const char *version_string;
--
--          vernum = ((elf_symbol_type *) symbol)->version & VERSYM_VERSION;
--
--          if (vernum == 0)
--            version_string = "";
--          else if (vernum == 1)
--            version_string = "Base";
--          else if (vernum <= elf_tdata (abfd)->cverdefs)
--            version_string =
--              elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
--          else
--            {
--              Elf_Internal_Verneed *t;
--
--              version_string = "";
--              for (t = elf_tdata (abfd)->verref;
--                   t != NULL;
--                   t = t->vn_nextref)
--                {
--                  Elf_Internal_Vernaux *a;
--
--                  for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
--                    {
--                      if (a->vna_other == vernum)
--                        {
--                          version_string = a->vna_nodename;
--                          break;
--                        }
--                    }
--                }
--            }
--
--          if ((((elf_symbol_type *) symbol)->version & VERSYM_HIDDEN) == 0)
++          if (!hidden)
              fprintf (file, "  %-11s", version_string);
            else
              {
index 55bc299febb8b3a31237ad7e1c6e98e32260b383,4d391e13c7d7fa504fc3b996582efd1f6bcbc993..e932d6fc4c219584d69c292246c215c45b5d48b4
@@@ -5094,22 -5068,7 +5094,20 @@@ elf_i386_add_symbol_hook (bfd * abfd
  #define elf_backend_plt_sym_val                     elf_i386_plt_sym_val
  #define elf_backend_hash_symbol                     elf_i386_hash_symbol
  #define elf_backend_add_symbol_hook           elf_i386_add_symbol_hook
- #undef        elf_backend_post_process_headers
- #define       elf_backend_post_process_headers        _bfd_elf_set_osabi
  
 +#define elf_backend_section_from_bfd_section \
 +  _bfd_elf_sharable_section_from_bfd_section
 +#define elf_backend_symbol_processing \
 +  _bfd_elf_sharable_symbol_processing
 +#define elf_backend_common_section_index \
 +  _bfd_elf_sharable_common_section_index
 +#define elf_backend_common_section \
 +  _bfd_elf_sharable_common_section
 +#define elf_backend_common_definition \
 +  _bfd_elf_sharable_common_definition
 +#define elf_backend_merge_symbol \
 +  _bfd_elf_sharable_merge_symbol
 +
  #include "elf32-target.h"
  
  /* FreeBSD support.  */
Simple merge
Simple merge
diff --cc bfd/elfcode.h
Simple merge
diff --cc bfd/elflink.c
Simple merge
Simple merge
diff --cc bfd/opncls.c
Simple merge
diff --cc bfd/plugin.c
index 9d169a447c9b8eb15a0e2b68cd6e01675970dcb3,3306607fe5c5e43510ede9372daec1ed38656e45..867e166a23feb7a91a3c26bb89b9204f5785ea7f
@@@ -130,139 -130,6 +130,139 @@@ register_claim_file (ld_plugin_claim_fi
    return LDPS_OK;
  }
  
-       s = bfd_alloc (abfd, sizeof (asymbol)); 
 +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,
Simple merge
index 0098ae7e7ad075c0b12b7971b6640758bda6c81c,0098ae7e7ad075c0b12b7971b6640758bda6c81c..af7bfce4d272f2ff513e15a5c697a3b43f8a34c4
@@@ -792,7 -792,7 +792,8 @@@ objdump_print_symname (bfd *abfd, struc
                       asymbol *sym)
  {
    char *alloc;
--  const char *name;
++  const char *name, *version_string = NULL;
++  bfd_boolean hidden = FALSE;
  
    alloc = NULL;
    name = bfd_asymbol_name (sym);
        name = alloc;
      }
  
++  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
++    version_string = bfd_elf_get_symbol_version_string (abfd, sym,
++                                                      &hidden);
++
++  if (bfd_is_und_section (bfd_get_section (sym)))
++    hidden = TRUE;
++
    if (inf != NULL)
--    (*inf->fprintf_func) (inf->stream, "%s", name);
++    {
++      (*inf->fprintf_func) (inf->stream, "%s", name);
++      if (version_string && *version_string != '\0')
++      (*inf->fprintf_func) (inf->stream, hidden ? "@%s" : "@@%s",
++                            version_string);
++    }
    else
--    printf ("%s", name);
++    {
++      printf ("%s", name);
++      if (version_string && *version_string != '\0')
++      printf (hidden ? "@%s" : "@@%s", version_string);
++    }
  
    if (alloc != NULL)
      free (alloc);
index 2138160672053ff51a2d535e1de68ce7e5b6196b,7d228d6b5a92fae970a56ef3b83292bdad20e851..19ff6f2537ec0e3848f5fd7e2921e5bbe769e9e5
@@@ -270,6 -271,6 +271,20 @@@ typedef enum print_mod
  }
  print_mode;
  
++/* Versioned symbol info.  */
++enum versioned_symbol_info
++{
++  symbol_undefined,
++  symbol_hidden,
++  symbol_public
++};
++
++static const char *get_symbol_version_string
++  (FILE *file, int is_dynsym, const char *strtab,
++   unsigned long int strtab_size, unsigned int si,
++   Elf_Internal_Sym *psym, enum versioned_symbol_info *sym_info,
++   unsigned short *vna_other);
++
  #define UNKNOWN -1
  
  #define SECTION_NAME(X)                                               \
@@@ -924,7 -926,7 +940,8 @@@ dump_relocations (FILE * file
                  unsigned long nsyms,
                  char * strtab,
                  unsigned long strtablen,
--                int is_rela)
++                int is_rela,
++                int is_dynsym)
  {
    unsigned int i;
    Elf_Internal_Rela * rels;
          else
            {
              Elf_Internal_Sym * psym;
++            const char * version_string;
++            enum versioned_symbol_info sym_info;
++            unsigned short vna_other;
  
              psym = symtab + symtab_index;
  
++            version_string
++              = get_symbol_version_string (file, is_dynsym,
++                                           strtab, strtablen,
++                                           symtab_index,
++                                           psym,
++                                           &sym_info,
++                                           &vna_other);
++
              printf (" ");
  
              if (ELF_ST_TYPE (psym->st_info) == STT_GNU_IFUNC)
                    name = strtab + psym->st_name;
  
                  len = print_symbol (width, name);
++                if (version_string)
++                  printf (sym_info == symbol_public ? "@@%s" : "@%s", 
++                          version_string);
                  printf ("()%-*s", len <= width ? (width + 1) - len : 1, " ");
                }
              else
              else if (psym->st_name >= strtablen)
                printf (_("<corrupt string table index: %3ld>"), psym->st_name);
              else
--              print_symbol (22, strtab + psym->st_name);
++              {
++                print_symbol (22, strtab + psym->st_name);
++                if (version_string)
++                  printf (sym_info == symbol_public ? "@@%s" : "@%s", 
++                          version_string);
++              }
  
              if (is_rela)
                {
@@@ -5713,7 -5920,7 +5958,8 @@@ process_relocs (FILE * file
                                offset_from_vma (file, rel_offset, rel_size),
                                rel_size,
                                dynamic_symbols, num_dynamic_syms,
--                              dynamic_strings, dynamic_strings_length, is_rela);
++                              dynamic_strings, dynamic_strings_length,
++                              is_rela, 1);
            }
        }
  
                    }
  
                  dump_relocations (file, rel_offset, rel_size,
--                                  symtab, nsyms, strtab, strtablen, is_rela);
++                                  symtab, nsyms, strtab, strtablen,
++                                  is_rela,
++                                  symsec->sh_type == SHT_DYNSYM);
                  if (strtab)
                    free (strtab);
                  free (symtab);
                }
              else
                dump_relocations (file, rel_offset, rel_size,
--                                NULL, 0, NULL, 0, is_rela);
++                                NULL, 0, NULL, 0, is_rela, 0);
  
              found = 1;
            }
@@@ -9377,6 -9581,6 +9625,181 @@@ print_dynamic_symbol (bfd_vma si, unsig
    putchar ('\n');
  }
  
++static const char *
++get_symbol_version_string (FILE *file, int is_dynsym,
++                         const char *strtab,
++                         unsigned long int strtab_size,
++                         unsigned int si, Elf_Internal_Sym *psym,
++                         enum versioned_symbol_info *sym_info,
++                         unsigned short *vna_other)
++{
++  const char *version_string = NULL;
++
++  if (is_dynsym
++      && version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
++    {
++      unsigned char data[2];
++      unsigned short vers_data;
++      unsigned long offset;
++      int is_nobits;
++      int check_def;
++
++      offset = offset_from_vma
++      (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
++       sizeof data + si * sizeof (vers_data));
++
++      if (get_data (&data, file, offset + si * sizeof (vers_data),
++                  sizeof (data), 1, _("version data")) == NULL)
++      return NULL;
++
++      vers_data = byte_get (data, 2);
++
++      is_nobits = (psym->st_shndx < elf_header.e_shnum
++                 && section_headers[psym->st_shndx].sh_type
++                 == SHT_NOBITS);
++
++      check_def = (psym->st_shndx != SHN_UNDEF);
++
++      if ((vers_data & VERSYM_HIDDEN) || vers_data > 1)
++      {
++        if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
++            && (is_nobits || ! check_def))
++          {
++            Elf_External_Verneed evn;
++            Elf_Internal_Verneed ivn;
++            Elf_Internal_Vernaux ivna;
++
++            /* We must test both.  */
++            offset = offset_from_vma
++              (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
++               sizeof evn);
++
++            do
++              {
++                unsigned long vna_off;
++
++                if (get_data (&evn, file, offset, sizeof (evn), 1,
++                              _("version need")) == NULL)
++                  {
++                    ivna.vna_next = 0;
++                    ivna.vna_other = 0;
++                    ivna.vna_name = 0;
++                    break;
++                  }
++
++                ivn.vn_aux  = BYTE_GET (evn.vn_aux);
++                ivn.vn_next = BYTE_GET (evn.vn_next);
++
++                vna_off = offset + ivn.vn_aux;
++
++                do
++                  {
++                    Elf_External_Vernaux evna;
++
++                    if (get_data (&evna, file, vna_off,
++                                  sizeof (evna), 1,
++                                  _("version need aux (3)")) == NULL)
++                      {
++                        ivna.vna_next = 0;
++                        ivna.vna_other = 0;
++                        ivna.vna_name = 0;
++                      }
++                    else
++                      {
++                        ivna.vna_other = BYTE_GET (evna.vna_other);
++                        ivna.vna_next  = BYTE_GET (evna.vna_next);
++                        ivna.vna_name  = BYTE_GET (evna.vna_name);
++                      }
++
++                    vna_off += ivna.vna_next;
++                  }
++                while (ivna.vna_other != vers_data
++                       && ivna.vna_next != 0);
++
++                if (ivna.vna_other == vers_data)
++                  break;
++
++                offset += ivn.vn_next;
++              }
++            while (ivn.vn_next != 0);
++
++            if (ivna.vna_other == vers_data)
++              {
++                *sym_info = symbol_undefined;
++                *vna_other = ivna.vna_other;
++                version_string = (ivna.vna_name < strtab_size
++                                  ? strtab + ivna.vna_name
++                                  : _("<corrupt>"));
++                check_def = 0;
++              }
++            else if (! is_nobits)
++              error (_("bad dynamic symbol\n"));
++            else
++              check_def = 1;
++          }
++
++        if (check_def)
++          {
++            if (vers_data != 0x8001
++                && version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
++              {
++                Elf_Internal_Verdef ivd;
++                Elf_Internal_Verdaux ivda;
++                Elf_External_Verdaux evda;
++                unsigned long off;
++
++                off = offset_from_vma
++                  (file,
++                   version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
++                   sizeof (Elf_External_Verdef));
++
++                do
++                  {
++                    Elf_External_Verdef evd;
++
++                    if (get_data (&evd, file, off, sizeof (evd),
++                                  1, _("version def")) == NULL)
++                      {
++                        ivd.vd_ndx = 0;
++                        ivd.vd_aux = 0;
++                        ivd.vd_next = 0;
++                      }
++                    else
++                      {
++                        ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
++                        ivd.vd_aux = BYTE_GET (evd.vd_aux);
++                        ivd.vd_next = BYTE_GET (evd.vd_next);
++                      }
++
++                    off += ivd.vd_next;
++                  }
++                while (ivd.vd_ndx != (vers_data & VERSYM_VERSION)
++                       && ivd.vd_next != 0);
++
++                off -= ivd.vd_next;
++                off += ivd.vd_aux;
++
++                if (get_data (&evda, file, off, sizeof (evda),
++                              1, _("version def aux")) == NULL)
++                  return version_string;
++
++                ivda.vda_name = BYTE_GET (evda.vda_name);
++
++                if (psym->st_name != ivda.vda_name)
++                  {
++                    *sym_info = ((vers_data & VERSYM_HIDDEN) != 0
++                                 ? symbol_hidden : symbol_public);
++                    version_string = (ivda.vda_name < strtab_size
++                                      ? strtab + ivda.vda_name
++                                      : _("<corrupt>"));
++                  }
++              }
++          }
++      }
++    }
++  return version_string;
++}
++
  /* Dump the symbol table.  */
  static int
  process_symbol_table (FILE * file)
  
          for (si = 0, psym = symtab; si < num_syms; si++, psym++)
            {
++            const char *version_string;
++            enum versioned_symbol_info sym_info;
++            unsigned short vna_other;
++
              printf ("%6d: ", si);
              print_vma (psym->st_value, LONG_HEX);
              putchar (' ');
              print_symbol (25, psym->st_name < strtab_size
                            ? strtab + psym->st_name : _("<corrupt>"));
  
--            if (section->sh_type == SHT_DYNSYM
--                && version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
++            version_string
++              = get_symbol_version_string (file,
++                                           section->sh_type == SHT_DYNSYM,
++                                           strtab, strtab_size, si,
++                                           psym, &sym_info, &vna_other);
++            if (version_string)
                {
--                unsigned char data[2];
--                unsigned short vers_data;
--                unsigned long offset;
--                int is_nobits;
--                int check_def;
--
--                offset = offset_from_vma
--                  (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
--                   sizeof data + si * sizeof (vers_data));
--
--                if (get_data (&data, file, offset + si * sizeof (vers_data),
--                              sizeof (data), 1, _("version data")) == NULL)
--                  break;
--
--                vers_data = byte_get (data, 2);
--
--                is_nobits = (psym->st_shndx < elf_header.e_shnum
--                             && section_headers[psym->st_shndx].sh_type
--                                == SHT_NOBITS);
--
--                check_def = (psym->st_shndx != SHN_UNDEF);
--
--                if ((vers_data & VERSYM_HIDDEN) || vers_data > 1)
--                  {
--                    if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
--                        && (is_nobits || ! check_def))
--                      {
--                        Elf_External_Verneed evn;
--                        Elf_Internal_Verneed ivn;
--                        Elf_Internal_Vernaux ivna;
--
--                        /* We must test both.  */
--                        offset = offset_from_vma
--                          (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
--                           sizeof evn);
--
--                        do
--                          {
--                            unsigned long vna_off;
--
--                            if (get_data (&evn, file, offset, sizeof (evn), 1,
--                                          _("version need")) == NULL)
--                              {
--                                ivna.vna_next = 0;
--                                ivna.vna_other = 0;
--                                ivna.vna_name = 0;
--                                break;
--                              }
--
--                            ivn.vn_aux  = BYTE_GET (evn.vn_aux);
--                            ivn.vn_next = BYTE_GET (evn.vn_next);
--
--                            vna_off = offset + ivn.vn_aux;
--
--                            do
--                              {
--                                Elf_External_Vernaux evna;
--
--                                if (get_data (&evna, file, vna_off,
--                                              sizeof (evna), 1,
--                                              _("version need aux (3)")) == NULL)
--                                  {
--                                    ivna.vna_next = 0;
--                                    ivna.vna_other = 0;
--                                    ivna.vna_name = 0;
--                                  }
--                                else
--                                  {
--                                    ivna.vna_other = BYTE_GET (evna.vna_other);
--                                    ivna.vna_next  = BYTE_GET (evna.vna_next);
--                                    ivna.vna_name  = BYTE_GET (evna.vna_name);
--                                  }
--
--                                vna_off += ivna.vna_next;
--                              }
--                            while (ivna.vna_other != vers_data
--                                   && ivna.vna_next != 0);
--
--                            if (ivna.vna_other == vers_data)
--                              break;
--
--                            offset += ivn.vn_next;
--                          }
--                        while (ivn.vn_next != 0);
--
--                        if (ivna.vna_other == vers_data)
--                          {
--                            printf ("@%s (%d)",
--                                    ivna.vna_name < strtab_size
--                                    ? strtab + ivna.vna_name : _("<corrupt>"),
--                                    ivna.vna_other);
--                            check_def = 0;
--                          }
--                        else if (! is_nobits)
--                          error (_("bad dynamic symbol\n"));
--                        else
--                          check_def = 1;
--                      }
--
--                    if (check_def)
--                      {
--                        if (vers_data != 0x8001
--                            && version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
--                          {
--                            Elf_Internal_Verdef ivd;
--                            Elf_Internal_Verdaux ivda;
--                            Elf_External_Verdaux evda;
--                            unsigned long off;
--
--                            off = offset_from_vma
--                              (file,
--                               version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
--                               sizeof (Elf_External_Verdef));
--
--                            do
--                              {
--                                Elf_External_Verdef evd;
--
--                                if (get_data (&evd, file, off, sizeof (evd),
--                                              1, _("version def")) == NULL)
--                                  {
--                                    ivd.vd_ndx = 0;
--                                    ivd.vd_aux = 0;
--                                    ivd.vd_next = 0;
--                                  }
--                                else
--                                  {
--                                    ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
--                                    ivd.vd_aux = BYTE_GET (evd.vd_aux);
--                                    ivd.vd_next = BYTE_GET (evd.vd_next);
--                                  }
--
--                                off += ivd.vd_next;
--                              }
--                            while (ivd.vd_ndx != (vers_data & VERSYM_VERSION)
--                                   && ivd.vd_next != 0);
--
--                            off -= ivd.vd_next;
--                            off += ivd.vd_aux;
--
--                            if (get_data (&evda, file, off, sizeof (evda),
--                                          1, _("version def aux")) == NULL)
--                              break;
--
--                            ivda.vda_name = BYTE_GET (evda.vda_name);
--
--                            if (psym->st_name != ivda.vda_name)
--                              printf ((vers_data & VERSYM_HIDDEN)
--                                      ? "@%s" : "@@%s",
--                                      ivda.vda_name < strtab_size
--                                      ? strtab + ivda.vda_name : _("<corrupt>"));
--                          }
--                      }
--                  }
++                if (sym_info == symbol_undefined)
++                  printf ("@%s (%d)", version_string, vna_other);
++                else
++                  printf (sym_info == symbol_hidden ? "@%s" : "@@%s",
++                          version_string);
                }
  
              putchar ('\n');
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc ld/ld.texinfo
Simple merge
diff --cc ld/ldlang.c
index 5273dfc57cd275de3948154f5b72cab3ff507a74,9903f7003cf8e38ad6779e360eab400d09012a42..a04a11964ac013f2d90c862dc8f4a2b871271ba2
@@@ -71,9 -67,7 +71,10 @@@ static struct bfd_hash_table lang_defin
  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 struct asneeded_minfo *asneeded_list_head;
 +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 *);
@@@ -1236,18 -1223,16 +1237,17 @@@ lang_init (bfd_boolean object_only
  
    abs_output_section->bfd_section = bfd_abs_section_ptr;
  
-   /* The value "3" is ad-hoc, somewhat related to the expected number of
-      DEFINED expressions in a linker script.  For most default linker
-      scripts, there are none.  Why a hash table then?  Well, it's somewhat
-      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.  */
+   /* The value "13" is ad-hoc, somewhat related to the expected number of
+      assignments in a linker script.  */
 -  if (!bfd_hash_table_init_n (&lang_definedness_table,
 -                            lang_definedness_newfunc,
 -                            sizeof (struct lang_definedness_hash_entry),
 -                            13))
 +  if (!object_only
 +      && !bfd_hash_table_init_n (&lang_definedness_table,
 +                               lang_definedness_newfunc,
 +                               sizeof (struct lang_definedness_hash_entry),
-                                3))
++                               13))
      einfo (_("%P%F: can not create hash table: %E\n"));
+   asneeded_list_head = NULL;
+   asneeded_list_tail = &asneeded_list_head;
  }
  
  void
@@@ -8115,961 -8096,3 +8149,963 @@@ lang_ld_feature (char *str
        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;
 +}
 +
 +/* Get object-only input files.  */
 +
 +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);
-   const char *ofilename = NULL;
++
 +      /* 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;
-   ofilename = bfd_get_filename (obfd);
++  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;
 +    }
-       
++  /* To be used after bfd_close ().  */
++  ofilename = xstrdup (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"));
 +    }
 +
++  free (ofilename);
 +  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;
 +
 +  /* Get object-only input files.  */
 +  cmdline_get_object_only_input_files ();
 +
 +  /* Open 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 ();
-   /* Remove the temporary object-only file.  */ 
++
 +  ldwrite ();
 +
 +  lang_finish (TRUE);
 +
 +  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 --cc ld/ldlang.h
index 175445744777fe2a04f5ca77f0cf66cda7464f6a,7236c1cc20179611684401ef8da5b14fa3687e5f..ad3f255cfa585335d42fccf4fe5080cf49bdd645
@@@ -486,11 -513,12 +513,12 @@@ extern lang_statement_list_type file_ch
  extern lang_statement_list_type input_file_chain;
  
  extern int lang_statement_iteration;
+ extern struct asneeded_minfo **asneeded_list_tail;
  
  extern void lang_init
 -  (void);
 +  (bfd_boolean);
  extern void lang_finish
 -  (void);
 +  (bfd_boolean);
  extern lang_memory_region_type * lang_memory_region_lookup
    (const char * const, bfd_boolean);
  extern void lang_memory_region_alias
diff --cc ld/ldmain.c
Simple merge
index aea3ad69d98fcadf27d7ed36343bcbac48d3a386,aea3ad69d98fcadf27d7ed36343bcbac48d3a386..48071068f452775fde96a4ffce398804a23b9069
  #...
  Relocation section '.rela.dyn' at offset 0x... contains 1 entries:
   Offset +Info +Type +Sym.Value +Sym. Name \+ Addend
--.* R_CRIS_COPY .* __expobj2 \+ 0
++.* R_CRIS_COPY .* __expobj2@TST3 \+ 0
  
  Relocation section '.rela.plt' at offset 0x... contains 1 entries:
   Offset +Info +Type +Sym.Value +Sym. Name \+ Addend
--.* R_CRIS_JUMP_SLOT .* expfn2 \+ 0
++.* R_CRIS_JUMP_SLOT .* expfn2@TST3 \+ 0
  
  The decoding of unwind sections for machine type Axis Communications 32-bit embedded processor is not currently supported.
  
index 79de29140687fdb16a3e1f19e862e93eee472b2f,79de29140687fdb16a3e1f19e862e93eee472b2f..aed0f39eb900d257bd1394eda6c8e5a5d2b13471
@@@ -17,7 -17,7 +17,7 @@@
  #...
  Relocation section '.rela.dyn' at offset 0x... contains 1 entries:
  #...
--.* R_CRIS_COPY .* __expobj2 \+ 0
++.* R_CRIS_COPY .* __expobj2@TST3 \+ 0
  
  The decoding of unwind sections for machine type Axis Communications 32-bit embedded processor is not currently supported.
  
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..35e855554efd746c48fa98a2403048178e36c394
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++void
++sd_get_seats (void)
++{
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d677f3765204c875f598d4dd607546c9ab4f985c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++LIBSYSTEMD_209 {
++global:
++        sd_get_seats;
++};
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..94a0f300fef1ea8ff464496ce491fd36cd88d3f1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++void sd_get_seats (void);
++void call_sd_get_seats (void)
++{
++  sd_get_seats ();
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..6fb54c11fc11767244d3bd50c44756b403be5cf9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,3 @@@
++#...
++.* sd_get_seats@LIBSYSTEMD_209
++#pass
index 3162547792dc039736648c5a20a6d236eb0a7d1c,bbfd464574e3eb77f2c3a798db1dbb2f6dac1632..da5f8e455882ea4ea8ffde4be5f0ee5739791a5a
@@@ -218,6 -218,12 +218,21 @@@ set build_tests 
    {"Build needed2"
     "tmpdir/libneeded2c.o -Wl,--as-needed tmpdir/libneeded2a.so tmpdir/libneeded2b.so" ""
     {dummy.c} {} "needed2"}
+   {"Build libpr2404a.so"
+    "-shared" "-fPIC"
+    {pr2404a.c} {} "libpr2404a.so"}
+   {"Build libpr2404b.a"
+    "" ""
+    {pr2404b.c} {} "libpr2404b.a"}
++  {"Build libpr16496a.so"
++   "-shared -Wl,--version-script=pr16496a.map" "-fPIC"
++   {pr16496a.c} {} "libpr16496a.so"}
++  {"Build libpr16496b.a"
++   "" "-fPIC"
++   {pr16496b.c} {} "libpr16496b.a"}
++  {"Build libpr16496b.so"
++   "-shared tmpdir/pr16496b.o tmpdir/libpr16496a.so" ""
++   {dummy.c} {{objdump {-R} pr16496b.od}} "libpr16496b.so"}
  }
  
  run_cc_link_tests $build_tests
index fb464f9f7a68f0c72fe3aa9f2d4206f775050583,fb464f9f7a68f0c72fe3aa9f2d4206f775050583..2360447b79cd031429dbc344bcd5e6a03db1aaed
@@@ -1,7 -1,7 +1,7 @@@
  Relocation section .*
  # Ensure there is a dynamic relocation against x
  #...
--[0-9a-f]+ +[0-9a-f]+ R_.* +_?x(| \+ 0)
++[0-9a-f]+ +[0-9a-f]+ R_.* +_?x@VERS.0(| \+ 0)
  #...
  Symbol table '.dynsym' contains [0-9]+ entries:
  # And ensure the dynamic symbol table contains at least x@VERS.0
Simple merge
index 3e86e0620cd2fc4cb94e456575f0227bc151e84f,0000000000000000000000000000000000000000..a5a80e08176f96a123eaa4dca8c14d59a13770b6
mode 100644,000000..100644
--- /dev/null
@@@ -1,47 -1,0 +1,47 @@@
-   
 +#define ASMNAME(cname)  ASMNAME2 (__USER_LABEL_PREFIX__, cname)
 +#define ASMNAME2(prefix, cname) STRING (prefix) cname
 +#define STRING(x)    #x
 +
 +typedef __SIZE_TYPE__ size_t;
 +extern void abort (void);
 +extern void *memcpy (void *, const void *, size_t)
 +  __asm (ASMNAME ("my_memcpy"));
 +extern void bcopy (const void *, void *, size_t)
 +  __asm (ASMNAME ("my_bcopy"));
 +extern void *memset (void *, int, size_t)
 +  __asm (ASMNAME ("my_memset"));
 +extern void bzero (void *, size_t)
 +  __asm (ASMNAME ("my_bzero"));
 +extern int memcmp (const void *, const void *, size_t);
 +
 +struct A { char c[32]; } a = { "foobar" };
 +char x[64] = "foobar", y[64];
 +int i = 39, j = 6, k = 4;
 +
 +extern int inside_main;
 +
 +void
 +main_test (void)
 +{
 +  struct A b = a;
 +  struct A c = { { 'x' } };
 +
 +  inside_main = 1;
++
 +  if (memcmp (b.c, x, 32) || c.c[0] != 'x' || memcmp (c.c + 1, x + 32, 31))
 +    abort ();
 +  if (__builtin_memcpy (y, x, i) != y || memcmp (x, y, 64))
 +    abort ();
 +  if (memcpy (y + 6, x, j) != y + 6
 +      || memcmp (x, y, 6) || memcmp (x, y + 6, 58))
 +    abort ();
 +  if (__builtin_memset (y + 2, 'X', k) != y + 2
 +      || memcmp (y, "foXXXXfoobar", 13))
 +    abort ();
 +  bcopy (y + 1, y + 2, 6);
 +  if (memcmp (y, "fooXXXXfobar", 13))
 +    abort ();
 +  __builtin_bzero (y + 4, 2);
 +  if (memcmp (y, "fooX\0\0Xfobar", 13))
 +    abort ();
 +}