Merge remote-tracking branch 'origin/hjl/linux/master' into hjl/linux/applied
diff --git a/.gitattributes b/.gitattributes
index 06d51d2..f7bb8f6 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -18,3 +18,12 @@
# file gets renamed again ...
ChangeLog merge=merge-changelog
+
+.cvsignore export-ignore
+.gitattributes export-ignore
+.gitignore export-ignore
+gdb export-ignore
+libdecnumber export-ignore
+readline export-ignore
+sim export-ignore
+include/gdb -export-ignore
diff --git a/ChangeLog.linux b/ChangeLog.linux
index 6bf4e0a..dbdf2ec 100644
--- a/ChangeLog.linux
+++ b/ChangeLog.linux
@@ -1,3 +1,11 @@
+2013-11-09 H.J. Lu <hjl.tools@gmail.com>
+
+ * .gitattributes (include/gdb): Unset export-ignore.
+
+2013-11-08 H.J. Lu <hjl.tools@gmail.com>
+
+ * .gitattributes: New file.
+
2013-11-04 H.J. Lu <hjl.tools@gmail.com>
* bfd/configure.in (ACX_PKGVERSION): Pass "Linux/GNU Binutils".
diff --git a/ChangeLog.lto-mixed b/ChangeLog.lto-mixed
new file mode 100644
index 0000000..bdbabea
--- /dev/null
+++ b/ChangeLog.lto-mixed
@@ -0,0 +1,317 @@
+bfd/
+
+2014-03-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ * format.c (bfd_check_format_matches): Don't check the plugin
+ target twice.
+
+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-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_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/
+
+2014-03-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld-plugin/lto.exp: Add test for nm on mixed LTO/non-LTO object.
+
+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.
diff --git a/ChangeLog.pr12639 b/ChangeLog.pr12639
new file mode 100644
index 0000000..e7a41f4
--- /dev/null
+++ b/ChangeLog.pr12639
@@ -0,0 +1,15 @@
+bfd/
+
+2013-11-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR binutils/12639
+ * elfcode.h (elf_slurp_symbol_table): Check corrupted global
+ symbols.
+
+binutils/
+
+2013-11-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR binutils/12639
+ * readelf.c (process_symbol_table): Detect corrupted symbol
+ table.
diff --git a/ChangeLog.pr16496 b/ChangeLog.pr16496
new file mode 100644
index 0000000..ef188ab
--- /dev/null
+++ b/ChangeLog.pr16496
@@ -0,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 --git a/ChangeLog.secondary b/ChangeLog.secondary
new file mode 100644
index 0000000..f3bb59d
--- /dev/null
+++ b/ChangeLog.secondary
@@ -0,0 +1,221 @@
+bfd/
+
+2012-09-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elf-bfd.h (_bfd_elf_merge_symbol): Add a boolean argument to
+ indicate if the old definition is secondary.
+
+ * elf32-sh-symbian.c (sh_symbian_relocate_section): Pass FALSE
+ to _bfd_elf_merge_symbol.
+
+ * elflink.c (_bfd_elf_merge_symbol): Add a boolean argument to
+ indicate if the old definition is secondary. Set OLDSECONADRY if
+ it isn't TRUE. Treat old secondary symbol as weak.
+ (_bfd_elf_add_default_symbol): Add a boolean argument to if the
+ old definition is secondary.
+ (elf_link_add_object_symbols): Pass oldsecondary to
+ _bfd_elf_merge_symbol and _bfd_elf_add_default_symbol.
+
+2012-09-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elflink.c (is_global_data_symbol_definition): Renamed to ...
+ (is_global_symbol_definition): This. If secondary symbols are
+ ignored, count function and common symbols as global definition.
+ (elf_link_is_defined_archive_symbol): Updated.
+
+2012-09-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elflink.c (is_global_data_symbol_definition): Add an argument
+ to ignore secondary symbols.
+ (elf_link_is_defined_archive_symbol): Likewise and pass it to
+ is_global_data_symbol_definition.
+ (elf_link_add_archive_symbols): Ignore another secondary
+ definition.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elflink.c (elf_link_output_extsym): Generate STB_SECONDARY
+ symbols if needed.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elf.c (swap_out_syms): Output undefined secondary symbols
+ as weak.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elflink.c (_bfd_elf_merge_symbol): Allow overriding secondary
+ symbols.
+ (elf_link_add_object_symbols): Treat secondary symbols as weak
+ symbols. Allow overriding secondary symbols.
+ (elf_link_add_archive_symbols): Keep searching if a definition
+ is secondary.
+ (elf_link_output_extsym): Treat secondary symbols as weak
+ symbols.
+ * linker.c (_bfd_generic_link_add_one_symbol): Treat secondary
+ symbol as weak symbol. Mark secondary symbol.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * archive.c (_bfd_compute_and_write_armap): Treat BSF_SECONDARY
+ symbol as global.
+ * elf32-mips.c (mips_elf_sym_is_global): Likewise.
+ * elfn32-mips.c (mips_elf_sym_is_global): Likewise.
+ * elf.c (sym_is_global): Likewise.
+ (swap_out_syms): Handle SECONDARY symbol.
+ * elf64-ia64-vms.c (elf64_vms_link_add_object_symbols): Likewise.
+ * elfcode.h (elf_slurp_symbol_table): Likewise.
+ * elflink.c (elf_link_add_object_symbols): Likewise.
+
+ * syms.c (BSF_SECONDARY): New.
+ (bfd_print_symbol_vandf): Handle SECONDARY symbol.
+ (bfd_decode_symclass): Likewise.
+
+ * bfd-in2.h: Regenerated.
+
+binutils/
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * nm.c (filter_symbols): Treat BSF_SECONDARY symbol as global.
+
+ * readelf.c (get_symbol_binding): Handle STB_SECONDARY.
+
+gas/
+
+2012-09-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/obj-elf.c (obj_elf_weak): Don't set symbol weak on
+ secondary symbol.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/obj-elf.c (elf_frob_symbol): Handle secondary symbol
+ for .symver. Also remove the unused secondary symbol.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * symbols.c (S_IS_SECONDARY): New.
+ (S_SET_SECONDARY): Likewise.
+ (S_FORCE_RELOC): Handle BSF_SECONDARY like BSF_WEAK.
+ (S_SET_EXTERNAL): Likewise.
+ (S_CLEAR_EXTERNAL): Likewise.
+ (S_CLEAR_WEAKREFD): Likewise.
+ (S_SET_WEAK): Also clear BSF_SECONDARY.
+
+ * symbols.h (S_IS_SECONDARY): New.
+ (S_SET_SECONDARY): Likewise.
+
+ * config/obj-elf.c (obj_elf_secondary): New.
+ (elf_pseudo_table): Add "secondary".
+ (elf_frob_symbol): Also check secondary symbols.
+
+ * doc/as.texinfo: Document .secondary directive.
+
+gas/testsuite/
+
+2012-09-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gas/elf/common3.d: New file.
+ * gas/elf/common3.l: Likewise.
+ * gas/elf/common3.s: Likewise.
+ * gas/elf/common4.d: Likewise.
+ * gas/elf/common4.l: Likewise.
+ * gas/elf/common4.s: Likewise.
+ * gas/elf/secondary1.e: Likewise.
+ * gas/elf/secondary1.s: Likewise.
+ * gas/elf/secondary2.e: Likewise.
+ * gas/elf/secondary2.s: Likewise.
+
+ * gas/elf/elf.exp: Run common3, common4, secondary1 and
+ secondary2.
+
+ * gas/elf/type.s: Add .secondary tests.
+ * gas/elf/type.e: Updated.
+
+include/
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * bfdlink.h (bfd_link_info): Add emit_secondary.
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * bfdlink.h (bfd_link_hash_entry): Add secondary.
+
+include/elf/
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * common.h (STB_SECONDARY): New.
+
+ld/
+
+2012-09-08 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld.texinfo: Change "-z secondary" to "-z nosecondary".
+
+ * ldmain.c (main): Initialize link_info.emit_secondary to TRUE.
+
+ * emultempl/elf32.em (gld${EMULATION_NAME}_handle_option): Set
+ to link_info.emit_secondary to FALSE for "-z nosecondary".
+ (gld${EMULATION_NAME}_list_options): Replace "-z secondary" with
+ "-z nosecondary".
+
+2012-06-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld.texinfo: Document "-z secondary".
+
+ * emultempl/elf32.em (gld${EMULATION_NAME}_handle_option): Set
+ to link_info.emit_secondary to TRUE for "-z secondary".
+ (gld${EMULATION_NAME}_list_options): Add "-z secondary".
+
+ld/testsuite/
+
+2012-09-08 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld-elf/secondary.exp: Update -Wl,-z,secondary with
+ -Wl,-z,nosecondary.
+
+2012-09-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld-elf/library1.c: New file.
+ * ld-elf/library1.out: Likewise.
+ * ld-elf/library2.c: Likewise.
+ * ld-elf/library2.out: Likewise.
+ * ld-elf/library3.out: Likewise.
+ * ld-elf/library4.out: Likewise.
+ * ld-elf/library5a.c: Likewise.
+ * ld-elf/library5b.c: Likewise.
+ * ld-elf/library6a.c: Likewise.
+ * ld-elf/library6b.c: Likewise.
+ * ld-elf/library6c.c: Likewise.
+ * ld-elf/library7a.c: Likewise.
+ * ld-elf/library7b.c: Likewise.
+ * ld-elf/library7c.c: Likewise.
+ * ld-elf/secondary-foo.c: Likewise.
+ * ld-elf/secondary-main.c: Likewise.
+ * ld-elf/secondary.c: Likewise.
+ * ld-elf/secondary.exp: Likewise.
+ * ld-elf/secondary.rd: Likewise.
+ * ld-elf/secondary1.out: Likewise.
+ * ld-elf/secondary1.rd: Likewise.
+ * ld-elf/secondary2.rd: Likewise.
+ * ld-elf/secondary3.rd: Likewise.
+ * ld-elf/secondary3a.s: Likewise.
+ * ld-elf/secondary3b.s: Likewise.
+ * ld-elf/secondary4.rd: Likewise.
+ * ld-elf/secondary4.s: Likewise.
+ * ld-elf/secondary5.c: Likewise.
+ * ld-elf/secondary5.out: Likewise.
+ * ld-elf/secondary6.c: Likewise.
+ * ld-elf/secondary6.out: Likewise.
+ * ld-elf/secondary7.c: Likewise.
+ * ld-elf/secondary7.out: Likewise.
+ * ld-elf/library8.map: Likewise.
+ * ld-elf/library8a.c: Likewise.
+ * ld-elf/library8a.rd: Likewise.
+ * ld-elf/library8b.c: Likewise.
+ * ld-elf/library8b.rd: Likewise.
+ * ld-elf/library8c.c: Likewise.
+ * ld-elf/library8c.rd: Likewise.
diff --git a/ChangeLog.sharable b/ChangeLog.sharable
new file mode 100644
index 0000000..3ccf957
--- /dev/null
+++ b/ChangeLog.sharable
@@ -0,0 +1,140 @@
+bfd/
+
+2013-04-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elf-bfd.h (struct elf_backend_data <merge_symbol>): Add abfd,
+ newdyn and olddyn. Remove const from oldsec.
+ (_bfd_elf_sharable_merge_symbol): Updated.
+ * elf64-x86-64.c (elf_x86_64_merge_symbol): Likewise.
+ * elflink.c (_bfd_elf_merge_symbol): Update bed->merge_symbol
+ call.
+
+2009-12-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elf.c: Fix shadowed variable warnings.
+ * elf64-x86-64.c: Likewise.
+ * elflink.c: Likewise.
+
+2007-01-23 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elf-bfd.h (_bfd_elf_sharable_com_section): New.
+ (_bfd_elf_add_sharable_symbol): Likewise.
+ (_bfd_elf_sharable_section_from_bfd_section): Likewise.
+ (_bfd_elf_sharable_symbol_processing): Likewise.
+ (_bfd_elf_sharable_common_definition): Likewise.
+ (_bfd_elf_sharable_common_section_index): Likewise.
+ (_bfd_elf_sharable_common_section): Likewise.
+ (_bfd_elf_sharable_merge_symbol): Likewise.
+
+ * elf.c (special_sections_g): Add ".gnu.linkonce.shrb" and
+ ".gnu.linkonce.shrd".
+ (special_sections_s): Add ".sharable_bss" and ".sharable_data".
+ (get_program_header_size): Handle PT_GNU_SHR segment.
+ (_bfd_elf_map_sections_to_segments): Likewise.
+ (assign_file_positions_for_load_sections): Likewise.
+
+ * elf32-i386.c (elf_i386_link_hash_table): Add sdynsharablebss
+ and srelsharablebss fields.
+ (elf_i386_link_hash_table_create): Initialize sdynsharablebss
+ and srelsharablebss.
+ (elf_i386_create_dynamic_sections): Handle sdynsharablebss and
+ srelsharablebss.
+ (elf_i386_adjust_dynamic_symbol): Likewise.
+ (elf_i386_size_dynamic_sections): Likewise.
+ (elf_i386_finish_dynamic_symbol): Likewise.
+ (elf_backend_add_symbol_hook): Defined.
+ (elf_backend_section_from_bfd_section): Likewise.
+ (elf_backend_symbol_processing): Likewise.
+ (elf_backend_common_section_index): Likewise.
+ (elf_backend_common_section): Likewise.
+ (elf_backend_common_definition): Likewise.
+ (elf_backend_merge_symbol): Likewise.
+
+ * elf64-x86-64.c (elf64_x86_64_link_hash_table): Add
+ sdynsharablebss and srelsharablebss fields.
+ (elf64_x86_64_link_hash_table_create): Initialize sdynsharablebss
+ and srelsharablebss.
+ (elf64_x86_64_create_dynamic_sections): Handle sdynsharablebss
+ and srelsharablebss.
+ (elf64_x86_64_adjust_dynamic_symbol): Likewise.
+ (elf64_x86_64_size_dynamic_sections): Likewise.
+ (elf64_x86_64_finish_dynamic_symbol): Likewise.
+ (elf64_x86_64_add_symbol_hook): Handle sharable symbols.
+ (elf64_x86_64_elf_section_from_bfd_section): Likewise.
+ (elf64_x86_64_symbol_processing): Likewise.
+ (elf64_x86_64_merge_symbol): Likewise.
+ (elf64_x86_64_common_definition): Handle sharable sections.
+ (elf64_x86_64_common_section_index): Likewise.
+ (elf64_x86_64_common_section): Likewise.
+
+ * elflink.c (_bfd_elf_create_dynamic_sections): Handle
+ .dynsharablebss section.
+ (_bfd_elf_sharable_com_section): New.
+ (get_sharable_common_section): Likewise.
+ (_bfd_elf_add_sharable_symbol): Likewise.
+ (_bfd_elf_sharable_section_from_bfd_section): Likewise.
+ (_bfd_elf_sharable_symbol_processing): Likewise.
+ (_bfd_elf_sharable_common_definition): Likewise.
+ (_bfd_elf_sharable_common_section_index): Likewise.
+ (_bfd_elf_sharable_common_section): Likewise.
+ (_bfd_elf_sharable_merge_symbol): Likewise.
+
+ * elfnn-ia64.c (elfNN_ia64_add_symbol_hook): Handle sharable
+ symbols.
+ (elf_backend_add_symbol_hook): Defined.
+ (elf_backend_section_from_bfd_section): Likewise.
+ (elf_backend_symbol_processing): Likewise.
+ (elf_backend_common_section_index): Likewise.
+ (elf_backend_common_section): Likewise.
+ (elf_backend_common_definition): Likewise.
+ (elf_backend_merge_symbol): Likewise.
+
+binutils/
+
+2007-01-04 H.J. Lu <hongjiu.lu@intel.com>
+
+ * readelf.c (dump_relocations): Handle sharable sections.
+ (get_segment_type): Handle sharable segment.
+ (get_symbol_index_type): Handle sharable sections.
+
+gas/
+
+2007-01-04 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/obj-elf.c (obj_elf_sharable_common): New.
+ (elf_pseudo_table): Add "sharable_common".
+ (obj_elf_change_section): Handle sharable sections.
+
+include/
+
+2007-01-23 H.J. Lu <hongjiu.lu@intel.com>
+
+ * bfdlink.h (bfd_link_info): Add sharable_sections.
+
+include/elf/
+
+2007-01-04 H.J. Lu <hongjiu.lu@intel.com>
+
+ * common.h (PT_GNU_SHR): New.
+ (SHF_GNU_SHARABLE): Likewise.
+ (SHN_GNU_SHARABLE_COMMON): Likewise.
+
+ld/
+
+2011-01-08 H.J. Lu <hongjiu.lu@intel.com>
+
+ * emulparams/elf32_x86_64.sh (SHARABLE_SECTIONS): Set to yes.
+
+2007-01-04 H.J. Lu <hongjiu.lu@intel.com>
+
+ * emulparams/elf64_ia64.sh (SHARABLE_SECTIONS): Set to yes.
+ * emulparams/elf_i386.sh (SHARABLE_SECTIONS): Likewise.
+ * emulparams/elf_x86_64.sh (SHARABLE_SECTIONS): Likewise.
+
+ * emultempl/elf32.em (gld${EMULATION_NAME}_before_parse): Set
+ link_info.sharable_sections based on $SHARABLE_SECTIONS.
+ (gld${EMULATION_NAME}_place_orphan): Don't allow orphaned
+ sharable sections.
+
+ * ldmain.c (main): Initialize link_info.sharable_sections.
+ * scripttempl/elf.sc: Support sharable sections.
diff --git a/bfd/archive.c b/bfd/archive.c
index 40a3395..0d80fc5 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -2337,6 +2337,7 @@
if (((flags & (BSF_GLOBAL
| BSF_WEAK
+ | BSF_SECONDARY
| BSF_INDIRECT
| BSF_GNU_UNIQUE)) != 0
|| bfd_is_com_section (sec))
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index a40a14a..1e81dd3 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1083,6 +1083,9 @@
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. */
@@ -1636,6 +1639,9 @@
#define BFD_COM_SECTION_NAME "*COM*"
#define BFD_IND_SECTION_NAME "*IND*"
+/* GNU object-only section name. */
+#define GNU_OBJECT_ONLY_SECTION_NAME ".gnu_object_only"
+
/* Pointer to the common section. */
#define bfd_com_section_ptr (&_bfd_std_section[0])
/* Pointer to the undefined section. */
@@ -6203,6 +6209,10 @@
with this name and type in use. BSF_OBJECT must also be set. */
#define BSF_GNU_UNIQUE (1 << 23)
+ /* A secondary global symbol, overridable without warnings by
+ a regular or weak global symbol of the same name. */
+#define BSF_SECONDARY (1 << 24)
+
flagword flags;
/* A pointer to the section to which this symbol is
@@ -6274,6 +6284,14 @@
both_direction = 3
};
+enum bfd_lto_object_type
+ {
+ lto_non_object,
+ lto_non_ir_object,
+ lto_ir_object,
+ lto_mixed_object
+ };
+
struct bfd
{
/* The filename the application opened the BFD with. */
@@ -6430,6 +6448,9 @@
/* Set if this is the linker output BFD. */
unsigned int is_linker_output : 1;
+ /* LTO object type. */
+ unsigned int lto_type : 2;
+
/* Currently my_archive is tested before adding origin to
anything. I believe that this can become always an add of
origin, with origin set to 0 for non archive files. */
@@ -6451,6 +6472,9 @@
/* 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;
@@ -6752,6 +6776,8 @@
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 --git a/bfd/bfd.c b/bfd/bfd.c
index 8b60911..537433c 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -44,6 +44,14 @@
. both_direction = 3
. };
.
+.enum bfd_lto_object_type
+. {
+. lto_non_object,
+. lto_non_ir_object,
+. lto_ir_object,
+. lto_mixed_object
+. };
+.
.struct bfd
.{
. {* The filename the application opened the BFD with. *}
@@ -200,6 +208,9 @@
. {* Set if this is the linker output BFD. *}
. unsigned int is_linker_output : 1;
.
+. {* LTO object type. *}
+. unsigned int lto_type : 2;
+.
. {* Currently my_archive is tested before adding origin to
. anything. I believe that this can become always an add of
. origin, with origin set to 0 for non archive files. *}
@@ -221,6 +232,9 @@
. {* 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;
.
@@ -1923,3 +1937,36 @@
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 --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index dc343ec..a406a29 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1209,8 +1209,9 @@
/* Return TRUE if we can merge 2 definitions. */
bfd_boolean (*merge_symbol) (struct elf_link_hash_entry *,
const Elf_Internal_Sym *, asection **,
+ bfd_boolean, bfd_boolean, bfd *,
bfd_boolean, bfd_boolean,
- bfd *, const asection *);
+ bfd *, asection *);
/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
bfd_boolean (*elf_hash_symbol) (struct elf_link_hash_entry *);
@@ -1770,6 +1771,8 @@
(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);
@@ -2145,6 +2148,24 @@
(bfd *, struct bfd_link_info *);
extern bfd_boolean _bfd_elf_add_dynamic_entry
(struct bfd_link_info *, bfd_vma, bfd_vma);
+extern asection _bfd_elf_sharable_com_section;
+extern bfd_boolean _bfd_elf_add_sharable_symbol
+ (bfd *, struct bfd_link_info *, Elf_Internal_Sym *, const char **,
+ flagword *, asection **, bfd_vma *);
+extern bfd_boolean _bfd_elf_sharable_section_from_bfd_section
+ (bfd *, asection *, int *);
+extern void _bfd_elf_sharable_symbol_processing
+ (bfd *, asymbol *);
+extern bfd_boolean _bfd_elf_sharable_common_definition
+ (Elf_Internal_Sym *);
+extern unsigned int _bfd_elf_sharable_common_section_index
+ (asection *);
+extern asection *_bfd_elf_sharable_common_section
+ (asection *);
+extern bfd_boolean _bfd_elf_sharable_merge_symbol
+ (struct elf_link_hash_entry *, const Elf_Internal_Sym *,
+ asection **, bfd_boolean, bfd_boolean, bfd *,
+ bfd_boolean, bfd_boolean, bfd *, asection *);
extern bfd_boolean bfd_elf_link_record_dynamic_symbol
(struct bfd_link_info *, struct elf_link_hash_entry *);
diff --git a/bfd/elf.c b/bfd/elf.c
index a772db0..4d1998e 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1396,6 +1396,53 @@
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 +1469,8 @@
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*)";
@@ -1447,45 +1496,12 @@
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
{
@@ -2100,12 +2116,15 @@
{ 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 },
{ STRING_COMMA_LEN (".gnu.liblist"), 0, SHT_GNU_LIBLIST, SHF_ALLOC },
{ STRING_COMMA_LEN (".gnu.conflict"), 0, SHT_RELA, SHF_ALLOC },
{ STRING_COMMA_LEN (".gnu.hash"), 0, SHT_GNU_HASH, SHF_ALLOC },
+ { STRING_COMMA_LEN (".gnu.linkonce.shrb"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_GNU_SHARABLE},
+ { STRING_COMMA_LEN (".gnu.linkonce.shrd"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_GNU_SHARABLE},
{ NULL, 0, 0, 0, 0 }
};
@@ -2160,6 +2179,8 @@
/* See struct bfd_elf_special_section declaration for the semantics of
this special case where .prefix_length != strlen (.prefix). */
{ ".stabstr", 5, 3, SHT_STRTAB, 0 },
+ { STRING_COMMA_LEN (".sharable_bss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_GNU_SHARABLE},
+ { STRING_COMMA_LEN (".sharable_data"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_GNU_SHARABLE},
{ NULL, 0, 0, 0, 0 }
};
@@ -3259,7 +3280,10 @@
if (bed->elf_backend_sym_is_global)
return (*bed->elf_backend_sym_is_global) (abfd, sym);
- return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0
+ return ((sym->flags & (BSF_GLOBAL
+ | BSF_WEAK
+ | BSF_SECONDARY
+ | BSF_GNU_UNIQUE)) != 0
|| bfd_is_und_section (bfd_get_section (sym))
|| bfd_is_com_section (bfd_get_section (sym)));
}
@@ -3623,6 +3647,32 @@
}
}
+ /* Check to see if we need a PT_GNU_SHR segment for sharable data
+ sections. */
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ if ((elf_section_flags (s) & SHF_GNU_SHARABLE) != 0
+ && elf_section_type (s) == SHT_PROGBITS)
+ {
+ /* We need a PT_GNU_SHR segment. */
+ ++segs;
+ break;
+ }
+ }
+
+ /* Check to see if we need a PT_GNU_SHR segment for sharable bss
+ sections. */
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ if ((elf_section_flags (s) & SHF_GNU_SHARABLE) != 0
+ && elf_section_type (s) == SHT_NOBITS)
+ {
+ /* We need a PT_GNU_SHR segment. */
+ ++segs;
+ break;
+ }
+ }
+
/* Let the backend count up any program headers it might need. */
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_additional_program_headers)
@@ -3793,6 +3843,8 @@
bfd_boolean phdr_in_segment = TRUE;
bfd_boolean writable;
int tls_count = 0;
+ int sharable_data_count = 0, sharable_bss_count = 0;
+ asection *first_sharable_data = NULL, *first_sharable_bss = NULL;
asection *first_tls = NULL;
asection *dynsec, *eh_frame_hdr;
bfd_size_type amt;
@@ -4101,6 +4153,22 @@
first_tls = s;
tls_count++;
}
+ if (elf_section_flags (s) & SHF_GNU_SHARABLE)
+ {
+ if (elf_section_type (s) == SHT_PROGBITS)
+ {
+ if (! sharable_data_count)
+ first_sharable_data = s;
+ sharable_data_count++;
+ }
+ else
+ {
+ BFD_ASSERT (elf_section_type (s) == SHT_NOBITS);
+ if (! sharable_bss_count)
+ first_sharable_bss = s;
+ sharable_bss_count++;
+ }
+ }
}
/* If there are any SHF_TLS output sections, add PT_TLS segment. */
@@ -4148,6 +4216,60 @@
pm = &m->next;
}
+ /* If there are any output SHF_GNU_SHARABLE data sections, add a
+ PT_GNU_SHR segment. */
+ if (sharable_data_count > 0)
+ {
+ int j;
+
+ amt = sizeof (struct elf_segment_map);
+ amt += (sharable_data_count - 1) * sizeof (asection *);
+ m = bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_GNU_SHR;
+ m->count = sharable_data_count;
+ /* Mandated PF_R. */
+ m->p_flags = PF_R;
+ m->p_flags_valid = 1;
+ for (j = 0; j < sharable_data_count; ++j)
+ {
+ m->sections[j] = first_sharable_data;
+ first_sharable_data = first_sharable_data->next;
+ }
+
+ *pm = m;
+ pm = &m->next;
+ }
+
+ /* If there are any output SHF_GNU_SHARABLE bss sections, add a
+ PT_GNU_SHR segment. */
+ if (sharable_bss_count > 0)
+ {
+ int j;
+
+ amt = sizeof (struct elf_segment_map);
+ amt += (sharable_bss_count - 1) * sizeof (asection *);
+ m = bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_GNU_SHR;
+ m->count = sharable_bss_count;
+ /* Mandated PF_R. */
+ m->p_flags = PF_R;
+ m->p_flags_valid = 1;
+ for (j = 0; j < sharable_bss_count; ++j)
+ {
+ m->sections[j] = first_sharable_bss;
+ first_sharable_bss = first_sharable_bss->next;
+ }
+
+ *pm = m;
+ pm = &m->next;
+ }
+
/* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
segment. */
eh_frame_hdr = elf_eh_frame_hdr (abfd);
@@ -4688,6 +4810,7 @@
align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec);
if ((p->p_type == PT_LOAD
+ || p->p_type == PT_GNU_SHR
|| p->p_type == PT_TLS)
&& (this_hdr->sh_type != SHT_NOBITS
|| ((this_hdr->sh_flags & SHF_ALLOC) != 0
@@ -6923,8 +7046,9 @@
#endif
sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
}
+ /* Output undefined secondary symbols as weak. */
else if (bfd_is_und_section (syms[idx]->section))
- sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
+ sym.st_info = ELF_ST_INFO (((flags & (BSF_WEAK | BSF_SECONDARY))
? STB_WEAK
: STB_GLOBAL),
type);
@@ -6938,6 +7062,8 @@
bind = STB_LOCAL;
else if (flags & BSF_GNU_UNIQUE)
bind = STB_GNU_UNIQUE;
+ else if (flags & BSF_SECONDARY)
+ bind = STB_SECONDARY;
else if (flags & BSF_WEAK)
bind = STB_WEAK;
else if (flags & BSF_GLOBAL)
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index a00d47c..c441ea5 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -817,6 +817,9 @@
/* The index of the next unused R_386_IRELATIVE slot in .rel.plt. */
bfd_vma next_irelative_index;
+
+ asection *sdynsharablebss;
+ asection *srelsharablebss;
};
/* Get the i386 ELF linker hash table from a link_info structure. */
@@ -996,10 +999,19 @@
htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
if (!info->shared)
- htab->srelbss = bfd_get_linker_section (dynobj, ".rel.bss");
+ {
+ htab->srelbss = bfd_get_linker_section (dynobj, ".rel.bss");
+ htab->sdynsharablebss
+ = bfd_get_linker_section (dynobj, ".dynsharablebss");
+ htab->srelsharablebss
+ = bfd_get_linker_section (dynobj, ".rel.sharable_bss");
+ }
if (!htab->sdynbss
- || (!info->shared && !htab->srelbss))
+ || (!info->shared
+ && (!htab->srelbss
+ || !htab->sdynsharablebss
+ || !htab->srelsharablebss)))
abort ();
if (get_elf_i386_backend_data (dynobj)->is_vxworks
@@ -2153,17 +2165,23 @@
both the dynamic object and the regular object will refer to the
same memory location for the variable. */
+ s = htab->sdynbss;
+
/* We must generate a R_386_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->srelbss->size += sizeof (Elf32_External_Rel);
+ if (elf_section_flags (h->root.u.def.section) & SHF_GNU_SHARABLE)
+ {
+ htab->srelsharablebss->size += sizeof (Elf32_External_Rel);
+ s = htab->sdynsharablebss;
+ }
+ else
+ htab->srelbss->size += sizeof (Elf32_External_Rel);
h->needs_copy = 1;
}
- s = htab->sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (h, s);
}
@@ -2885,6 +2903,7 @@
|| s == htab->elf.iplt
|| s == htab->elf.igotplt
|| s == htab->plt_eh_frame
+ || s == htab->sdynsharablebss
|| s == htab->sdynbss)
{
/* Strip these too. */
@@ -4682,20 +4701,26 @@
if (h->needs_copy)
{
Elf_Internal_Rela rel;
+ asection *s;
+
+ if (h->root.u.def.section == htab->sdynsharablebss)
+ s = htab->srelsharablebss;
+ else
+ s = htab->srelbss;
/* This symbol needs a copy reloc. Set it up. */
if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->srelbss == NULL)
+ || s == NULL)
abort ();
rel.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_COPY);
- elf_append_rel (output_bfd, htab->srelbss, &rel);
+ elf_append_rel (output_bfd, s, &rel);
}
return TRUE;
@@ -5048,7 +5073,8 @@
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
- return TRUE;
+ return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp,
+ secp, valp);
}
#define TARGET_LITTLE_SYM i386_elf32_vec
@@ -5099,6 +5125,19 @@
#define elf_backend_hash_symbol elf_i386_hash_symbol
#define elf_backend_add_symbol_hook elf_i386_add_symbol_hook
+#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. */
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index 4cfef7a..da7cd52 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -2253,7 +2253,10 @@
if (SGI_COMPAT (abfd))
return (sym->flags & BSF_SECTION_SYM) == 0;
else
- return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0
+ return ((sym->flags & (BSF_GLOBAL
+ | BSF_WEAK
+ | BSF_SECONDARY
+ | BSF_GNU_UNIQUE)) != 0
|| bfd_is_und_section (bfd_get_section (sym))
|| bfd_is_com_section (bfd_get_section (sym)));
}
diff --git a/bfd/elf64-ia64-vms.c b/bfd/elf64-ia64-vms.c
index dd86e3c..0ff1798 100644
--- a/bfd/elf64-ia64-vms.c
+++ b/bfd/elf64-ia64-vms.c
@@ -4926,6 +4926,10 @@
flags = BSF_WEAK;
break;
+ case STB_SECONDARY:
+ flags = BSF_SECONDARY;
+ break;
+
case STB_GNU_UNIQUE:
flags = BSF_GNU_UNIQUE;
break;
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 9d18a54..4ec1533 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -854,6 +854,9 @@
bfd_vma next_jump_slot_index;
/* The index of the next R_X86_64_IRELATIVE entry in .rela.plt. */
bfd_vma next_irelative_index;
+
+ asection *sdynsharablebss;
+ asection *srelsharablebss;
};
/* Get the x86-64 ELF linker hash table from a link_info structure. */
@@ -1054,10 +1057,19 @@
htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
if (!info->shared)
- htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
+ {
+ htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
+ htab->sdynsharablebss
+ = bfd_get_linker_section (dynobj, ".dynsharablebss");
+ htab->srelsharablebss
+ = bfd_get_linker_section (dynobj, ".rela.sharable_bss");
+ }
if (!htab->sdynbss
- || (!info->shared && !htab->srelbss))
+ || (!info->shared
+ && (!htab->srelbss
+ || !htab->sdynsharablebss
+ || !htab->srelsharablebss)))
abort ();
if (!info->no_ld_generated_unwind_info
@@ -2390,6 +2402,8 @@
if (htab == NULL)
return FALSE;
+ s = htab->sdynbss;
+
/* We must generate a R_X86_64_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
@@ -2397,12 +2411,16 @@
{
const struct elf_backend_data *bed;
bed = get_elf_backend_data (info->output_bfd);
- htab->srelbss->size += bed->s->sizeof_rela;
+ if (elf_section_flags (h->root.u.def.section) & SHF_GNU_SHARABLE)
+ {
+ htab->srelsharablebss->size += bed->s->sizeof_rela;
+ s = htab->sdynsharablebss;
+ }
+ else
+ htab->srelbss->size += bed->s->sizeof_rela;
h->needs_copy = 1;
}
- s = htab->sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (h, s);
}
@@ -3139,6 +3157,7 @@
|| s == htab->elf.igotplt
|| s == htab->plt_bnd
|| s == htab->plt_eh_frame
+ || s == htab->sdynsharablebss
|| s == htab->sdynbss)
{
/* Strip this section if we don't need it; see the
@@ -5002,13 +5021,19 @@
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;
+
+ if (h->root.u.def.section == htab->sdynsharablebss)
+ s = htab->srelsharablebss;
+ else
+ s = htab->srelbss;
/* This symbol needs a copy reloc. Set it up. */
if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->srelbss == NULL)
+ || s == NULL)
abort ();
rela.r_offset = (h->root.u.def.value
@@ -5016,7 +5041,7 @@
+ h->root.u.def.section->output_offset);
rela.r_info = htab->r_info (h->dynindx, R_X86_64_COPY);
rela.r_addend = 0;
- elf_append_rela (output_bfd, htab->srelbss, &rela);
+ elf_append_rela (output_bfd, s, &rela);
}
return TRUE;
@@ -5544,7 +5569,8 @@
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
- return TRUE;
+ return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp,
+ secp, valp);
}
@@ -5560,7 +5586,8 @@
*index_return = SHN_X86_64_LCOMMON;
return TRUE;
}
- return FALSE;
+ return _bfd_elf_sharable_section_from_bfd_section (abfd, sec,
+ index_return);
}
/* Process a symbol. */
@@ -5578,22 +5605,26 @@
asym->value = elfsym->internal_elf_sym.st_size;
/* Common symbol doesn't set BSF_GLOBAL. */
asym->flags &= ~BSF_GLOBAL;
+ return;
break;
}
+
+ _bfd_elf_sharable_symbol_processing (abfd, asym);
}
static bfd_boolean
elf_x86_64_common_definition (Elf_Internal_Sym *sym)
{
return (sym->st_shndx == SHN_COMMON
- || sym->st_shndx == SHN_X86_64_LCOMMON);
+ || sym->st_shndx == SHN_X86_64_LCOMMON
+ || _bfd_elf_sharable_common_definition (sym));
}
static unsigned int
elf_x86_64_common_section_index (asection *sec)
{
if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0)
- return SHN_COMMON;
+ return _bfd_elf_sharable_common_section_index (sec);
else
return SHN_X86_64_LCOMMON;
}
@@ -5602,7 +5633,7 @@
elf_x86_64_common_section (asection *sec)
{
if ((elf_section_flags (sec) & SHF_X86_64_LARGE) == 0)
- return bfd_com_section_ptr;
+ return _bfd_elf_sharable_common_section (sec);
else
return &_bfd_elf_large_com_section;
}
@@ -5612,9 +5643,12 @@
const Elf_Internal_Sym *sym,
asection **psec,
bfd_boolean newdef,
+ bfd_boolean newdyn,
+ bfd *abfd,
bfd_boolean olddef,
+ bfd_boolean olddyn,
bfd *oldbfd,
- const asection *oldsec)
+ asection *oldsec)
{
/* A normal common symbol and a large common symbol result in a
normal common symbol. We turn the large common symbol into a
@@ -5623,7 +5657,8 @@
&& h->root.type == bfd_link_hash_common
&& !newdef
&& bfd_is_com_section (*psec)
- && oldsec != *psec)
+ && oldsec != *psec
+ && _bfd_elf_sharable_common_section_index (oldsec) == SHN_COMMON)
{
if (sym->st_shndx == SHN_COMMON
&& (elf_section_flags (oldsec) & SHF_X86_64_LARGE) != 0)
@@ -5631,13 +5666,19 @@
h->root.u.c.p->section
= bfd_make_section_old_way (oldbfd, "COMMON");
h->root.u.c.p->section->flags = SEC_ALLOC;
+ return TRUE;
}
else if (sym->st_shndx == SHN_X86_64_LCOMMON
&& (elf_section_flags (oldsec) & SHF_X86_64_LARGE) == 0)
- *psec = bfd_com_section_ptr;
+ {
+ *psec = bfd_com_section_ptr;
+ return TRUE;
+ }
}
- return TRUE;
+ return _bfd_elf_sharable_merge_symbol (h, sym, psec, newdef, newdyn,
+ abfd, olddef, olddyn, oldbfd,
+ oldsec);
}
static int
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index ec53c3b..34a766b 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1167,6 +1167,9 @@
sym = symbase = NULL;
else
{
+ /* Start of global symbols */
+ Elf_Internal_Sym *start_global;
+
isymbuf = bfd_elf_get_elf_syms (abfd, hdr, symcount, 0,
NULL, NULL, NULL);
if (isymbuf == NULL)
@@ -1211,6 +1214,9 @@
if (xver != NULL)
++xver;
isymend = isymbuf + symcount;
+ start_global = isymbuf;
+ if (!elf_bad_symtab (abfd))
+ start_global += hdr->sh_info;
for (isym = isymbuf + 1, sym = symbase; isym < isymend; isym++, sym++)
{
memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym));
@@ -1269,6 +1275,12 @@
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
sym->symbol.value -= sym->symbol.section->vma;
+ if (isym < start_global
+ && ELF_ST_BIND (isym->st_info) != STB_LOCAL)
+ (*_bfd_error_handler)
+ (_("%s: corrupted global symbol `%s' treated as local"),
+ abfd->filename, sym->symbol.name);
+
switch (ELF_ST_BIND (isym->st_info))
{
case STB_LOCAL:
@@ -1281,6 +1293,9 @@
case STB_WEAK:
sym->symbol.flags |= BSF_WEAK;
break;
+ case STB_SECONDARY:
+ sym->symbol.flags |= BSF_SECONDARY;
+ break;
case STB_GNU_UNIQUE:
sym->symbol.flags |= BSF_GNU_UNIQUE;
break;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index d33efe0..26ab8ce 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -385,6 +385,27 @@
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
+
+ if (info->sharable_sections)
+ {
+ s = bfd_make_section (abfd, ".dynsharablebss");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s,
+ (SEC_ALLOC
+ | SEC_LINKER_CREATED)))
+ return FALSE;
+
+ s = bfd_make_section (abfd,
+ (bed->default_use_rela_p
+ ? ".rela.sharable_bss"
+ : ".rel.sharable_bss"));
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s,
+ flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s,
+ bed->s->log_file_align))
+ return FALSE;
+ }
}
}
@@ -885,7 +906,8 @@
overriding a new definition. We set TYPE_CHANGE_OK if it is OK for
the type to change. We set SIZE_CHANGE_OK if it is OK for the size
to change. By OK to change, we mean that we shouldn't warn if the
- type or size does change. */
+ type or size does change. If OLDSECONARY is TRUE, the old definion
+ is a secondary symbol. */
static bfd_boolean
_bfd_elf_merge_symbol (bfd *abfd,
@@ -895,6 +917,7 @@
asection **psec,
bfd_vma *pvalue,
struct elf_link_hash_entry **sym_hash,
+ bfd_boolean oldsecondary,
bfd **poldbfd,
bfd_boolean *pold_weak,
unsigned int *pold_alignment,
@@ -910,7 +933,7 @@
int bind;
bfd *oldbfd;
bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
- bfd_boolean newweak, oldweak, newfunc, oldfunc;
+ bfd_boolean newweak, oldweak, newfunc, oldfunc, weakbind;
const struct elf_backend_data *bed;
*skip = FALSE;
@@ -968,9 +991,17 @@
if (poldbfd && *poldbfd == NULL)
*poldbfd = oldbfd;
+ /* Set OLDSECONADRY if it isn't TRUE. */
+ if (!oldsecondary)
+ oldsecondary = h->root.secondary != 0;
+
+ /* Treat secondary symbols as weak symbols. */
+ weakbind = bind == STB_WEAK || bind == STB_SECONDARY;
+
/* Differentiate strong and weak symbols. */
- newweak = bind == STB_WEAK;
- oldweak = (h->root.type == bfd_link_hash_defweak
+ newweak = weakbind;
+ oldweak = (oldsecondary
+ || h->root.type == bfd_link_hash_defweak
|| h->root.type == bfd_link_hash_undefweak);
if (pold_weak)
*pold_weak = oldweak;
@@ -1001,7 +1032,7 @@
{
if (bfd_is_und_section (sec))
{
- if (bind != STB_WEAK)
+ if (!weakbind)
{
h->ref_dynamic_nonweak = 1;
hi->ref_dynamic_nonweak = 1;
@@ -1250,7 +1281,7 @@
if (newdef && !newdyn && olddyn)
newweak = FALSE;
- if (olddef && newdyn)
+ if (olddef && newdyn && !oldsecondary)
oldweak = FALSE;
/* Allow changes between different types of function symbol. */
@@ -1324,7 +1355,8 @@
backend to check if we can merge them. */
if (bed->merge_symbol != NULL)
{
- if (!bed->merge_symbol (h, sym, psec, newdef, olddef, oldbfd, oldsec))
+ if (!bed->merge_symbol (h, sym, psec, newdef, newdyn, abfd,
+ olddef, olddyn, oldbfd, oldsec))
return FALSE;
sec = *psec;
}
@@ -1365,10 +1397,14 @@
represent variables; this can cause confusion in principle, but
any such confusion would seem to indicate an erroneous program or
shared library. We also permit a common symbol in a regular
- object to override a weak symbol in a shared object. */
+ object to override a weak symbol in a shared object.
+
+ We let a definition in a dynamic object override the old secondary
+ symbol. */
if (newdyn
&& newdef
+ && !oldsecondary
&& (olddef
|| (h->root.type == bfd_link_hash_common
&& (newweak || newfunc))))
@@ -1407,8 +1443,9 @@
*size_change_ok = TRUE;
}
- /* Skip weak definitions of symbols that are already defined. */
- if (newdef && olddef && newweak)
+ /* Skip weak definitions of symbols that are already defined unless
+ the old definition is secondary. */
+ if (newdef && olddef && newweak && !oldsecondary)
{
/* Don't skip new non-IR weak syms. */
if (!(oldbfd != NULL
@@ -1439,18 +1476,20 @@
always take precedence over symbols from dynamic objects, even if
they are defined after the dynamic object in the link.
+ The new non-secondary definition overrides the old secondary
+ definition.
+
As above, we again permit a common symbol in a regular object to
override a definition in a shared object if the shared object
symbol is a function or is weak. */
flip = NULL;
- if (!newdyn
+ if (((!newdyn && olddyn && h->def_dynamic) || oldsecondary)
+ && bind != STB_SECONDARY
&& (newdef
|| (bfd_is_com_section (sec)
&& (oldweak || oldfunc)))
- && olddyn
- && olddef
- && h->def_dynamic)
+ && olddef)
{
/* Change the hash table entry to undefined, and let
_bfd_generic_link_add_one_symbol do the right thing with the
@@ -1553,8 +1592,8 @@
/* This function is called to create an indirect symbol from the
default for the symbol with the default version if needed. The
- symbol is described by H, NAME, SYM, SEC, and VALUE. We
- set DYNSYM if the new indirect symbol is dynamic. */
+ symbol is described by H, NAME, SYM, SEC, VALUE, and OLDSECONDARY.
+ We set DYNSYM if the new indirect symbol is dynamic. */
static bfd_boolean
_bfd_elf_add_default_symbol (bfd *abfd,
@@ -1564,6 +1603,7 @@
Elf_Internal_Sym *sym,
asection *sec,
bfd_vma value,
+ bfd_boolean oldsecondary,
bfd **poldbfd,
bfd_boolean *dynsym)
{
@@ -1608,8 +1648,9 @@
size_change_ok = FALSE;
tmp_sec = sec;
if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value,
- &hi, poldbfd, NULL, NULL, &skip, &override,
- &type_change_ok, &size_change_ok))
+ &hi, oldsecondary, poldbfd, NULL, NULL,
+ &skip, &override, &type_change_ok
+ , &size_change_ok))
return FALSE;
if (skip)
@@ -1723,8 +1764,8 @@
size_change_ok = FALSE;
tmp_sec = sec;
if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value,
- &hi, poldbfd, NULL, NULL, &skip, &override,
- &type_change_ok, &size_change_ok))
+ &hi, oldsecondary, poldbfd, NULL, NULL, &skip,
+ &override, &type_change_ok, &size_change_ok))
return FALSE;
if (skip)
@@ -2425,6 +2466,20 @@
}
else
{
+ /* If a plugin symbol is referenced from a non-IR file, mark
+ the symbol as undefined, except for symbol for linker
+ created section. */
+ if (h->root.non_ir_ref
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && (h->root.u.def.section->flags & SEC_LINKER_CREATED) == 0
+ && h->root.u.def.section->owner != NULL
+ && (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0)
+ {
+ h->root.type = bfd_link_hash_undefined;
+ h->root.u.undef.abfd = h->root.u.def.section->owner;
+ }
+
/* Unfortunately, NON_ELF is only correct if the symbol
was first seen in a non-ELF file. Fortunately, if the symbol
was first seen in an ELF file, we're probably OK unless the
@@ -2868,31 +2923,41 @@
return tls;
}
-/* Return TRUE iff this is a non-common, definition of a non-function symbol. */
+/* Return TRUE iff this is a non-common, definition of a
+ non-function symbol, unless IGNORE_SECONDARY is TRUE. */
+
static bfd_boolean
-is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
- Elf_Internal_Sym *sym)
+is_global_symbol_definition (bfd *abfd, Elf_Internal_Sym *sym,
+ bfd_boolean ignore_secondary)
{
- const struct elf_backend_data *bed;
+ /* Ignore secondary symbols. */
+ if (ignore_secondary && ELF_ST_BIND (sym->st_info) == STB_SECONDARY)
+ return FALSE;
/* Local symbols do not count, but target specific ones might. */
if (ELF_ST_BIND (sym->st_info) != STB_GLOBAL
&& ELF_ST_BIND (sym->st_info) < STB_LOOS)
return FALSE;
- bed = get_elf_backend_data (abfd);
- /* Function symbols do not count. */
- if (bed->is_function_type (ELF_ST_TYPE (sym->st_info)))
- return FALSE;
-
/* If the section is undefined, then so is the symbol. */
if (sym->st_shndx == SHN_UNDEF)
return FALSE;
- /* If the symbol is defined in the common section, then
- it is a common definition and so does not count. */
- if (bed->common_definition (sym))
- return FALSE;
+ /* If secondary symbols are ignored, count function and common
+ symbols as global definition. */
+ if (!ignore_secondary)
+ {
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ /* Function symbols do not count. */
+ if (bed->is_function_type (ELF_ST_TYPE (sym->st_info)))
+ return FALSE;
+
+ /* If the symbol is defined in the common section, then
+ it is a common definition and so does not count. */
+ if (bed->common_definition (sym))
+ return FALSE;
+ }
/* If the symbol is in a target specific section then we
must rely upon the backend to tell us what it is. */
@@ -2911,9 +2976,12 @@
/* Search the symbol table of the archive element of the archive ABFD
whose archive map contains a mention of SYMDEF, and determine if
- the symbol is defined in this element. */
+ the symbol is defined in this element. Igore seconday defintion,
+ it IGNORE_SECONDARY is TRUE. */
+
static bfd_boolean
-elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
+elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef,
+ bfd_boolean ignore_secondary)
{
Elf_Internal_Shdr * hdr;
bfd_size_type symcount;
@@ -2974,7 +3042,8 @@
if (strcmp (name, symdef->name) == 0)
{
- result = is_global_data_symbol_definition (abfd, isym);
+ result = is_global_symbol_definition (abfd, isym,
+ ignore_secondary);
break;
}
}
@@ -3822,6 +3891,7 @@
bfd_boolean common;
unsigned int old_alignment;
bfd *old_bfd;
+ bfd_boolean oldsecondary;
override = FALSE;
@@ -3849,6 +3919,10 @@
flags = BSF_WEAK;
break;
+ case STB_SECONDARY:
+ flags = BSF_SECONDARY;
+ break;
+
case STB_GNU_UNIQUE:
flags = BSF_GNU_UNIQUE;
break;
@@ -4084,7 +4158,7 @@
| (isym->st_other & ~ELF_ST_VISIBILITY (-1)));
if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value,
- sym_hash, &old_bfd, &old_weak,
+ sym_hash, FALSE, &old_bfd, &old_weak,
&old_alignment, &skip, &override,
&type_change_ok, &size_change_ok))
goto error_free_vers;
@@ -4104,7 +4178,12 @@
&& vernum > 1
&& definition)
h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1];
+
+ /* Remember if the old definition is secondary. */
+ oldsecondary = h->root.secondary != 0;
}
+ else
+ oldsecondary = FALSE;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, name, flags, sec, value, NULL, FALSE, bed->collect,
@@ -4184,10 +4263,14 @@
if (! definition)
{
h->ref_regular = 1;
- if (bind != STB_WEAK)
+ /* Treat secondary symbols as weak symbols. */
+ if (bind != STB_WEAK && bind != STB_SECONDARY)
h->ref_regular_nonweak = 1;
}
- else
+ /* Mark it defined in a regular object if it is a
+ non-secondary definition or it hasn't been defined
+ in a dynamic object. */
+ else if (!h->def_dynamic || bind != STB_SECONDARY)
{
h->def_regular = 1;
if (h->def_dynamic)
@@ -4216,6 +4299,13 @@
{
h->def_dynamic = 1;
hi->def_dynamic = 1;
+ /* Dynamic definition overrides regular old secondary
+ definition. */
+ if (oldsecondary)
+ {
+ h->def_regular = 0;
+ hi->def_regular = 0;
+ }
}
/* If the indirect symbol has been forced local, don't
@@ -4234,7 +4324,8 @@
if (definition
|| (!override && h->root.type == bfd_link_hash_common))
if (!_bfd_elf_add_default_symbol (abfd, info, h, name, isym,
- sec, value, &old_bfd, &dynsym))
+ sec, value, oldsecondary,
+ &old_bfd, &dynsym))
goto error_free_vers;
/* Check the alignment when a common symbol is involved. This
@@ -5024,16 +5115,27 @@
map alone. Instead we must read in the element's symbol
table and check that to see what kind of symbol definition
this is. */
- if (! elf_link_is_defined_archive_symbol (abfd, symdef))
+ if (! elf_link_is_defined_archive_symbol (abfd, symdef,
+ FALSE))
continue;
}
- else if (h->root.type != bfd_link_hash_undefined)
+ /* Keep searching if a definition is secondary. */
+ else if (h->root.type != bfd_link_hash_undefined
+ && !h->root.secondary)
{
if (h->root.type != bfd_link_hash_undefweak)
/* Symbol must be defined. Don't check it again. */
included[i] = TRUE;
continue;
}
+ else if (h->root.secondary
+ && h->root.type == bfd_link_hash_defweak)
+ {
+ /* Ignore another secondary definition. */
+ if (! elf_link_is_defined_archive_symbol (abfd, symdef,
+ TRUE))
+ continue;
+ }
/* We need to include this archive member. */
element = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
@@ -8807,7 +8909,21 @@
sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type);
else if (h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_defweak)
- sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
+ {
+ /* Generate defined secondary symbols for "ld -shared -z secondary"
+ and "ld -r". For undefined secondary symbols, we convert them
+ to weak symbols. We also convert defined secondary symbols in
+ executables to weak symbols since their bindings in executables
+ are final and can't be changed. */
+ if ((flinfo->info->relocatable
+ || (!flinfo->info->executable
+ && flinfo->info->emit_secondary))
+ && h->root.type == bfd_link_hash_defweak
+ && h->root.secondary)
+ sym.st_info = ELF_ST_INFO (STB_SECONDARY, h->type);
+ else
+ sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
+ }
else
sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
sym.st_target_internal = h->target_internal;
@@ -8938,7 +9054,8 @@
if (sym.st_shndx == SHN_UNDEF
&& h->ref_regular
&& (ELF_ST_BIND (sym.st_info) == STB_GLOBAL
- || ELF_ST_BIND (sym.st_info) == STB_WEAK))
+ || ELF_ST_BIND (sym.st_info) == STB_WEAK
+ || ELF_ST_BIND (sym.st_info) == STB_SECONDARY))
{
int bindtype;
unsigned int type = ELF_ST_TYPE (sym.st_info);
@@ -8964,10 +9081,12 @@
sym.st_size = 0;
/* If a non-weak symbol with non-default visibility is not defined
- locally, it is a fatal error. */
+ locally, it is a fatal error. Treat secondary symbols as weak
+ symbols. */
if (!flinfo->info->relocatable
&& ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT
&& ELF_ST_BIND (sym.st_info) != STB_WEAK
+ && ELF_ST_BIND (sym.st_info) != STB_SECONDARY
&& h->root.type == bfd_link_hash_undefined
&& !h->def_regular)
{
@@ -13052,3 +13171,207 @@
BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
bed->s->swap_reloc_out (abfd, rel, loc);
}
+
+asection _bfd_elf_sharable_com_section
+ = BFD_FAKE_SECTION (_bfd_elf_sharable_com_section, SEC_IS_COMMON,
+ NULL, "SHARABLE_COMMON", 0);
+
+static asection *
+get_sharable_common_section (bfd *abfd)
+{
+ asection *scomm = bfd_get_section_by_name (abfd, "SHARABLE_COMMON");
+
+ if (scomm == NULL)
+ {
+ scomm = bfd_make_section_with_flags (abfd,
+ "SHARABLE_COMMON",
+ (SEC_ALLOC
+ | SEC_IS_COMMON
+ | SEC_LINKER_CREATED));
+ if (scomm == NULL)
+ return scomm;
+ elf_section_flags (scomm) |= SHF_GNU_SHARABLE;
+ }
+
+ return scomm;
+}
+
+bfd_boolean
+_bfd_elf_add_sharable_symbol (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ Elf_Internal_Sym *sym,
+ const char **namep ATTRIBUTE_UNUSED,
+ flagword *flagsp ATTRIBUTE_UNUSED,
+ asection **secp,
+ bfd_vma *valp)
+{
+ asection *scomm;
+
+ switch (sym->st_shndx)
+ {
+ case SHN_GNU_SHARABLE_COMMON:
+ scomm = get_sharable_common_section (abfd);
+ if (scomm == NULL)
+ return FALSE;
+ *secp = scomm;
+ *valp = sym->st_size;
+ break;
+ }
+ return TRUE;
+}
+
+bfd_boolean
+_bfd_elf_sharable_section_from_bfd_section
+ (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, int *index_return)
+{
+ if (sec == &_bfd_elf_sharable_com_section)
+ {
+ *index_return = SHN_GNU_SHARABLE_COMMON;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+_bfd_elf_sharable_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
+ asymbol *asym)
+{
+ elf_symbol_type *elfsym = (elf_symbol_type *) asym;
+
+ switch (elfsym->internal_elf_sym.st_shndx)
+ {
+ case SHN_GNU_SHARABLE_COMMON:
+ asym->section = &_bfd_elf_sharable_com_section;
+ asym->value = elfsym->internal_elf_sym.st_size;
+ asym->flags &= ~BSF_GLOBAL;
+ break;
+ }
+}
+
+bfd_boolean
+_bfd_elf_sharable_common_definition (Elf_Internal_Sym *sym)
+{
+ return (sym->st_shndx == SHN_COMMON
+ || sym->st_shndx == SHN_GNU_SHARABLE_COMMON);
+}
+
+unsigned int
+_bfd_elf_sharable_common_section_index (asection *sec)
+{
+ if ((elf_section_flags (sec) & SHF_GNU_SHARABLE) == 0)
+ return SHN_COMMON;
+ else
+ return SHN_GNU_SHARABLE_COMMON;
+}
+
+asection *
+_bfd_elf_sharable_common_section (asection *sec)
+{
+ if ((elf_section_flags (sec) & SHF_GNU_SHARABLE) == 0)
+ return bfd_com_section_ptr;
+ else
+ return &_bfd_elf_sharable_com_section;
+}
+
+bfd_boolean
+_bfd_elf_sharable_merge_symbol (struct elf_link_hash_entry *h,
+ const Elf_Internal_Sym *sym,
+ asection **psec,
+ bfd_boolean newdef,
+ bfd_boolean newdyn,
+ bfd *abfd,
+ bfd_boolean olddef,
+ bfd_boolean olddyn,
+ bfd *oldbfd,
+ asection *oldsec)
+{
+ asection *sec = *psec;
+
+ /* Check sharable symbol. If one is undefined, it is OK. */
+ if (oldsec && !bfd_is_und_section (sec))
+ {
+ bfd_boolean sharable, oldsharable;
+
+ sharable = (elf_section_data (sec)
+ && (elf_section_flags (sec) & SHF_GNU_SHARABLE));
+ oldsharable = (elf_section_data (oldsec)
+ && (elf_section_flags (oldsec)
+ & SHF_GNU_SHARABLE));
+
+ if (sharable != oldsharable)
+ {
+ bfd *nsbfd, *sbfd;
+ asection *nssec, *ssec;
+ bfd_boolean nsdyn, sdyn, nsdef, sdef;
+
+ if (oldsharable)
+ {
+ sbfd = oldbfd;
+ nsbfd = abfd;
+ ssec = oldsec;
+ nssec = sec;
+ sdyn = olddyn;
+ nsdyn = newdyn;
+ sdef = olddef;
+ nsdef = newdef;
+ }
+ else
+ {
+ sbfd = abfd;
+ nsbfd = oldbfd;
+ ssec = sec;
+ nssec = oldsec;
+ sdyn = newdyn;
+ nsdyn = olddyn;
+ sdef = newdef;
+ nsdef = olddef;
+ }
+
+ if (sdef && !sdyn)
+ {
+ /* If the sharable definition comes from a relocatable
+ file, it will override the non-sharable one in DSO. */
+ return TRUE;
+ }
+ else if (!nsdef
+ && !nsdyn
+ && (h->root.type == bfd_link_hash_common
+ || bfd_is_com_section (nssec)))
+ {
+ asection *scomm;
+
+ /* When the non-sharable common symbol in a relocatable
+ file, we can turn it into sharable. If the sharable
+ symbol isn't common, the non-sharable common symbol
+ will be overidden. We only need to handle the
+ sharable common symbol and the non-sharable common
+ symbol. We just turn the non-sharable common symbol
+ into the sharable one. */
+ if (sym->st_shndx == SHN_GNU_SHARABLE_COMMON)
+ {
+ scomm = get_sharable_common_section (oldbfd);
+ if (scomm == NULL)
+ return FALSE;
+ h->root.u.c.p->section = scomm;
+ }
+ else
+ {
+ scomm = get_sharable_common_section (abfd);
+ if (scomm == NULL)
+ return FALSE;
+ *psec = scomm;
+ }
+
+ return TRUE;
+ }
+
+ (*_bfd_error_handler)
+ (_("%s: sharable symbol in %B section %A mismatches non-shrable symbol in %B section %A"),
+ sbfd, ssec, nsbfd, nssec, h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c
index 9ddde24..a24cc8e 100644
--- a/bfd/elfn32-mips.c
+++ b/bfd/elfn32-mips.c
@@ -3456,7 +3456,10 @@
if (SGI_COMPAT (abfd))
return (sym->flags & BSF_SECTION_SYM) == 0;
else
- return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0
+ return ((sym->flags & (BSF_GLOBAL
+ | BSF_WEAK
+ | BSF_SECONDARY
+ | BSF_GNU_UNIQUE)) != 0
|| bfd_is_und_section (bfd_get_section (sym))
|| bfd_is_com_section (bfd_get_section (sym)));
}
diff --git a/bfd/elfnn-ia64.c b/bfd/elfnn-ia64.c
index a8d8d0b..02420ec 100644
--- a/bfd/elfnn-ia64.c
+++ b/bfd/elfnn-ia64.c
@@ -1055,7 +1055,8 @@
*valp = sym->st_size;
}
- return TRUE;
+ return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp,
+ secp, valp);
}
/* Return the number of additional phdrs we will need. */
@@ -5068,6 +5069,19 @@
#define elf_backend_special_sections elfNN_ia64_special_sections
#define elf_backend_default_execstack 0
+#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
+
/* FIXME: PR 290: The Intel C compiler generates SHT_IA_64_UNWIND with
SHF_LINK_ORDER. But it doesn't set the sh_link or sh_info fields.
We don't want to flood users with so many error messages. We turn
diff --git a/bfd/format.c b/bfd/format.c
index c4bc944..63ad2e6 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -179,6 +179,33 @@
preserve->marker = NULL;
}
+/* Set lto_type in ABFD. */
+
+static void
+bfd_set_lto_type (bfd *abfd)
+{
+ if (abfd->format == bfd_object
+ && abfd->lto_type == lto_non_object
+ && (abfd->flags & (DYNAMIC | EXEC_P)) == 0)
+ {
+ asection *sec;
+ enum bfd_lto_object_type type = lto_non_ir_object;
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ {
+ if (strcmp (sec->name, GNU_OBJECT_ONLY_SECTION_NAME) == 0)
+ {
+ type = lto_mixed_object;
+ abfd->object_only_section = sec;
+ break;
+ }
+ else if (type != lto_ir_object
+ && strncmp (sec->name, ".gnu.lto_", 9) == 0)
+ type = lto_ir_object;
+ }
+ abfd->lto_type = type;
+ }
+}
+
/*
FUNCTION
bfd_check_format_matches
@@ -203,6 +230,9 @@
bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
{
extern const bfd_target binary_vec;
+#if BFD_SUPPORTS_PLUGINS
+ extern const bfd_target plugin_vec;
+#endif
const bfd_target * const *target;
const bfd_target **matching_vector = NULL;
const bfd_target *save_targ, *right_targ, *ar_right_targ, *match_targ;
@@ -221,7 +251,10 @@
}
if (abfd->format != bfd_unknown)
- return abfd->format == format;
+ {
+ bfd_set_lto_type (abfd);
+ return abfd->format == format;
+ }
if (matching != NULL || *bfd_associated_vector != NULL)
{
@@ -285,6 +318,13 @@
|| (*target)->match_priority > best_match)
continue;
+#if BFD_SUPPORTS_PLUGINS
+ /* Since the plugin target is explicitly specified when a BFD file
+ is opened, don't check it twice. */
+ if (*target == &plugin_vec)
+ continue;
+#endif
+
/* If we already tried a match, the bfd is modified and may
have sections attached, which will confuse the next
_bfd_check_format call. */
@@ -449,6 +489,8 @@
if (matching_vector)
free (matching_vector);
+ bfd_set_lto_type (abfd);
+
/* File position has moved, BTW. */
return TRUE;
}
diff --git a/bfd/linker.c b/bfd/linker.c
index abdf5b0..9cb5cc4 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -1444,6 +1444,7 @@
struct bfd_link_hash_entry *h;
struct bfd_link_hash_entry *inh = NULL;
bfd_boolean cycle;
+ unsigned int secondary;
BFD_ASSERT (section != NULL);
@@ -1508,15 +1509,53 @@
return FALSE;
}
+ /* Since secondary symbols have lower precedence than weak symbols,
+ we treat them as weak symbols here. */
+ secondary = (flags & BSF_SECONDARY) != 0;
+ if (secondary)
+ switch (row)
+ {
+ default:
+ break;
+
+ case UNDEF_ROW:
+ row = UNDEFW_ROW;
+ break;
+
+ case DEF_ROW:
+ row = DEFW_ROW;
+ break;
+ }
+
if (hashp != NULL)
*hashp = h;
do
{
enum link_action action;
+ enum bfd_link_hash_type type;
+
+ type = h->type;
+ /* Convert a secondary symbol to a weak symbol. Backend is
+ responsible to let a weak symbol override a secondary
+ symbol. */
+ if (h->secondary)
+ switch (type)
+ {
+ default:
+ break;
+
+ case bfd_link_hash_undefined:
+ type = bfd_link_hash_undefweak;
+ break;
+
+ case bfd_link_hash_defined:
+ type = bfd_link_hash_defweak;
+ break;
+ }
cycle = FALSE;
- action = link_action[(int) row][(int) h->type];
+ action = link_action[(int) row][(int) type];
switch (action)
{
case FAIL:
@@ -1561,6 +1600,9 @@
h->u.def.section = section;
h->u.def.value = value;
+ /* Mark if this is a secondary symbol. */
+ h->secondary = secondary;
+
/* If we have been asked to, we act like collect2 and
identify all functions that might be global
constructors and destructors and pass them up in a
diff --git a/bfd/opncls.c b/bfd/opncls.c
index a2a35f4..5873196 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -1692,3 +1692,69 @@
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 --git a/bfd/plugin.c b/bfd/plugin.c
index c9d53c8..81ee80f 100644
--- a/bfd/plugin.c
+++ b/bfd/plugin.c
@@ -128,6 +128,139 @@
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,
@@ -140,10 +273,13 @@
plugin_data->nsyms = nsyms;
plugin_data->syms = syms;
- if (nsyms != 0)
+ abfd->tdata.plugin_data = plugin_data;
+
+ 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;
return LDPS_OK;
}
@@ -387,7 +523,8 @@
bfd_plugin_get_symtab_upper_bound (bfd *abfd)
{
struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
- long nsyms = plugin_data->nsyms;
+ /* Add symbols from object only section. */
+ long nsyms = plugin_data->nsyms + plugin_data->object_only_nsyms;
BFD_ASSERT (nsyms >= 0);
@@ -421,12 +558,7 @@
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;
+ int i, j;
for (i = 0; i < nsyms; i++)
{
@@ -439,10 +571,11 @@
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 = &fake_common_section;
+ s->section = &bfd_plugin_fake_common_section;
break;
case LDPK_UNDEF:
case LDPK_WEAKUNDEF:
@@ -450,15 +583,18 @@
break;
case LDPK_DEF:
case LDPK_WEAKDEF:
- s->section = &fake_section;
+ s->section = &bfd_plugin_fake_text_section;
break;
default:
BFD_ASSERT (0);
}
-
- s->udata.p = (void *) &syms[i];
}
+ /* 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 --git a/bfd/plugin.h b/bfd/plugin.h
index 4f1d18b..0ec54bf 100644
--- a/bfd/plugin.h
+++ b/bfd/plugin.h
@@ -30,6 +30,8 @@
{
int nsyms;
const struct ld_plugin_symbol *syms;
+ int object_only_nsyms;
+ asymbol **object_only_syms;
}
plugin_data_struct;
diff --git a/bfd/section.c b/bfd/section.c
index b27539a..b3e0c3d 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -576,6 +576,9 @@
.#define BFD_COM_SECTION_NAME "*COM*"
.#define BFD_IND_SECTION_NAME "*IND*"
.
+.{* GNU object-only section name. *}
+.#define GNU_OBJECT_ONLY_SECTION_NAME ".gnu_object_only"
+.
.{* Pointer to the common section. *}
.#define bfd_com_section_ptr (&_bfd_std_section[0])
.{* Pointer to the undefined section. *}
diff --git a/bfd/syms.c b/bfd/syms.c
index a1d1d77..6077121 100644
--- a/bfd/syms.c
+++ b/bfd/syms.c
@@ -306,6 +306,10 @@
. with this name and type in use. BSF_OBJECT must also be set. *}
.#define BSF_GNU_UNIQUE (1 << 23)
.
+. {* A secondary global symbol, overridable without warnings by
+. a regular or weak global symbol of the same name. *}
+.#define BSF_SECONDARY (1 << 24)
+.
. flagword flags;
.
. {* A pointer to the section to which this symbol is
@@ -489,6 +493,7 @@
((type & BSF_LOCAL)
? (type & BSF_GLOBAL) ? '!' : 'l'
: (type & BSF_GLOBAL) ? 'g'
+ : (type & BSF_SECONDARY) ? 's'
: (type & BSF_GNU_UNIQUE) ? 'u' : ' '),
(type & BSF_WEAK) ? 'w' : ' ',
(type & BSF_CONSTRUCTOR) ? 'C' : ' ',
@@ -692,6 +697,15 @@
}
if (symbol->flags & BSF_GNU_UNIQUE)
return 'u';
+ if (symbol->flags & BSF_SECONDARY)
+ {
+ /* If secondary, determine if it's specifically an object
+ or non-object weak. */
+ if (symbol->flags & BSF_OBJECT)
+ return 'Y';
+ else
+ return 'S';
+ }
if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
return '?';
diff --git a/binutils/nm.c b/binutils/nm.c
index ecd147e..300fd13 100644
--- a/binutils/nm.c
+++ b/binutils/nm.c
@@ -444,6 +444,7 @@
/* PR binutls/12753: Unique symbols are global too. */
keep = ((sym->flags & (BSF_GLOBAL
| BSF_WEAK
+ | BSF_SECONDARY
| BSF_GNU_UNIQUE)) != 0
|| bfd_is_und_section (sym->section)
|| bfd_is_com_section (sym->section));
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 3b353ad..ef1595f 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -1009,30 +1009,6 @@
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
@@ -1114,7 +1090,7 @@
/* PR binutils/3181
If we are going to strip the group signature symbol, then
strip the group section too. */
- gsym = group_signature (sec);
+ gsym = bfd_group_signature (sec, isympp);
if (gsym != NULL)
gname = gsym->name;
else
@@ -2810,7 +2786,7 @@
if ((isection->flags & SEC_GROUP) != 0)
{
- asymbol *gsym = group_signature (isection);
+ asymbol *gsym = bfd_group_signature (isection, isympp);
if (gsym != NULL)
{
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 413de56..cbd4147 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -792,7 +792,8 @@
asymbol *sym)
{
char *alloc;
- const char *name;
+ const char *name, *version_string = NULL;
+ bfd_boolean hidden = FALSE;
alloc = NULL;
name = bfd_asymbol_name (sym);
@@ -804,10 +805,26 @@
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);
diff --git a/binutils/readelf.c b/binutils/readelf.c
index d9c12cc..368b0f6 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -271,6 +271,20 @@
}
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) \
@@ -925,7 +939,8 @@
unsigned long nsyms,
char * strtab,
unsigned long strtablen,
- int is_rela)
+ int is_rela,
+ int is_dynsym)
{
unsigned int i;
Elf_Internal_Rela * rels;
@@ -1358,9 +1373,20 @@
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)
@@ -1387,6 +1413,9 @@
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
@@ -1410,6 +1439,8 @@
sec_name = "ABS";
else if (psym->st_shndx == SHN_COMMON)
sec_name = "COMMON";
+ else if (psym->st_shndx == SHN_GNU_SHARABLE_COMMON)
+ sec_name = "GNU_SHARABLE_COMMON";
else if ((elf_header.e_machine == EM_MIPS
&& psym->st_shndx == SHN_MIPS_SCOMMON)
|| (elf_header.e_machine == EM_TI_C6000
@@ -1444,7 +1475,12 @@
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)
{
@@ -3257,6 +3293,7 @@
case PT_SHLIB: return "SHLIB";
case PT_PHDR: return "PHDR";
case PT_TLS: return "TLS";
+ case PT_GNU_SHR: return "GNU_SHR";
case PT_GNU_EH_FRAME:
return "GNU_EH_FRAME";
@@ -3535,6 +3572,7 @@
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))
@@ -5932,7 +5970,8 @@
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);
}
}
@@ -6007,14 +6046,16 @@
}
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;
}
@@ -9266,6 +9307,7 @@
case STB_LOCAL: return "LOCAL";
case STB_GLOBAL: return "GLOBAL";
case STB_WEAK: return "WEAK";
+ case STB_SECONDARY: return "SECOND";
default:
if (binding >= STB_LOPROC && binding <= STB_HIPROC)
snprintf (buff, sizeof (buff), _("<processor specific>: %d"),
@@ -9490,6 +9532,8 @@
case SHN_UNDEF: return "UND";
case SHN_ABS: return "ABS";
case SHN_COMMON: return "COM";
+ case SHN_GNU_SHARABLE_COMMON:
+ return "GNU_SHARABLE_COM";
default:
if (type == SHN_IA_64_ANSI_COMMON
&& elf_header.e_machine == EM_IA_64
@@ -9594,6 +9638,181 @@
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)
@@ -9833,6 +10052,12 @@
else if (do_dyn_syms || (do_syms && !do_using_dynamic))
{
unsigned int i;
+ /* Irix 5 and 6 are broken. Object file symbol tables are not
+ always sorted correctly such that local symbols precede global
+ symbols, and the sh_info field in the symbol table is not
+ always right. */
+ bfd_boolean check_corrupt_symtab
+ = elf_header.e_ident[EI_OSABI] != ELFOSABI_IRIX;
for (i = 0, section = section_headers;
i < elf_header.e_shnum;
@@ -9890,12 +10115,21 @@
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_vma (psym->st_size, DEC_5);
printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
- printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
+ if (check_corrupt_symtab
+ && si < section->sh_info
+ && ELF_ST_BIND (psym->st_info) != STB_LOCAL)
+ printf (" %-6s", "<corrupt>");
+ else
+ printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
printf (" %-7s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
/* Check to see if any other bits in the st_other field are set.
Note - displaying this information disrupts the layout of the
@@ -9906,163 +10140,18 @@
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');
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index e2ef99e..1ffaa4e 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -68,6 +68,7 @@
static void obj_elf_size (int);
static void obj_elf_type (int);
static void obj_elf_ident (int);
+static void obj_elf_secondary (int);
static void obj_elf_weak (int);
static void obj_elf_local (int);
static void obj_elf_visibility (int);
@@ -76,6 +77,7 @@
static void obj_elf_popsection (int);
static void obj_elf_gnu_attribute (int);
static void obj_elf_tls_common (int);
+static void obj_elf_sharable_common (int);
static void obj_elf_lcomm (int);
static void obj_elf_struct (int);
@@ -97,6 +99,7 @@
{"type", obj_elf_type, 0},
{"version", obj_elf_version, 0},
{"weak", obj_elf_weak, 0},
+ {"secondary", obj_elf_secondary, 0},
/* These define symbol visibility. */
{"internal", obj_elf_visibility, STV_INTERNAL},
@@ -136,6 +139,8 @@
{"tls_common", obj_elf_tls_common, 0},
+ {"sharable_common", obj_elf_sharable_common, 0},
+
/* End sentinel. */
{NULL, NULL, 0},
};
@@ -391,6 +396,39 @@
}
static void
+obj_elf_sharable_common (int ignore ATTRIBUTE_UNUSED)
+{
+ static segT sharable_bss_section;
+ asection *saved_com_section_ptr = elf_com_section_ptr;
+ asection *saved_bss_section = bss_section;
+
+ if (sharable_bss_section == NULL)
+ {
+ flagword applicable;
+ segT seg = now_seg;
+ subsegT subseg = now_subseg;
+
+ /* The .sharable_bss section is for local .sharable_common
+ symbols. */
+ sharable_bss_section = subseg_new (".sharable_bss", 0);
+ applicable = bfd_applicable_section_flags (stdoutput);
+ bfd_set_section_flags (stdoutput, sharable_bss_section,
+ applicable & SEC_ALLOC);
+ seg_info (sharable_bss_section)->bss = 1;
+
+ subseg_set (seg, subseg);
+ }
+
+ elf_com_section_ptr = &_bfd_elf_sharable_com_section;
+ bss_section = sharable_bss_section;
+
+ s_comm_internal (0, elf_common_parse);
+
+ elf_com_section_ptr = saved_com_section_ptr;
+ bss_section = saved_bss_section;
+}
+
+static void
obj_elf_lcomm (int ignore ATTRIBUTE_UNUSED)
{
symbolS *symbolP = s_comm_internal (0, s_lcomm_internal);
@@ -443,6 +481,29 @@
}
static void
+obj_elf_secondary (int ignore ATTRIBUTE_UNUSED)
+{
+ int c;
+ symbolS *symbolP;
+
+ do
+ {
+ symbolP = get_sym_from_input_line_and_check ();
+ c = *input_line_pointer;
+ S_SET_SECONDARY (symbolP);
+ if (c == ',')
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\n')
+ c = '\n';
+ }
+ }
+ while (c == ',');
+ demand_empty_rest_of_line ();
+}
+
+static void
obj_elf_weak (int ignore ATTRIBUTE_UNUSED)
{
int c;
@@ -452,7 +513,8 @@
{
symbolP = get_sym_from_input_line_and_check ();
c = *input_line_pointer;
- S_SET_WEAK (symbolP);
+ if (!S_IS_SECONDARY (symbolP))
+ S_SET_WEAK (symbolP);
if (c == ',')
{
input_line_pointer++;
@@ -609,11 +671,17 @@
.section .lbss,"aw",@progbits
+ "@progbits" is incorrect. Also for sharable bss
+ sections, gcc, as of 2005-07-06, will emit
+
+ .section .sharable_bss,"aw",@progbits
+
"@progbits" is incorrect. */
#ifdef TC_I386
&& (bed->s->arch_size != 64
|| !(ssect->attr & SHF_X86_64_LARGE))
#endif
+ && !(ssect->attr & SHF_GNU_SHARABLE)
&& ssect->type != SHT_INIT_ARRAY
&& ssect->type != SHT_FINI_ARRAY
&& ssect->type != SHT_PREINIT_ARRAY)
@@ -2194,18 +2262,24 @@
if (S_IS_WEAK (symp))
S_SET_WEAK (symp2);
+ if (S_IS_SECONDARY (symp))
+ S_SET_SECONDARY (symp2);
+
if (S_IS_EXTERNAL (symp))
S_SET_EXTERNAL (symp2);
}
}
}
- /* Double check weak symbols. */
- if (S_IS_WEAK (symp))
+ /* Double check weak and secondary symbols. */
+ if (S_IS_COMMON (symp))
{
- if (S_IS_COMMON (symp))
+ if (S_IS_WEAK (symp))
as_bad (_("symbol `%s' can not be both weak and common"),
S_GET_NAME (symp));
+ else if (S_IS_SECONDARY (symp))
+ as_bad (_("symbol `%s' can not be both secondary and common"),
+ S_GET_NAME (symp));
}
#ifdef TC_MIPS
@@ -2419,7 +2493,7 @@
/* If there was .weak foo, but foo was neither defined nor
used anywhere, remove it. */
- else if (S_IS_WEAK (symp)
+ else if ((S_IS_WEAK (symp) || S_IS_SECONDARY (symp))
&& symbol_used_p (symp) == 0
&& symbol_used_in_reloc_p (symp) == 0)
symbol_remove (symp, &symbol_rootP, &symbol_lastP);
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index f93c044..d3dffb9 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -4273,6 +4273,7 @@
* Print:: @code{.print @var{string}}
@ifset ELF
* Protected:: @code{.protected @var{names}}
+* Secondary:: @code{.secondary @var{names}}
@end ifset
* Psize:: @code{.psize @var{lines}, @var{columns}}
@@ -5955,6 +5956,14 @@
components that defines them must be resolved to the definition in that
component, even if a definition in another component would normally preempt
this.
+
+@node Secondary
+@section @code{.secondary @var{names}}
+
+@cindex @code{secondary} directive
+This directive sets the secondary attribute on the comma separated list
+of symbol @code{names}. If the symbols do not already exist, they will
+be created.
@end ifset
@node Psize
diff --git a/gas/symbols.c b/gas/symbols.c
index 6af8604..87f22d6 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -2033,6 +2033,14 @@
}
int
+S_IS_SECONDARY (symbolS *s)
+{
+ if (LOCAL_SYMBOL_CHECK (s))
+ return 0;
+ return (s->bsym->flags & BSF_SECONDARY) != 0;
+}
+
+int
S_IS_WEAKREFR (symbolS *s)
{
if (LOCAL_SYMBOL_CHECK (s))
@@ -2079,7 +2087,7 @@
return ((struct local_symbol *) s)->lsy_section == undefined_section;
return ((strict
- && ((s->bsym->flags & BSF_WEAK) != 0
+ && ((s->bsym->flags & (BSF_WEAK | BSF_SECONDARY)) != 0
|| (EXTERN_FORCE_RELOC
&& (s->bsym->flags & BSF_GLOBAL) != 0)))
|| (s->bsym->flags & BSF_GNU_INDIRECT_FUNCTION) != 0
@@ -2215,9 +2223,9 @@
{
if (LOCAL_SYMBOL_CHECK (s))
s = local_symbol_convert ((struct local_symbol *) s);
- if ((s->bsym->flags & BSF_WEAK) != 0)
+ if ((s->bsym->flags & (BSF_WEAK | BSF_SECONDARY)) != 0)
{
- /* Let .weak override .global. */
+ /* Let .weak/.secondary override .global. */
return;
}
if (s->bsym->flags & BSF_SECTION_SYM)
@@ -2240,7 +2248,7 @@
}
#endif
s->bsym->flags |= BSF_GLOBAL;
- s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK);
+ s->bsym->flags &= ~(BSF_LOCAL | BSF_WEAK | BSF_SECONDARY);
#ifdef TE_PE
if (! an_external_name && S_GET_NAME(s)[0] != '.')
@@ -2253,13 +2261,13 @@
{
if (LOCAL_SYMBOL_CHECK (s))
return;
- if ((s->bsym->flags & BSF_WEAK) != 0)
+ if ((s->bsym->flags & (BSF_WEAK | BSF_SECONDARY)) != 0)
{
- /* Let .weak override. */
+ /* Let .weak/.secondary override. */
return;
}
s->bsym->flags |= BSF_LOCAL;
- s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK);
+ s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK | BSF_SECONDARY);
}
void
@@ -2271,7 +2279,16 @@
obj_set_weak_hook (s);
#endif
s->bsym->flags |= BSF_WEAK;
- s->bsym->flags &= ~(BSF_GLOBAL | BSF_LOCAL);
+ s->bsym->flags &= ~(BSF_GLOBAL | BSF_SECONDARY | BSF_LOCAL);
+}
+
+void
+S_SET_SECONDARY (symbolS *s)
+{
+ if (LOCAL_SYMBOL_CHECK (s))
+ s = local_symbol_convert ((struct local_symbol *) s);
+ s->bsym->flags |= BSF_SECONDARY;
+ s->bsym->flags &= ~(BSF_GLOBAL | BSF_WEAK | BSF_LOCAL);
}
void
@@ -2328,6 +2345,12 @@
s->bsym->flags &= ~BSF_WEAK;
s->bsym->flags |= BSF_LOCAL;
}
+ /* The same applies to secondary symbol. */
+ else if (s->bsym->flags & BSF_SECONDARY)
+ {
+ s->bsym->flags &= ~BSF_SECONDARY;
+ s->bsym->flags |= BSF_LOCAL;
+ }
}
}
diff --git a/gas/symbols.h b/gas/symbols.h
index 4c83033..f765aec 100644
--- a/gas/symbols.h
+++ b/gas/symbols.h
@@ -91,6 +91,7 @@
extern int S_IS_FUNCTION (symbolS *);
extern int S_IS_EXTERNAL (symbolS *);
extern int S_IS_WEAK (symbolS *);
+extern int S_IS_SECONDARY (symbolS *);
extern int S_IS_WEAKREFR (symbolS *);
extern int S_IS_WEAKREFD (symbolS *);
extern int S_IS_COMMON (symbolS *);
@@ -109,6 +110,7 @@
extern void S_SET_NAME (symbolS *, const char *);
extern void S_CLEAR_EXTERNAL (symbolS *);
extern void S_SET_WEAK (symbolS *);
+extern void S_SET_SECONDARY (symbolS *);
extern void S_SET_WEAKREFR (symbolS *);
extern void S_CLEAR_WEAKREFR (symbolS *);
extern void S_SET_WEAKREFD (symbolS *);
diff --git a/gas/testsuite/gas/elf/common3.d b/gas/testsuite/gas/elf/common3.d
new file mode 100644
index 0000000..e73f6c5
--- /dev/null
+++ b/gas/testsuite/gas/elf/common3.d
@@ -0,0 +1,2 @@
+#name: secondary and common directives
+#error-output: common3.l
diff --git a/gas/testsuite/gas/elf/common3.l b/gas/testsuite/gas/elf/common3.l
new file mode 100644
index 0000000..58d5142
--- /dev/null
+++ b/gas/testsuite/gas/elf/common3.l
@@ -0,0 +1,2 @@
+[^:]*: Assembler messages:
+[^:]*: Error: symbol `foobar' can not be both secondary and common
diff --git a/gas/testsuite/gas/elf/common3.s b/gas/testsuite/gas/elf/common3.s
new file mode 100644
index 0000000..df8b7ed
--- /dev/null
+++ b/gas/testsuite/gas/elf/common3.s
@@ -0,0 +1,2 @@
+ .secondary foobar
+ .comm foobar,30
diff --git a/gas/testsuite/gas/elf/common4.d b/gas/testsuite/gas/elf/common4.d
new file mode 100644
index 0000000..aca59c0
--- /dev/null
+++ b/gas/testsuite/gas/elf/common4.d
@@ -0,0 +1,2 @@
+#name: common and secondary directives
+#error-output: common4.l
diff --git a/gas/testsuite/gas/elf/common4.l b/gas/testsuite/gas/elf/common4.l
new file mode 100644
index 0000000..58d5142
--- /dev/null
+++ b/gas/testsuite/gas/elf/common4.l
@@ -0,0 +1,2 @@
+[^:]*: Assembler messages:
+[^:]*: Error: symbol `foobar' can not be both secondary and common
diff --git a/gas/testsuite/gas/elf/common4.s b/gas/testsuite/gas/elf/common4.s
new file mode 100644
index 0000000..37bd0ce
--- /dev/null
+++ b/gas/testsuite/gas/elf/common4.s
@@ -0,0 +1,2 @@
+ .comm foobar,30
+ .secondary foobar
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index f17f7e0..65bb3c5 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -203,6 +203,11 @@
run_dump_test "common1"
run_dump_test "common2"
+ run_dump_test "common3"
+ run_dump_test "common4"
+
+ run_elf_list_test "secondary1" "" "" "-s" "| grep \"secondary_\""
+ run_elf_list_test "secondary2" "" "" "-s" "| grep \"secondary_\""
load_lib gas-dg.exp
dg-init
diff --git a/gas/testsuite/gas/elf/secondary1.e b/gas/testsuite/gas/elf/secondary1.e
new file mode 100644
index 0000000..da00dfb
--- /dev/null
+++ b/gas/testsuite/gas/elf/secondary1.e
@@ -0,0 +1,4 @@
+ +.: 0+0 +1 +FUNC +SECOND +DEFAULT +. secondary_function1
+ +.: 0+1 +1 +FUNC +SECOND +DEFAULT +. secondary_function2
+ +.: 0+0 +1 +OBJECT +SECOND +DEFAULT +. secondary_object1
+ +.: 0+1 +1 +OBJECT +SECOND +DEFAULT +. secondary_object2
diff --git a/gas/testsuite/gas/elf/secondary1.s b/gas/testsuite/gas/elf/secondary1.s
new file mode 100644
index 0000000..6a3032d
--- /dev/null
+++ b/gas/testsuite/gas/elf/secondary1.s
@@ -0,0 +1,33 @@
+ .text
+
+ .size secondary_function1,1
+ .secondary secondary_function1
+ .weak secondary_function1
+ .type secondary_function1,%function
+secondary_function1:
+ .byte 0x0
+ .size secondary_function1,1
+
+ .size secondary_function2,1
+ .weak secondary_function2
+ .secondary secondary_function2
+ .type secondary_function2,%function
+secondary_function2:
+ .byte 0x0
+ .size secondary_function2,1
+
+
+ .data
+ .type secondary_object1,%object
+ .weak secondary_object1
+ .secondary secondary_object1
+secondary_object1:
+ .byte 0x0
+ .size secondary_object1,1
+
+ .type secondary_object2,%object
+ .weak secondary_object2
+ .secondary secondary_object2
+secondary_object2:
+ .byte 0x0
+ .size secondary_object2,1
diff --git a/gas/testsuite/gas/elf/secondary2.e b/gas/testsuite/gas/elf/secondary2.e
new file mode 100644
index 0000000..0470eb8
--- /dev/null
+++ b/gas/testsuite/gas/elf/secondary2.e
@@ -0,0 +1 @@
+ +.: 0+ +0 +[A-Z]+ +WEAK +DEFAULT +UND secondary_function
diff --git a/gas/testsuite/gas/elf/secondary2.s b/gas/testsuite/gas/elf/secondary2.s
new file mode 100644
index 0000000..234330a
--- /dev/null
+++ b/gas/testsuite/gas/elf/secondary2.s
@@ -0,0 +1,5 @@
+ .text
+ .secondary secondary_function
+ .dc.a secondary_function
+ .data
+ .secondary secondary_object
diff --git a/gas/testsuite/gas/elf/section9.d b/gas/testsuite/gas/elf/section9.d
index 1acf63e..bb66fa5 100644
--- a/gas/testsuite/gas/elf/section9.d
+++ b/gas/testsuite/gas/elf/section9.d
@@ -4,4 +4,5 @@
#...
[ ]*\[.*\][ ]+\.gnu\.lto_main[ ]+PROGBITS.*[ ]+E[ ]+.*
[ ]*\[.*\][ ]+\.gnu\.lto_\.pureconst[ ]+PROGBITS.*[ ]+E[ ]+.*
+[ ]*\[.*\][ ]+\.gnu_object_only[ ]+GNU_OBJECT_ONLY.*[ ]+E[ ]+.*
#pass
diff --git a/gas/testsuite/gas/elf/section9.s b/gas/testsuite/gas/elf/section9.s
index 6b8b107..abcdea1 100644
--- a/gas/testsuite/gas/elf/section9.s
+++ b/gas/testsuite/gas/elf/section9.s
@@ -2,3 +2,5 @@
.byte 0,0,0,0
.section .gnu.lto_.pureconst,"",%progbits
.byte 0,0,0,0
+ .section .gnu_object_only
+ .byte 0,0,0,0
diff --git a/gas/testsuite/gas/elf/type.e b/gas/testsuite/gas/elf/type.e
index a1159bf..d4c0548 100644
--- a/gas/testsuite/gas/elf/type.e
+++ b/gas/testsuite/gas/elf/type.e
@@ -3,5 +3,7 @@
+.+: 0+0 +1 +OBJECT +LOCAL +DEFAULT +. object
+.+: 0+1 +1 +TLS +LOCAL +DEFAULT +. tls_object
+.+: 0+2 +1 +NOTYPE +LOCAL +DEFAULT +. notype
+ +.+: 0+2 +1 +FUNC +SECOND +DEFAULT +. secondary_function
+.+: 0+3 +1 +OBJECT +UNIQUE +DEFAULT +. unique_global
+ +.+: 0+4 +1 +OBJECT +SECOND +DEFAULT +. secondary_object
+.+: 0+1 +1 +(COMMON|OBJECT) +GLOBAL +DEFAULT +COM common
diff --git a/gas/testsuite/gas/elf/type.s b/gas/testsuite/gas/elf/type.s
index d0a1afd..bd7df2c 100644
--- a/gas/testsuite/gas/elf/type.s
+++ b/gas/testsuite/gas/elf/type.s
@@ -10,6 +10,12 @@
indirect_function:
.byte 0x0
+ .size secondary_function,1
+ .secondary secondary_function
+ .type secondary_function,%function
+secondary_function:
+ .byte 0x0
+
.data
.type object,%object
@@ -32,6 +38,11 @@
.byte 0x0
.size unique_global,1
+ .type secondary_object,%object
+ .secondary secondary_object
+secondary_object:
+ .byte 0x0
+ .size secondary_object,1
+
.comm common, 1
.type common,STT_COMMON
-
\ No newline at end of file
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 125683d..d7976d6 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -93,6 +93,9 @@
unsigned int non_ir_ref : 1;
+ /* Set if it is a secondary symbol. */
+ unsigned int secondary : 1;
+
/* A union of information depending upon the type. */
union
{
@@ -355,6 +358,9 @@
/* TRUE if .gnu.hash section should be created. */
unsigned int emit_gnu_hash: 1;
+ /* TRUE if secondary symbols should be generated. */
+ unsigned int emit_secondary: 1;
+
/* If TRUE reduce memory overheads, at the expense of speed. This will
cause map file generation to use an O(N^2) algorithm and disable
caching ELF symbol buffer. */
@@ -389,6 +395,12 @@
/* 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;
@@ -396,6 +408,9 @@
--dynamic-list command line options. */
unsigned int dynamic: 1;
+ /* TRUE if sharables sections may be created. */
+ unsigned int sharable_sections: 1;
+
/* TRUE if PT_GNU_STACK segment should be created with PF_R|PF_W|PF_X
flags. */
unsigned int execstack: 1;
diff --git a/include/elf/common.h b/include/elf/common.h
index e8ae3ac..e2dd96d 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -434,6 +434,7 @@
#define PT_SUNW_EH_FRAME PT_GNU_EH_FRAME /* Solaris uses the same value */
#define PT_GNU_STACK (PT_LOOS + 0x474e551) /* Stack flags */
#define PT_GNU_RELRO (PT_LOOS + 0x474e552) /* Read-only after relocation */
+#define PT_GNU_SHR (PT_LOOS + 0x474e554) /* Sharable segment */
/* Program segment permissions, in program header p_flags field. */
@@ -472,6 +473,7 @@
#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*
@@ -516,6 +518,8 @@
are not to be further
relocated. */
+#define SHF_GNU_SHARABLE 0x01000000 /* sharable section */
+
/* Values of note segment descriptor types for core files. */
#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
@@ -664,6 +668,7 @@
#define STB_LOCAL 0 /* Symbol not visible outside obj */
#define STB_GLOBAL 1 /* Symbol visible outside obj */
#define STB_WEAK 2 /* Like globals, lower precedence */
+#define STB_SECONDARY 3 /* Like weaks, lower precedence */
#define STB_LOOS 10 /* OS-specific semantics */
#define STB_GNU_UNIQUE 10 /* Symbol is unique in namespace */
#define STB_HIOS 12 /* OS-specific semantics */
@@ -685,6 +690,9 @@
#define STT_LOPROC 13 /* Processor-specific semantics */
#define STT_HIPROC 15 /* Processor-specific semantics */
+/* Associated symbol is in common sharable */
+#define SHN_GNU_SHARABLE_COMMON (SHN_LOOS + 10)
+
/* The following constants control how a symbol may be accessed once it has
become part of an executable or shared library. */
diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
index 11d17ad..012ca78 100644
--- a/ld/emulparams/elf32_x86_64.sh
+++ b/ld/emulparams/elf32_x86_64.sh
@@ -16,6 +16,7 @@
LARGE_BSS_AFTER_BSS=
SEPARATE_GOTPLT="SIZEOF (.got.plt) >= 24 ? 24 : 0"
IREL_IN_PLT=
+SHARABLE_SECTIONS=yes
if [ "x${host}" = "x${target}" ]; then
case " $EMULATION_LIBPATH " in
diff --git a/ld/emulparams/elf64_ia64.sh b/ld/emulparams/elf64_ia64.sh
index 7e5e54d..d8cf531 100644
--- a/ld/emulparams/elf64_ia64.sh
+++ b/ld/emulparams/elf64_ia64.sh
@@ -37,3 +37,4 @@
# .dtors. They have to be next to .sbss/.sbss2/.sdata/.sdata2.
SMALL_DATA_CTOR=" "
SMALL_DATA_DTOR=" "
+SHARABLE_SECTIONS=yes
diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh
index 93f1992..31df4b6 100644
--- a/ld/emulparams/elf_i386.sh
+++ b/ld/emulparams/elf_i386.sh
@@ -13,6 +13,7 @@
NO_SMALL_DATA=yes
SEPARATE_GOTPLT="SIZEOF (.got.plt) >= 12 ? 12 : 0"
IREL_IN_PLT=
+SHARABLE_SECTIONS=yes
# Linux modify the default library search path to first include
# a 32-bit specific directory.
diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
index d8cb6bf..0ef63e4 100644
--- a/ld/emulparams/elf_x86_64.sh
+++ b/ld/emulparams/elf_x86_64.sh
@@ -18,6 +18,7 @@
IREL_IN_PLT=
# Reuse TINY_READONLY_SECTION which is placed right after .plt section.
TINY_READONLY_SECTION=".plt.bnd ${RELOCATING-0} : { *(.plt.bnd) }"
+SHARABLE_SECTIONS=yes
if [ "x${host}" = "x${target}" ]; then
case " $EMULATION_LIBPATH " in
diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em
index bb58901..1382596 100644
--- a/ld/emultempl/aarch64elf.em
+++ b/ld/emultempl/aarch64elf.em
@@ -269,7 +269,7 @@
}
static void
-gld${EMULATION_NAME}_finish (void)
+aarch64_finish (void)
{
if (! link_info.relocatable)
{
@@ -281,7 +281,7 @@
}
}
- finish_default ();
+ gld${EMULATION_NAME}_finish ();
}
/* This is a convenient point to tell BFD about target specific flags.
@@ -418,4 +418,4 @@
LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
# Call the extra arm-elf function
-LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+LDEMUL_FINISH=aarch64_finish
diff --git a/ld/emultempl/alphaelf.em b/ld/emultempl/alphaelf.em
index a36fc7d..2d4a9f6 100644
--- a/ld/emultempl/alphaelf.em
+++ b/ld/emultempl/alphaelf.em
@@ -100,7 +100,7 @@
if (limit_32bit)
elf_elfheader (link_info.output_bfd)->e_flags |= EF_ALPHA_32BIT;
- finish_default ();
+ gld${EMULATION_NAME}_finish ();
}
EOF
diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
index 1dde019..4388fdb 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -370,7 +370,7 @@
}
static void
-gld${EMULATION_NAME}_finish (void)
+arm_finish (void)
{
struct bfd_link_hash_entry * h;
@@ -393,7 +393,7 @@
}
}
- finish_default ();
+ gld${EMULATION_NAME}_finish ();
if (thumb_entry_symbol)
{
@@ -702,4 +702,4 @@
LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
# Call the extra arm-elf function
-LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+LDEMUL_FINISH=arm_finish
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 67c437d..2339ca3 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -65,6 +65,7 @@
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
@@ -102,6 +103,7 @@
input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
+ link_info.sharable_sections = `if test "$SHARABLE_SECTIONS" = "yes" ; then echo TRUE ; else echo FALSE ; fi`;
}
EOF
@@ -1729,6 +1731,8 @@
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. */
@@ -1737,7 +1741,7 @@
const char *secname,
int constraint)
{
- static struct orphan_save hold[] =
+ static struct orphan_save orig_hold[] =
{
{ ".text",
SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
@@ -1767,6 +1771,7 @@
SEC_HAS_CONTENTS,
0, 0, 0, 0 },
};
+ static struct orphan_save hold[ARRAY_SIZE (orig_hold)];
enum orphan_save_index
{
orphan_text = 0,
@@ -1779,7 +1784,6 @@
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;
@@ -1788,6 +1792,12 @@
int iself = s->owner->xvec->flavour == bfd_target_elf_flavour;
unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL;
+ /* Orphaned sharable sections won't have correct page
+ requirements. */
+ if (elf_section_flags (s) & SHF_GNU_SHARABLE)
+ einfo ("%F%P: unable to place orphaned sharable section %A (%B)\n",
+ s, s->owner);
+
if (! link_info.relocatable
&& link_info.combreloc
&& (s->flags & SEC_ALLOC))
@@ -1856,15 +1866,22 @@
if (!orphan_init_done)
{
- struct orphan_save *ho;
+ 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;
}
@@ -1936,6 +1953,27 @@
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
@@ -2326,6 +2364,8 @@
link_info.error_textrel = FALSE;
else if (strcmp (optarg, "textoff") == 0)
link_info.error_textrel = FALSE;
+ else if (strcmp (optarg, "nosecondary") == 0)
+ link_info.emit_secondary = FALSE;
EOF
fi
@@ -2453,6 +2493,8 @@
-z relro Create RELRO program header\n"));
fprintf (file, _("\
-z stacksize=SIZE Set size of stack segment\n"));
+ fprintf (file, _("\
+ -z nosecondary Convert secondary symbols to weak symbols\n"));
EOF
fi
@@ -2489,7 +2531,7 @@
${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
"${EMULATION_NAME}",
"${OUTPUT_FORMAT}",
- ${LDEMUL_FINISH-finish_default},
+ ${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 --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em
index 914fc52..23d592c 100644
--- a/ld/emultempl/ppc64elf.em
+++ b/ld/emultempl/ppc64elf.em
@@ -523,7 +523,7 @@
/* Final emulation specific call. */
static void
-gld${EMULATION_NAME}_finish (void)
+ppc_finish (void)
{
char *msg = NULL;
char *line, *endline;
@@ -554,7 +554,7 @@
free (msg);
ppc64_elf_restore_symbols (&link_info);
- finish_default ();
+ gld${EMULATION_NAME}_finish ();
}
@@ -876,6 +876,6 @@
#
LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation
LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
-LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+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 --git a/ld/emultempl/spuelf.em b/ld/emultempl/spuelf.em
index 1b4d72f..8c8090c 100644
--- a/ld/emultempl/spuelf.em
+++ b/ld/emultempl/spuelf.em
@@ -416,7 +416,7 @@
/* Final emulation specific call. */
static void
-gld${EMULATION_NAME}_finish (void)
+spu_finish (void)
{
if (is_spu_target ())
{
@@ -432,7 +432,7 @@
einfo ("%P: --auto-overlay ignored with zero local store range\n");
}
- finish_default ();
+ gld${EMULATION_NAME}_finish ();
}
static char *
@@ -832,5 +832,5 @@
LDEMUL_AFTER_OPEN=spu_after_open
LDEMUL_BEFORE_ALLOCATION=spu_before_allocation
-LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+LDEMUL_FINISH=spu_finish
LDEMUL_CHOOSE_TARGET=gld${EMULATION_NAME}_choose_target
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index e71be5e..30dddd4 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1121,6 +1121,10 @@
@item relro
Create an ELF @code{PT_GNU_RELRO} segment header in the object.
+@item nosecondary
+Convert secondary symbols to weak symbols when generating a shared
+library.
+
@item max-page-size=@var{value}
Set the emulation maximum page size to @var{value}.
diff --git a/ld/ldfile.c b/ld/ldfile.c
index 782ed7f..ead7345 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -317,7 +317,9 @@
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 --git a/ld/ldlang.c b/ld/ldlang.c
index 899f710..342a547 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -36,6 +36,7 @@
#include "ldctor.h"
#include "ldfile.h"
#include "ldemul.h"
+#include "ldwrite.h"
#include "fnmatch.h"
#include "demangle.h"
#include "hashtab.h"
@@ -45,6 +46,9 @@
#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
@@ -69,6 +73,9 @@
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 *);
@@ -88,6 +95,10 @@
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;
@@ -1201,14 +1212,17 @@
/* Build enough state so that the parser can build its tree. */
void
-lang_init (void)
+lang_init (bfd_boolean object_only)
{
- obstack_begin (&stat_obstack, 1000);
+ 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);
@@ -1223,10 +1237,11 @@
/* 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),
+ 13))
einfo (_("%P%F: can not create hash table: %E\n"));
asneeded_list_head = NULL;
@@ -1234,9 +1249,10 @@
}
void
-lang_finish (void)
+lang_finish (bfd_boolean object_only)
{
- bfd_hash_table_free (&lang_definedness_table);
+ if (!object_only)
+ bfd_hash_table_free (&lang_definedness_table);
output_section_statement_table_free ();
}
@@ -2820,6 +2836,12 @@
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,
@@ -6721,7 +6743,38 @@
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 (verbose
+ && (cmdline_object_only_file_list.head
+ || cmdline_object_only_archive_list.head))
+ {
+ info_msg (_("Object-only input files:\n "));
+ 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)
@@ -8123,3 +8176,963 @@
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);
+
+ /* 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;
+ 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 ();
+
+ 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 --git a/ld/ldlang.h b/ld/ldlang.h
index 5f6faae..0b334e0 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -523,9 +523,9 @@
extern void (*output_bfd_hash_table_free_fn) (struct bfd_link_hash_table *);
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
@@ -698,4 +698,45 @@
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 --git a/ld/ldlex.h b/ld/ldlex.h
index 63f4c81..2019bc3 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -133,6 +133,7 @@
#ifdef ENABLE_PLUGINS
OPTION_PLUGIN,
OPTION_PLUGIN_OPT,
+ OPTION_PLUGIN_SAVE_TEMPS,
#endif /* ENABLE_PLUGINS */
OPTION_DEFAULT_SCRIPT,
OPTION_PRINT_OUTPUT_FORMAT,
diff --git a/ld/ldmain.c b/ld/ldmain.c
index bc24957..e7a4296 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -220,6 +220,9 @@
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)
@@ -279,6 +282,7 @@
link_info.combreloc = TRUE;
link_info.strip_discarded = TRUE;
link_info.emit_hash = TRUE;
+ link_info.emit_secondary = TRUE;
link_info.callbacks = &link_callbacks;
link_info.input_bfds_tail = &link_info.input_bfds;
/* SVR4 linkers seem to set DT_INIT and DT_FINI based on magic _init
@@ -289,6 +293,7 @@
link_info.pei386_auto_import = -1;
link_info.spare_dynamic_tags = 5;
link_info.path_separator = ':';
+ link_info.sharable_sections = FALSE;
ldfile_add_arch ("");
emulation = get_emulation (argc, argv);
@@ -296,7 +301,7 @@
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 ();
+ lang_init (FALSE);
ldemul_before_parse ();
lang_has_input_file = FALSE;
parse_args (argc, argv);
@@ -311,34 +316,7 @@
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;
- }
+ ld_parse_linker_script ();
if (verbose)
{
@@ -440,7 +418,7 @@
fprintf (stderr, "lookup = %p val %lx\n", h, h ? h->u.def.value : 1);
}
#endif
- lang_finish ();
+ lang_finish (FALSE);
/* Even if we're producing relocatable output, some non-fatal errors should
be reported in the exit status. (What non-fatal errors, if any, do we
@@ -459,6 +437,8 @@
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. */
@@ -505,6 +485,9 @@
}
}
+ if (link_info.emit_gnu_object_only)
+ cmdline_emit_object_only_section ();
+
END_PROGRESS (program_name);
if (config.stats)
@@ -814,7 +797,9 @@
}
}
}
+ else
#endif /* ENABLE_PLUGINS */
+ cmdline_check_object_only_section (input->the_bfd, FALSE);
ldlang_add_file (input);
@@ -1493,3 +1478,38 @@
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 --git a/ld/ldmain.h b/ld/ldmain.h
index dce9650..5c1efc3 100644
--- a/ld/ldmain.h
+++ b/ld/ldmain.h
@@ -59,4 +59,6 @@
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 --git a/ld/lexsup.c b/ld/lexsup.c
index 3a1ea9e..a0612e1 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -166,6 +166,9 @@
'\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 },
@@ -971,6 +974,9 @@
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 --git a/ld/plugin.c b/ld/plugin.c
index f02a97f..0a16644 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -39,6 +39,9 @@
/* 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. */
@@ -882,6 +885,9 @@
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
@@ -935,14 +941,17 @@
{
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);
+ 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 --git a/ld/plugin.h b/ld/plugin.h
index bccbee3..483519e 100644
--- a/ld/plugin.h
+++ b/ld/plugin.h
@@ -24,6 +24,9 @@
/* 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 --git a/ld/scripttempl/armbpabi.sc b/ld/scripttempl/armbpabi.sc
index b910847..693f4cf 100644
--- a/ld/scripttempl/armbpabi.sc
+++ b/ld/scripttempl/armbpabi.sc
@@ -36,7 +36,7 @@
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_*) }"
+DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
if test -z "${NO_SMALL_DATA}"; then
SBSS=".sbss ${RELOCATING-0} :
{
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
index 4368fd9..9cbaf6a 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -165,7 +165,7 @@
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_*) }"
+DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
if test -z "${NO_SMALL_DATA}"; then
SBSS=".${SBSS_NAME} ${RELOCATING-0} :
{
@@ -303,6 +303,40 @@
${RELOCATING+${USER_LABEL_PREFIX}_stack = .;}
*(.stack)
}"
+test "${SHARABLE_SECTIONS}" = "yes" && OTHER_READWRITE_SECTIONS="
+ ${OTHER_READWRITE_SECTIONS}
+ /* Sharable data sections. */
+ .sharable_data ${RELOCATING-0} : ${RELOCATING+ALIGN(${MAXPAGESIZE})}
+ {
+ ${RELOCATING+PROVIDE_HIDDEN (__sharable_data_start = .);}
+ *(.sharable_data${RELOCATING+ .sharable_data.* .gnu.linkonce.shrd.*})
+ /* Align here to ensure that the sharable data section ends at the
+ page boundary. */
+ ${RELOCATING+. = ALIGN(. != 0 ? ${MAXPAGESIZE} : 1);}
+ ${RELOCATING+PROVIDE_HIDDEN (__sharable_data_end = .);}
+ }
+"
+test "${SHARABLE_SECTIONS}" = "yes" && OTHER_BSS_SECTIONS="
+ ${OTHER_BSS_SECTIONS}
+ /* Sharable bss sections */
+ .sharable_bss ${RELOCATING-0} : ${RELOCATING+ALIGN(${MAXPAGESIZE})}
+ {
+ ${RELOCATING+PROVIDE_HIDDEN (__sharable_bss_start = .);}
+ *(.dynsharablebss)
+ *(.sharable_bss${RELOCATING+ .sharable_bss.* .gnu.linkonce.shrb.*})
+ *(SHARABLE_COMMON)
+ /* Align here to ensure that the sharable bss section ends at the
+ page boundary. */
+ ${RELOCATING+. = ALIGN(. != 0 ? ${MAXPAGESIZE} : 1);}
+ ${RELOCATING+PROVIDE_HIDDEN (__sharable_bss_end = .);}
+ }
+"
+test "${SHARABLE_SECTIONS}" = "yes" && REL_SHARABLE="
+ .rel.sharable_data ${RELOCATING-0} : { *(.rel.sharable_data${RELOCATING+ .rel.sharable_data.* .rel.gnu.linkonce.shrd.*}) }
+ .rela.sharable_data ${RELOCATING-0} : { *(.rela.sharable_data${RELOCATING+ .rela.sharable_data.* .rela.gnu.linkonce.shrd.*}) }
+ .rel.sharable_bss ${RELOCATING-0} : { *(.rel.sharable_bss${RELOCATING+ .rel.sharable_bss.* .rel.gnu.linkonce.shrb.*}) }
+ .rela.sharable_bss ${RELOCATING-0} : { *(.rela.sharable_bss${RELOCATING+ .rela.sharable_bss.* .rela.gnu.linkonce.shrb.*}) }
+"
TEXT_START_ADDR="SEGMENT_START(\"text-segment\", ${TEXT_START_ADDR})"
SHLIB_TEXT_START_ADDR="SEGMENT_START(\"text-segment\", ${SHLIB_TEXT_START_ADDR:-0})"
@@ -403,6 +437,7 @@
.rel.got ${RELOCATING-0} : { *(.rel.got) }
.rela.got ${RELOCATING-0} : { *(.rela.got) }
${OTHER_GOT_RELOC_SECTIONS}
+ ${REL_SHARABLE}
${REL_SDATA}
${REL_SBSS}
${REL_SDATA2}
diff --git a/ld/scripttempl/elf32sh-symbian.sc b/ld/scripttempl/elf32sh-symbian.sc
index 8e66e69..6d83d6e 100644
--- a/ld/scripttempl/elf32sh-symbian.sc
+++ b/ld/scripttempl/elf32sh-symbian.sc
@@ -88,7 +88,7 @@
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_*) }"
+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 --git a/ld/scripttempl/elf64hppa.sc b/ld/scripttempl/elf64hppa.sc
index 59bcb05..8e18b43 100644
--- a/ld/scripttempl/elf64hppa.sc
+++ b/ld/scripttempl/elf64hppa.sc
@@ -132,7 +132,7 @@
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_*) }"
+DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
if test -z "${NO_SMALL_DATA}"; then
SBSS=".sbss ${RELOCATING-0} :
{
diff --git a/ld/scripttempl/elfxtensa.sc b/ld/scripttempl/elfxtensa.sc
index 5c577ce..7e045a0 100644
--- a/ld/scripttempl/elfxtensa.sc
+++ b/ld/scripttempl/elfxtensa.sc
@@ -145,7 +145,7 @@
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_*) }"
+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 --git a/ld/scripttempl/mep.sc b/ld/scripttempl/mep.sc
index ac4d88d..6bf84aa 100644
--- a/ld/scripttempl/mep.sc
+++ b/ld/scripttempl/mep.sc
@@ -119,7 +119,7 @@
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_*) }"
+DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu_object_only) }"
if test -z "${NO_SMALL_DATA}"; then
SBSS=".sbss ${RELOCATING-0} :
{
diff --git a/ld/scripttempl/pe.sc b/ld/scripttempl/pe.sc
index 7c9fc88..66d80eb 100644
--- a/ld/scripttempl/pe.sc
+++ b/ld/scripttempl/pe.sc
@@ -165,6 +165,7 @@
*(.drectve)
${RELOCATING+ *(.note.GNU-stack)}
${RELOCATING+ *(.gnu.lto_*)}
+ ${RELOCATING+ *(.gnu_object_only)}
}
.idata ${RELOCATING+BLOCK(__section_alignment__)} :
diff --git a/ld/scripttempl/pep.sc b/ld/scripttempl/pep.sc
index 71f9b48..a78fb8f 100644
--- a/ld/scripttempl/pep.sc
+++ b/ld/scripttempl/pep.sc
@@ -170,6 +170,7 @@
*(.drectve)
${RELOCATING+ *(.note.GNU-stack)}
${RELOCATING+ *(.gnu.lto_*)}
+ ${RELOCATING+ *(.gnu_object_only)}
}
.idata ${RELOCATING+BLOCK(__section_alignment__)} :
diff --git a/ld/testsuite/ld-cris/weakref3.d b/ld/testsuite/ld-cris/weakref3.d
index aea3ad6..4807106 100644
--- a/ld/testsuite/ld-cris/weakref3.d
+++ b/ld/testsuite/ld-cris/weakref3.d
@@ -16,11 +16,11 @@
#...
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.
diff --git a/ld/testsuite/ld-cris/weakref4.d b/ld/testsuite/ld-cris/weakref4.d
index 79de291..aed0f39 100644
--- a/ld/testsuite/ld-cris/weakref4.d
+++ b/ld/testsuite/ld-cris/weakref4.d
@@ -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.
diff --git a/ld/testsuite/ld-elf/library1.c b/ld/testsuite/ld-elf/library1.c
new file mode 100644
index 0000000..28e255d
--- /dev/null
+++ b/ld/testsuite/ld-elf/library1.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+void
+bar (void)
+{
+#ifdef SHARED
+ printf ("library bar (SHARED)\n");
+#else
+ printf ("library bar\n");
+#endif
+}
diff --git a/ld/testsuite/ld-elf/library1.out b/ld/testsuite/ld-elf/library1.out
new file mode 100644
index 0000000..2050e74
--- /dev/null
+++ b/ld/testsuite/ld-elf/library1.out
@@ -0,0 +1 @@
+library bar
diff --git a/ld/testsuite/ld-elf/library2.c b/ld/testsuite/ld-elf/library2.c
new file mode 100644
index 0000000..271ebd6
--- /dev/null
+++ b/ld/testsuite/ld-elf/library2.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+void
+__attribute__((weak))
+bar (void)
+{
+#ifdef SHARED
+ printf ("weak library bar (SHARED)\n");
+#else
+ printf ("weak library bar\n");
+#endif
+}
diff --git a/ld/testsuite/ld-elf/library2.out b/ld/testsuite/ld-elf/library2.out
new file mode 100644
index 0000000..ddd3d10
--- /dev/null
+++ b/ld/testsuite/ld-elf/library2.out
@@ -0,0 +1 @@
+weak library bar
diff --git a/ld/testsuite/ld-elf/library3.out b/ld/testsuite/ld-elf/library3.out
new file mode 100644
index 0000000..881856e
--- /dev/null
+++ b/ld/testsuite/ld-elf/library3.out
@@ -0,0 +1 @@
+library bar (SHARED)
diff --git a/ld/testsuite/ld-elf/library4.out b/ld/testsuite/ld-elf/library4.out
new file mode 100644
index 0000000..1ff1840
--- /dev/null
+++ b/ld/testsuite/ld-elf/library4.out
@@ -0,0 +1 @@
+weak library bar (SHARED)
diff --git a/ld/testsuite/ld-elf/library5a.c b/ld/testsuite/ld-elf/library5a.c
new file mode 100644
index 0000000..7e44bb4
--- /dev/null
+++ b/ld/testsuite/ld-elf/library5a.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+asm (".secondary bar");
+asm (".weak bar");
+
+void
+bar (void)
+{
+ printf ("secondary bar\n");
+}
+
+void
+xxx (void)
+{
+ printf ("xxx\n");
+}
diff --git a/ld/testsuite/ld-elf/library5b.c b/ld/testsuite/ld-elf/library5b.c
new file mode 100644
index 0000000..f44d97c
--- /dev/null
+++ b/ld/testsuite/ld-elf/library5b.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+extern void bar (void);
+
+void
+foo (void)
+{
+ printf ("foo\n");
+ bar ();
+}
diff --git a/ld/testsuite/ld-elf/library6a.c b/ld/testsuite/ld-elf/library6a.c
new file mode 100644
index 0000000..7de81b3
--- /dev/null
+++ b/ld/testsuite/ld-elf/library6a.c
@@ -0,0 +1,4 @@
+void
+bar (void)
+{
+}
diff --git a/ld/testsuite/ld-elf/library6b.c b/ld/testsuite/ld-elf/library6b.c
new file mode 100644
index 0000000..528fd89
--- /dev/null
+++ b/ld/testsuite/ld-elf/library6b.c
@@ -0,0 +1,7 @@
+extern void bar (void);
+
+void
+xxx (void)
+{
+ bar ();
+}
diff --git a/ld/testsuite/ld-elf/library6c.c b/ld/testsuite/ld-elf/library6c.c
new file mode 100644
index 0000000..60f4b92
--- /dev/null
+++ b/ld/testsuite/ld-elf/library6c.c
@@ -0,0 +1,9 @@
+extern void abort (void);
+
+asm (".secondary bar");
+
+void
+bar (void)
+{
+ abort ();
+}
diff --git a/ld/testsuite/ld-elf/library7a.c b/ld/testsuite/ld-elf/library7a.c
new file mode 100644
index 0000000..10cd8bf
--- /dev/null
+++ b/ld/testsuite/ld-elf/library7a.c
@@ -0,0 +1 @@
+int bar;
diff --git a/ld/testsuite/ld-elf/library7b.c b/ld/testsuite/ld-elf/library7b.c
new file mode 100644
index 0000000..5f67848
--- /dev/null
+++ b/ld/testsuite/ld-elf/library7b.c
@@ -0,0 +1,7 @@
+extern int bar;
+
+int
+xxx (void)
+{
+ return bar;
+}
diff --git a/ld/testsuite/ld-elf/library7c.c b/ld/testsuite/ld-elf/library7c.c
new file mode 100644
index 0000000..aa57fde
--- /dev/null
+++ b/ld/testsuite/ld-elf/library7c.c
@@ -0,0 +1,3 @@
+asm (".secondary bar");
+
+int bar = 3;
diff --git a/ld/testsuite/ld-elf/library8.map b/ld/testsuite/ld-elf/library8.map
new file mode 100644
index 0000000..bcbb4de
--- /dev/null
+++ b/ld/testsuite/ld-elf/library8.map
@@ -0,0 +1,4 @@
+VERS_1 {
+ global: bar; _bar;
+ local: *;
+};
diff --git a/ld/testsuite/ld-elf/library8a.c b/ld/testsuite/ld-elf/library8a.c
new file mode 100644
index 0000000..29a7508
--- /dev/null
+++ b/ld/testsuite/ld-elf/library8a.c
@@ -0,0 +1,10 @@
+#if 1
+asm (".secondary bar");
+#else
+asm (".weak bar");
+#endif
+
+void
+bar (void)
+{
+}
diff --git a/ld/testsuite/ld-elf/library8a.rd b/ld/testsuite/ld-elf/library8a.rd
new file mode 100644
index 0000000..a593fbd
--- /dev/null
+++ b/ld/testsuite/ld-elf/library8a.rd
@@ -0,0 +1,5 @@
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +SECOND +DEFAULT +[0-9]+ +_?bar@@VERS_1
+#...
diff --git a/ld/testsuite/ld-elf/library8b.c b/ld/testsuite/ld-elf/library8b.c
new file mode 100644
index 0000000..7de81b3
--- /dev/null
+++ b/ld/testsuite/ld-elf/library8b.c
@@ -0,0 +1,4 @@
+void
+bar (void)
+{
+}
diff --git a/ld/testsuite/ld-elf/library8b.rd b/ld/testsuite/ld-elf/library8b.rd
new file mode 100644
index 0000000..fc18d1a
--- /dev/null
+++ b/ld/testsuite/ld-elf/library8b.rd
@@ -0,0 +1,5 @@
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +GLOBAL +DEFAULT +[0-9]+ +_?bar@@VERS_1
+#...
diff --git a/ld/testsuite/ld-elf/library8c.c b/ld/testsuite/ld-elf/library8c.c
new file mode 100644
index 0000000..dfb6a22
--- /dev/null
+++ b/ld/testsuite/ld-elf/library8c.c
@@ -0,0 +1,7 @@
+extern void bar ();
+
+void
+foo (void)
+{
+ bar ();
+}
diff --git a/ld/testsuite/ld-elf/library8c.rd b/ld/testsuite/ld-elf/library8c.rd
new file mode 100644
index 0000000..317631f
--- /dev/null
+++ b/ld/testsuite/ld-elf/library8c.rd
@@ -0,0 +1,5 @@
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +0+ +0+ +FUNC +GLOBAL +DEFAULT +UND +_?bar@@VERS_1
+#...
diff --git a/ld/testsuite/ld-elf/pr16496a.c b/ld/testsuite/ld-elf/pr16496a.c
new file mode 100644
index 0000000..35e8555
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr16496a.c
@@ -0,0 +1,4 @@
+void
+sd_get_seats (void)
+{
+}
diff --git a/ld/testsuite/ld-elf/pr16496a.map b/ld/testsuite/ld-elf/pr16496a.map
new file mode 100644
index 0000000..d677f37
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr16496a.map
@@ -0,0 +1,4 @@
+LIBSYSTEMD_209 {
+global:
+ sd_get_seats;
+};
diff --git a/ld/testsuite/ld-elf/pr16496b.c b/ld/testsuite/ld-elf/pr16496b.c
new file mode 100644
index 0000000..94a0f30
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr16496b.c
@@ -0,0 +1,5 @@
+void sd_get_seats (void);
+void call_sd_get_seats (void)
+{
+ sd_get_seats ();
+}
diff --git a/ld/testsuite/ld-elf/pr16496b.od b/ld/testsuite/ld-elf/pr16496b.od
new file mode 100644
index 0000000..6fb54c1
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr16496b.od
@@ -0,0 +1,3 @@
+#...
+.* sd_get_seats@LIBSYSTEMD_209
+#pass
diff --git a/ld/testsuite/ld-elf/secondary-foo.c b/ld/testsuite/ld-elf/secondary-foo.c
new file mode 100644
index 0000000..8b23ec8
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary-foo.c
@@ -0,0 +1,7 @@
+extern void bar (void);
+
+void
+foo (void)
+{
+ bar ();
+}
diff --git a/ld/testsuite/ld-elf/secondary-main.c b/ld/testsuite/ld-elf/secondary-main.c
new file mode 100644
index 0000000..f1cb6b4
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary-main.c
@@ -0,0 +1,8 @@
+extern void foo (void);
+
+int
+main (void)
+{
+ foo ();
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/secondary.c b/ld/testsuite/ld-elf/secondary.c
new file mode 100644
index 0000000..6d64ed7
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+asm (".secondary bar");
+
+void
+bar (void)
+{
+ printf ("secondary bar\n");
+}
diff --git a/ld/testsuite/ld-elf/secondary.exp b/ld/testsuite/ld-elf/secondary.exp
new file mode 100644
index 0000000..5143262
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary.exp
@@ -0,0 +1,176 @@
+# Expect script for ELF secondary symbol tests.
+# Copyright 2012
+# Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+# Exclude non-ELF targets.
+
+# The following tests require running the executable generated by ld,
+# or enough of a build environment to create a fully linked executable.
+# This is not commonly available when testing a cross-built linker.
+if ![isnative] {
+ return
+}
+
+if ![is_elf_format] {
+ return
+}
+
+# Check to see if the C compiler works
+if { [which $CC] == 0 } {
+ return
+}
+
+set build_tests {
+ {"Build secondary1.o"
+ "-r -nostdlib" ""
+ {secondary.c} {{readelf {-s} secondary.rd}} "secondary1.o"}
+ {"Build secondary1.so"
+ "-Wl,-z,nosecondary -shared" "-fPIC"
+ {secondary.c} {{readelf {--dyn-syms} secondary1.rd}} "secondary1.so"}
+ {"Build secondary2.so"
+ "-shared" "-fPIC"
+ {secondary.c} {{readelf {--dyn-syms} secondary2.rd}} "secondary2.so"}
+ {"Build libfoo.so"
+ "-shared" "-fPIC"
+ {secondary-foo.c} {} "libfoo.so"}
+ {"Build secondary-main with secondary.o"
+ "tmpdir/secondary.o tmpdir/libfoo.so" ""
+ {secondary-main.c} {{readelf {--dyn-syms} secondary1.rd}} "secondary"}
+ {"Build library1.so"
+ "-shared" "-fPIC -DSHARED"
+ {library1.c} {} "library1.so"}
+ {"Build library2.so"
+ "-shared" "-fPIC -DSHARED"
+ {library2.c} {} "library2.so"}
+ {"Build library1.a"
+ "" ""
+ {library1.c} {} "library1.a"}
+ {"Build library2.a"
+ "" ""
+ {library2.c} {} "library2.a"}
+ {"Build secondary3a.o"
+ "" ""
+ {secondary3a.s} {} "secondary3a.a"}
+ {"Build secondary3"
+ "-nostdlib tmpdir/secondary3a.o" ""
+ {secondary3b.s} {{readelf {-s} secondary3.rd}} "secondary3"}
+ {"Build secondary4.so"
+ "-nostdlib -shared tmpdir/secondary3a.o" ""
+ {secondary4.s} {{readelf {--dyn-syms} secondary4.rd}} "secondary4.so"}
+ {"Build library5a.a"
+ "" ""
+ {library5a.c} {} "library5a.a"}
+ {"Build library5b.a"
+ "" ""
+ {library5b.c} {} "library5b.a"}
+ {"Build secondary5.a"
+ "" ""
+ {secondary5.c} {} "secondary5.a"}
+ {"Build library6a.a"
+ "" ""
+ {library6a.c} {} "library6a.a"}
+ {"Build library6b.a"
+ "" ""
+ {library6b.c} {} "library6b.a"}
+ {"Build library6c.a"
+ "" ""
+ {library6c.c} {} "library6c.a"}
+ {"Build secondary6.a"
+ "" ""
+ {secondary6.c} {} "secondary6.a"}
+ {"Build library7a.a"
+ "" ""
+ {library7a.c} {} "library7a.a"}
+ {"Build library7b.a"
+ "" ""
+ {library7b.c} {} "library7b.a"}
+ {"Build library7c.a"
+ "" ""
+ {library7c.c} {} "library7c.a"}
+ {"Build secondary7.a"
+ "" ""
+ {secondary7.c} {} "secondary7.a"}
+ {"Build library8a.so"
+ "-shared -Wl,--version-script=library8.map" "-fPIC"
+ {library8a.c} {{readelf {-s} library8a.rd}} "library8a.so"}
+ {"Build library8b.so"
+ "-shared -Wl,--version-script=library8.map" "-fPIC"
+ {library8b.c} {{readelf {-s} library8b.rd}} "library8b.so"}
+ {"Build library8c.a"
+ "" "-fPIC"
+ {library8c.c} {} "library8c.a"}
+ {"Build library8c.so"
+ "-shared -Wl,--version-script=library8.map tmpdir/library8c.o tmpdir/library8a.so tmpdir/library8b.so"
+ "-fPIC"
+ {dummy.c} {{readelf {-s} library8c.rd}} "library8c.so"}
+}
+
+run_cc_link_tests $build_tests
+
+set run_tests {
+ {"Run secondary-main with secondary.o"
+ "tmpdir/secondary.o tmpdir/libfoo.so" ""
+ {secondary-main.c} "secondary1" "secondary1.out"}
+ {"Run secondary-main with secondary1.so"
+ "tmpdir/secondary1.so tmpdir/libfoo.so" ""
+ {secondary-main.c} "secondary2" "secondary1.out"}
+ {"Run secondary-main with secondary.o library1.o"
+ "tmpdir/secondary.o tmpdir/secondary.o tmpdir/library1.o tmpdir/libfoo.so" ""
+ {secondary-main.c} "secondary3" "library1.out"}
+ {"Run secondary-main with library1.o secondary.o"
+ "tmpdir/library1.o tmpdir/secondary.o tmpdir/secondary.o tmpdir/libfoo.so" ""
+ {secondary-main.c} "secondary4" "library1.out"}
+ {"Run secondary-main with secondary.o library2.o"
+ "tmpdir/secondary.o tmpdir/library2.o tmpdir/libfoo.so" ""
+ {secondary-main.c} "secondary5" "library2.out"}
+ {"Run secondary-main with library2.o secondary.o"
+ "tmpdir/library2.o tmpdir/secondary.o tmpdir/libfoo.so" ""
+ {secondary-main.c} "secondary6" "library2.out"}
+ {"Run secondary-main with secondary.o library1.so"
+ "tmpdir/secondary.o tmpdir/library1.so tmpdir/libfoo.so" ""
+ {secondary-main.c} "secondary7" "library3.out"}
+ {"Run secondary-main with library1.so secondary.o"
+ "tmpdir/library1.so tmpdir/secondary.o tmpdir/libfoo.so" ""
+ {secondary-main.c} "secondary8" "library3.out"}
+ {"Run secondary-main with secondary.o library2.so"
+ "tmpdir/secondary.o tmpdir/library2.so tmpdir/libfoo.so" ""
+ {secondary-main.c} "secondary9" "library4.out"}
+ {"Run secondary-main with library2.so secondary.o"
+ "tmpdir/library2.so tmpdir/secondary.o tmpdir/libfoo.so" ""
+ {secondary-main.c} "secondary10" "library4.out"}
+ {"Run secondary5 with library5a.a library5b.a"
+ "tmpdir/secondary5.o tmpdir/library5a.a tmpdir/library5b.a" ""
+ {dummy.c} "secondary5a" "secondary5.out"}
+ {"Run secondary5 with -( library5a.a library5b.a -)"
+ "tmpdir/secondary5.o -\\( tmpdir/library5a.a tmpdir/library5b.a -\\)" ""
+ {dummy.c} "secondary5b" "secondary5.out"}
+ {"Run secondary5 with -( library5a.a library5b.a -) -( library5a.a library5b.a -)"
+ "tmpdir/secondary5.o -\\( tmpdir/library5a.a tmpdir/library5b.a -\\) -\\( tmpdir/library5a.a tmpdir/library5b.a -\\)" ""
+ {dummy.c} "secondary5c" "secondary5.out"}
+ {"Run secondary6 with -( library6a.a library6b.a library6c.a -)"
+ "tmpdir/secondary6.o -\\( tmpdir/library6a.a tmpdir/library6b.a tmpdir/library6c.a -\\)" ""
+ {dummy.c} "secondary6" "secondary6.out"}
+ {"Run secondary7 with -( library7a.a library7b.a library7c.a -)"
+ "tmpdir/secondary7.o -\\( tmpdir/library7a.a tmpdir/library7b.a tmpdir/library7c.a -\\)" ""
+ {dummy.c} "secondary7" "secondary7.out"}
+}
+
+run_ld_link_exec_tests [] $run_tests
diff --git a/ld/testsuite/ld-elf/secondary.rd b/ld/testsuite/ld-elf/secondary.rd
new file mode 100644
index 0000000..9931c04
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary.rd
@@ -0,0 +1,5 @@
+Symbol table '\.symtab' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +SECOND +DEFAULT +[0-9]+ +_?bar
+#...
diff --git a/ld/testsuite/ld-elf/secondary1.out b/ld/testsuite/ld-elf/secondary1.out
new file mode 100644
index 0000000..8d9378f
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary1.out
@@ -0,0 +1 @@
+secondary bar
diff --git a/ld/testsuite/ld-elf/secondary1.rd b/ld/testsuite/ld-elf/secondary1.rd
new file mode 100644
index 0000000..89d6d76
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary1.rd
@@ -0,0 +1,5 @@
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +WEAK +DEFAULT +[0-9]+ +_?bar
+#...
diff --git a/ld/testsuite/ld-elf/secondary2.rd b/ld/testsuite/ld-elf/secondary2.rd
new file mode 100644
index 0000000..ff618a0
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary2.rd
@@ -0,0 +1,5 @@
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +SECOND +DEFAULT +[0-9]+ +_?bar
+#...
diff --git a/ld/testsuite/ld-elf/secondary3.rd b/ld/testsuite/ld-elf/secondary3.rd
new file mode 100644
index 0000000..93c3469
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary3.rd
@@ -0,0 +1,5 @@
+Symbol table '\.symtab' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +0+ +0+ +[A-Z]+ +WEAK +DEFAULT +UND +_?foo
+#...
diff --git a/ld/testsuite/ld-elf/secondary3a.s b/ld/testsuite/ld-elf/secondary3a.s
new file mode 100644
index 0000000..16a1300
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary3a.s
@@ -0,0 +1,4 @@
+ .section .text,"axG",%progbits,foo_group,comdat
+ .global bar
+bar:
+ .byte 0
diff --git a/ld/testsuite/ld-elf/secondary3b.s b/ld/testsuite/ld-elf/secondary3b.s
new file mode 100644
index 0000000..cc6f37b
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary3b.s
@@ -0,0 +1,20 @@
+ .section .text,"axG",%progbits,foo_group,comdat
+ .secondary foo
+ .global bar
+foo:
+ .byte 0
+bar:
+ .byte 0
+ .data
+ .dc.a foo
+
+ .text
+ .global start /* Used by SH targets. */
+start:
+ .global _start
+_start:
+ .global __start
+__start:
+ .global main /* Used by HPPA targets. */
+main:
+ .dc.a bar
diff --git a/ld/testsuite/ld-elf/secondary4.rd b/ld/testsuite/ld-elf/secondary4.rd
new file mode 100644
index 0000000..e84b1a6
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary4.rd
@@ -0,0 +1,5 @@
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +0+ +0+ +[A-Z]+ +WEAK +DEFAULT +UND +_?foo
+#...
diff --git a/ld/testsuite/ld-elf/secondary4.s b/ld/testsuite/ld-elf/secondary4.s
new file mode 100644
index 0000000..a2acf21
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary4.s
@@ -0,0 +1,9 @@
+ .section .text,"axG",%progbits,foo_group,comdat
+ .secondary foo
+ .global bar
+foo:
+ .byte 0
+bar:
+ .byte 0
+ .data
+ .dc.a foo
diff --git a/ld/testsuite/ld-elf/secondary5.c b/ld/testsuite/ld-elf/secondary5.c
new file mode 100644
index 0000000..a2b2f20
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary5.c
@@ -0,0 +1,10 @@
+extern void foo (void);
+extern void xxx (void);
+
+int
+main (void)
+{
+ foo ();
+ xxx ();
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/secondary5.out b/ld/testsuite/ld-elf/secondary5.out
new file mode 100644
index 0000000..730c35d
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary5.out
@@ -0,0 +1,3 @@
+foo
+secondary bar
+xxx
diff --git a/ld/testsuite/ld-elf/secondary6.c b/ld/testsuite/ld-elf/secondary6.c
new file mode 100644
index 0000000..2a7e17b
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary6.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+extern void xxx (void);
+
+int
+main (void)
+{
+ xxx ();
+ printf ("OK\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/secondary6.out b/ld/testsuite/ld-elf/secondary6.out
new file mode 100644
index 0000000..d86bac9
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary6.out
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-elf/secondary7.c b/ld/testsuite/ld-elf/secondary7.c
new file mode 100644
index 0000000..9a67352
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary7.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+extern void abort (void);
+extern int xxx (void);
+
+int
+main (void)
+{
+ if (xxx () != 0)
+ abort ();
+ printf ("OK\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/secondary7.out b/ld/testsuite/ld-elf/secondary7.out
new file mode 100644
index 0000000..d86bac9
--- /dev/null
+++ b/ld/testsuite/ld-elf/secondary7.out
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
index b55856a..00a4983 100644
--- a/ld/testsuite/ld-elf/shared.exp
+++ b/ld/testsuite/ld-elf/shared.exp
@@ -246,6 +246,15 @@
{"Build dynamic-1"
"-Wl,--dynamic-list,dynamic-1.syms -Wl,--gc-sections" "-ffunction-sections"
{dynamic-1.c} {{readelf {-s} dynamic-1.rd}} "dynamic-1"}
+ {"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
diff --git a/ld/testsuite/ld-elfvers/vers24.rd b/ld/testsuite/ld-elfvers/vers24.rd
index fb464f9..2360447 100644
--- a/ld/testsuite/ld-elfvers/vers24.rd
+++ b/ld/testsuite/ld-elfvers/vers24.rd
@@ -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
diff --git a/ld/testsuite/ld-plugin/lto-10.out b/ld/testsuite/ld-plugin/lto-10.out
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-10.out
@@ -0,0 +1 @@
+hello
diff --git a/ld/testsuite/ld-plugin/lto-10a.c b/ld/testsuite/ld-plugin/lto-10a.c
new file mode 100644
index 0000000..93d57b5
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-10a.c
@@ -0,0 +1,6 @@
+extern int foo(void);
+
+int main(void)
+{
+ return foo();
+}
diff --git a/ld/testsuite/ld-plugin/lto-10b.c b/ld/testsuite/ld-plugin/lto-10b.c
new file mode 100644
index 0000000..507055b
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-10b.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int foo(void)
+{
+ printf ("hello\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-10r.d b/ld/testsuite/ld-plugin/lto-10r.d
new file mode 100644
index 0000000..689e6ec
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-10r.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-10a.o tmpdir/lto-10b.o
+#source: dummy.s
+#nm: -p
+
+#...
+[0-9a-f]+ C __gnu_lto_v.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-4.out b/ld/testsuite/ld-plugin/lto-4.out
new file mode 100644
index 0000000..8d8cc92
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4.out
@@ -0,0 +1,2 @@
+hello bar
+hello foo
diff --git a/ld/testsuite/ld-plugin/lto-4a.c b/ld/testsuite/ld-plugin/lto-4a.c
new file mode 100644
index 0000000..2d07cf5
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4a.c
@@ -0,0 +1,7 @@
+extern void foo(void);
+
+int main(void)
+{
+ foo();
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-4b.c b/ld/testsuite/ld-plugin/lto-4b.c
new file mode 100644
index 0000000..bb4a68b
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4b.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+extern void bar (void);
+
+void foo(void)
+{
+ bar ();
+ printf ("hello foo\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-4c.c b/ld/testsuite/ld-plugin/lto-4c.c
new file mode 100644
index 0000000..317e6fc
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4c.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void bar (void)
+{
+ printf ("hello bar\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-4r-a.d b/ld/testsuite/ld-plugin/lto-4r-a.d
new file mode 100644
index 0000000..c618cff
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4r-a.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-4a.o tmpdir/lto-4b.o tmpdir/lto-4c.o
+#source: dummy.s
+#objdump: -h
+
+#...
+.* .gnu_object_only.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-4r-b.d b/ld/testsuite/ld-plugin/lto-4r-b.d
new file mode 100644
index 0000000..07d71cb
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4r-b.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-4a.o tmpdir/lto-4b.o
+#source: dummy.s
+#objdump: -h
+
+#...
+.* .gnu_object_only.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-4r-c.d b/ld/testsuite/ld-plugin/lto-4r-c.d
new file mode 100644
index 0000000..ada50c0
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4r-c.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-4r-b.o tmpdir/lto-4c.o
+#source: dummy.s
+#objdump: -h
+
+#...
+.* .gnu_object_only.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-4r-d.d b/ld/testsuite/ld-plugin/lto-4r-d.d
new file mode 100644
index 0000000..d4c5852
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4r-d.d
@@ -0,0 +1,7 @@
+#ld: -r --whole-archive tmpdir/liblto-4.a
+#source: dummy.s
+#objdump: -h
+
+#...
+.* .gnu_object_only.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
index 031752d..e6b768c 100644
--- a/ld/testsuite/ld-plugin/lto.exp
+++ b/ld/testsuite/ld-plugin/lto.exp
@@ -79,6 +79,15 @@
[list "Build liblto-3.a" \
"" "-flto $lto_fat" \
{lto-3b.c} {} "liblto-3.a"] \
+ [list "Compile 4a" \
+ "" "-flto $lto_fat" \
+ {lto-4a.c} {} ""] \
+ [list "Compile 4b" \
+ "" "-O2" \
+ {lto-4b.c} {} ""] \
+ [list "Compile 4c" \
+ "" "-O2" \
+ {lto-4c.c} {} ""] \
[list "Compile 5a" \
"" "-flto $lto_fat" \
{lto-5a.c} {} ""] \
@@ -88,9 +97,18 @@
[list "LTO 6" \
"-O2 -flto -fuse-linker-plugin" "" \
{lto-6.c} {} "lto-6.exe" "c"] \
+ [list "Compile PR ld/12365" \
+ "" "-flto -O2 $lto_fat" \
+ {pr12365a.c pr12365b.c pr12365c.c} {} ""] \
[list "Compile 9" \
"" "-O2 -finline -flto" \
{lto-9.cc} {} "" "c++"] \
+ [list "Compile 10a" \
+ "" "-O2" \
+ {lto-10a.c} {} ""] \
+ [list "Compile 10b" \
+ "" "-O2 -flto $lto_fat" \
+ {lto-10b.c} {} ""] \
[list "Compile 11a" \
"" "-O -flto" \
{lto-11a.c} {} ""] \
@@ -247,6 +265,9 @@
[list "PR ld/16746 (2)" \
"-O2 -flto -fuse-linker-plugin tmpdir/pr16746c.o tmpdir/pr16746a.o" "-O2 -flto" \
{dummy.c} {} "pr16746b.exe"] \
+ [list "PR ld/14918" \
+ "-flto" "-flto" \
+ {pr14918.c} {{"readelf" {-d --wide} "pr14918.d"}} "pr14918.exe" "c"] \
]
# Check final symbols in executables.
@@ -282,9 +303,21 @@
[list "LTO 3c" \
"-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o -Wl,--whole-archive tmpdir/liblto-3.a -Wl,--no-whole-archive tmpdir/liblto-3.a" "" \
{dummy.c} "lto-3d.exe" "lto-3.out" "" "c"] \
+ [list "LTO 4a" \
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-a.o" "" \
+ {dummy.c} "lto-4a.exe" "lto-4.out" "" "c"] \
+ [list "LTO 4c" \
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-c.o" "" \
+ {dummy.c} "lto-4c.exe" "lto-4.out" "" "c"] \
+ [list "LTO 4d" \
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-d.o" "" \
+ {dummy.c} "lto-4d.exe" "lto-4.out" "" "c"] \
[list "LTO 5" \
"-O2 -flto -fuse-linker-plugin tmpdir/lto-5.o" "" \
{dummy.c} "lto-5.exe" "lto-5.out" "" "c"] \
+ [list "LTO 10" \
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-10.o" "" \
+ {dummy.c} "lto-10.exe" "lto-10.out" "" "c"] \
[list "LTO 11" \
"-O -flto -fuse-linker-plugin tmpdir/liblto-11.a" "" \
{dummy.c} "lto-11.exe" "lto-11.out" "" "c"] \
@@ -366,6 +399,15 @@
}
}
+set testname "Build liblto-4.a"
+remote_file host delete "tmpdir/liblto-4.a"
+set catch_output [run_host_cmd "$ar" "rc tmpdir/liblto-4.a tmpdir/lto-4a.o tmpdir/lto-4b.o tmpdir/lto-4c.o"]
+if {![string match "" $catch_output]} {
+ unresolved $testname
+ restore_notify
+ return
+}
+
set testname "Build liblto-11.a"
remote_file host delete "tmpdir/liblto-11.a"
set catch_output [run_host_cmd "$ar" "rc $plug_opt tmpdir/liblto-11.a tmpdir/lto-11a.o tmpdir/lto-11b.o tmpdir/lto-11c.o"]
@@ -377,6 +419,13 @@
if { [at_least_gcc_version 4 7] } {
# Check expected LTO linker errors.
+ set testname "PR ld/12365"
+ set exec_output [run_host_cmd "$CC" "-O2 -flto -fuse-linker-plugin tmpdir/pr12365a.o tmpdir/pr12365b.o tmpdir/pr12365c.o"]
+ if { [ regexp "undefined reference to `my_bcopy'" $exec_output ] } {
+ pass $testname
+ } {
+ fail $testname
+ }
set testname "PR ld/12942 (3)"
set exec_output [run_host_cmd "$CXX" "-O2 -flto -fuse-linker-plugin tmpdir/pr12942b.o tmpdir/pr12942a.o"]
if { [ regexp "undefined reference to `link_error\\(\\)'" $exec_output ] } {
@@ -389,8 +438,30 @@
# Run "ld -r" to generate inputs for complex LTO tests.
run_dump_test "lto-3r"
remote_exec host "mv" "tmpdir/dump tmpdir/lto-3.o"
+run_dump_test "lto-4r-a"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-a.o"
+run_dump_test "lto-4r-b"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-b.o"
+run_dump_test "lto-4r-c"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-c.o"
+run_dump_test "lto-4r-d"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-d.o"
run_dump_test "lto-5r"
remote_exec host "mv" "tmpdir/dump tmpdir/lto-5.o"
+run_dump_test "lto-10r"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-10.o"
+set testname "nm mixed object"
+set lto_plugin [run_host_cmd "$CC" "-print-prog-name=liblto_plugin.so tmpdir/lto-10.o"]
+if { [ regexp "liblto_plugin.so" $lto_plugin ] } {
+ set exec_output [run_host_cmd "$NM" "--plugin $lto_plugin tmpdir/lto-10.o"]
+ if { [ regexp "T main" $exec_output ] } {
+ pass $testname
+ } {
+ fail $testname
+ }
+} {
+ fail $testname
+ }
run_cc_link_tests $lto_link_symbol_tests
diff --git a/ld/testsuite/ld-plugin/pr12365a.c b/ld/testsuite/ld-plugin/pr12365a.c
new file mode 100644
index 0000000..a9bb6c6
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12365a.c
@@ -0,0 +1,25 @@
+extern void abort(void);
+extern void main_test (void);
+extern void abort (void);
+int inside_main;
+
+int
+main ()
+{
+ inside_main = 1;
+ main_test ();
+ inside_main = 0;
+ return 0;
+}
+
+/* When optimizing, all the constant cases should have been
+ constant folded, so no calls to link_error should remain.
+ In any case, link_error should not be called. */
+
+#ifndef __OPTIMIZE__
+void
+link_error (void)
+{
+ abort ();
+}
+#endif
diff --git a/ld/testsuite/ld-plugin/pr12365b.c b/ld/testsuite/ld-plugin/pr12365b.c
new file mode 100644
index 0000000..a5a80e0
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12365b.c
@@ -0,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 ();
+}
diff --git a/ld/testsuite/ld-plugin/pr12365c.c b/ld/testsuite/ld-plugin/pr12365c.c
new file mode 100644
index 0000000..2edd0ff
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12365c.c
@@ -0,0 +1,79 @@
+extern void abort (void);
+extern int inside_main;
+typedef __SIZE_TYPE__ size_t;
+
+#define TEST_ABORT if (inside_main) abort()
+
+void *
+my_memcpy (void *d, const void *s, size_t n)
+{
+ char *dst = (char *) d;
+ const char *src = (const char *) s;
+ while (n--)
+ *dst++ = *src++;
+ return (char *) d;
+}
+
+void
+my_bcopy (const void *s, void *d, size_t n)
+{
+ char *dst = (char *) d;
+ const char *src = (const char *) s;
+ if (src >= dst)
+ while (n--)
+ *dst++ = *src++;
+ else
+ {
+ dst += n;
+ src += n;
+ while (n--)
+ *--dst = *--src;
+ }
+}
+
+void *
+my_memset (void *d, int c, size_t n)
+{
+ char *dst = (char *) d;
+ while (n--)
+ *dst++ = c;
+ return (char *) d;
+}
+
+void
+my_bzero (void *d, size_t n)
+{
+ char *dst = (char *) d;
+ while (n--)
+ *dst++ = '\0';
+}
+
+void *
+memcpy (void *d, const void *s, size_t n)
+{
+ void *result = my_memcpy (d, s, n);
+ TEST_ABORT;
+ return result;
+}
+
+void
+bcopy (const void *s, void *d, size_t n)
+{
+ my_bcopy (s, d, n);
+ TEST_ABORT;
+}
+
+void *
+memset (void *d, int c, size_t n)
+{
+ void *result = my_memset (d, c, n);
+ TEST_ABORT;
+ return result;
+}
+
+void
+bzero (void *d, size_t n)
+{
+ my_bzero (d, n);
+ TEST_ABORT;
+}
diff --git a/ld/testsuite/ld-plugin/pr14918.c b/ld/testsuite/ld-plugin/pr14918.c
new file mode 100644
index 0000000..a9bce4a
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr14918.c
@@ -0,0 +1,5 @@
+int
+main ()
+{
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/pr14918.d b/ld/testsuite/ld-plugin/pr14918.d
new file mode 100644
index 0000000..0b14948
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr14918.d
@@ -0,0 +1,4 @@
+#failif
+#...
+ 0x0+1 \(NEEDED\) +Shared library: \[libgcc_s.so.[0-9]+\]
+#...
diff --git a/release.binutils-2.24.51.0.3 b/release.binutils-2.24.51.0.3
new file mode 100644
index 0000000..2b1210c
--- /dev/null
+++ b/release.binutils-2.24.51.0.3
@@ -0,0 +1,899 @@
+This is the beta release of binutils 2.24.51.0.3 for Linux, which is
+based on binutils 2014 0127 master branch on sourceware.org plus
+various changes. It is purely for Linux.
+
+All relevant patches in patches have been applied to the source tree.
+You can take a look at patches/README to see what have been applied and
+in what order they have been applied.
+
+Starting from the 2.23.52.0.2 release, when creating executables, BFD
+linker will issue an error for undefined weak reference which is
+defined in a shared library from DT_NEEDED. Previously BFD linker
+will silently include the shared library from DT_NEEDED.
+
+Starting from the 2.21.51.0.3 release, you must remove .ctors/.dtors
+section sentinels when building glibc or other C run-time libraries.
+Otherwise, you will run into:
+
+http://sourceware.org/bugzilla/show_bug.cgi?id=12343
+
+Starting from the 2.21.51.0.2 release, BFD linker has the working LTO
+plugin support. It can be used with GCC 4.5 and above. For GCC 4.5, you
+need to configure GCC with --enable-gold to enable LTO plugin support.
+
+Starting from the 2.21.51.0.2 release, binutils fully supports compressed
+debug sections. However, compressed debug section isn't turned on by
+default in assembler. I am planning to turn it on for x86 assembler in
+the future release, which may lead to the Linux kernel bug messages like
+
+WARNING: lib/ts_kmp.o (.zdebug_aranges): unexpected non-allocatable section.
+
+But the resulting kernel works fine.
+
+Starting from the 2.20.51.0.4 release, no diffs against the previous
+release will be provided.
+
+You can enable both gold and bfd ld with --enable-gold=both. Gold will
+be installed as ld.gold and bfd ld will be installed as ld.bfd. By
+default, ld.bfd will be installed as ld. You can use the configure
+option, --enable-gold=both/gold to choose gold as the default linker,
+ld. IA-32 binary and X64_64 binary tar balls are configured with
+--enable-gold=both/ld --enable-plugins --enable-threads.
+
+Starting from the 2.18.50.0.4 release, the x86 assembler no longer
+accepts
+
+ fnstsw %eax
+
+fnstsw stores 16bit into %ax and the upper 16bit of %eax is unchanged.
+Please use
+
+ fnstsw %ax
+
+Starting from the 2.17.50.0.4 release, the default output section LMA
+(load memory address) has changed for allocatable sections from being
+equal to VMA (virtual memory address), to keeping the difference between
+LMA and VMA the same as the previous output section in the same region.
+
+For
+
+.data.init_task : { *(.data.init_task) }
+
+LMA of .data.init_task section is equal to its VMA with the old linker.
+With the new linker, it depends on the previous output section. You
+can use
+
+.data.init_task : AT (ADDR(.data.init_task)) { *(.data.init_task) }
+
+to ensure that LMA of .data.init_task section is always equal to its
+VMA. The linker script in the older 2.6 x86-64 kernel depends on the
+old behavior. You can add AT (ADDR(section)) to force LMA of
+.data.init_task section equal to its VMA. It will work with both old
+and new linkers. The x86-64 kernel linker script in kernel 2.6.13 and
+above is OK.
+
+The new x86_64 assembler no longer accepts
+
+ monitor %eax,%ecx,%edx
+
+You should use
+
+ monitor %rax,%ecx,%edx
+
+or
+ monitor
+
+which works with both old and new x86_64 assemblers. They should
+generate the same opcode.
+
+The new i386/x86_64 assemblers no longer accept instructions for moving
+between a segment register and a 32bit memory location, i.e.,
+
+ movl (%eax),%ds
+ movl %ds,(%eax)
+
+To generate instructions for moving between a segment register and a
+16bit memory location without the 16bit operand size prefix, 0x66,
+
+ mov (%eax),%ds
+ mov %ds,(%eax)
+
+should be used. It will work with both new and old assemblers. The
+assembler starting from 2.16.90.0.1 will also support
+
+ movw (%eax),%ds
+ movw %ds,(%eax)
+
+without the 0x66 prefix. Patches for 2.4 and 2.6 Linux kernels are
+available at
+
+http://www.kernel.org/pub/linux/devel/binutils/linux-2.4-seg-4.patch
+http://www.kernel.org/pub/linux/devel/binutils/linux-2.6-seg-5.patch
+
+The ia64 assembler is now defaulted to tune for Itanium 2 processors.
+To build a kernel for Itanium 1 processors, you will need to add
+
+ifeq ($(CONFIG_ITANIUM),y)
+ CFLAGS += -Wa,-mtune=itanium1
+ AFLAGS += -Wa,-mtune=itanium1
+endif
+
+to arch/ia64/Makefile in your kernel source tree.
+
+Please report any bugs related to binutils 2.24.51.0.3 to
+hjl.tools@gmail.com
+
+and
+
+http://www.sourceware.org/bugzilla/
+
+Changes from binutils 2.24.51.0.2:
+
+1. Update from binutils 2014 0127.
+2. Fix a linker crash with mixed IR/non-IR input objects.
+3. Update readelf/objdump to display versioned symbol names when dumping
+dynamic relocations. PR 16496.
+4. Update linker to improve orphaned TLS section handling. PR 16498.
+5. Update linker to check incompatible existing default symbol definition.
+PR 16467.
+6. Update linker to properly handle non-PIC references to __ehdr_start in
+pie and shared object. PR 16428.
+7. Update bfd to properly generate PT_GNU_RELRO segment for ld and
+objcopy. PRs 14207/16322/16323.
+8. Update x86 assembler to check for invalid register set in AVX512 gather
+instructions. PR 16489.
+9. Update empty section handling in linker.
+10. Avoid invalid directory in linker library search. PR 16456.
+11. Improve x86 disassembler.
+12. Improve gold.
+13. Improve COFF support.
+14. Add nds32 support.
+15. Improve aarch64 support.
+16. Improve arm support.
+17. Improve mips support.
+18. Improve msp430 support.
+19. Improve ppc support.
+20. Improve rl78 support.
+21. Improve z80 support.
+
+Changes from binutils 2.24.51.0.1:
+
+1. Update from binutils 2013 1213.
+2. Fix ld and objcopy to set the SHF_INFO_LINK bit for SHT_REL/SHT_RELA
+sections. PR 16317.
+3. Fix ld and objcopy to properly generate PT_GNU_RELRO segment. PRs
+14207/16322/16323.
+4. Fix objcopy to copy EI_OSABI field. PR 16318.
+5. Change ld to set e_type in ELF header to ET_EXEC for -pie
+-Ttext-segment=.
+6. Fix a ld bug for --as-needed with symbol versioning.
+7. Add gas/ld/gold support for R_X86_64_PC32_BND and R_X86_64_PLT32_BND
+relocations.
+8. Fix an assembler line listing bug. PR 16109.
+9. Improve gold.
+10. Improve nacl support.
+11. Improve COFF support.
+12. Improve aarch64 support.
+13. Improve arm support.
+14. Improve hppa support.
+15. Improve mips support.
+16. Improve ppc support.
+
+Changes from binutils 2.23.52.0.2:
+
+1. Update from binutils 2013 1106.
+2. Add Intel AVX-512 new instruction support.
+3. Add Intel MPX new instruction support.
+4. Update ld to support x86-64 large PIC model with TLS GD and LD sequences.
+5. Fix ld to properly handle R_X86_64_DTPOFF64. PR 15685.
+6. Fix x86 assembler to properly check 64-bit register.
+7. Update x86 assembler not to align text/data/bss sections for ELF.
+8. Fix x86 assembler to properly support cvttps2pi. PR 13572.
+9. Fix ld to generate warning sections in glibc. PR 15762.
+10. Avoid corrupted binary generated by objcopy/strip. PR 16056.
+11. Improve ld hash. PR 15657.
+12. Fix objdump on /proc/kcore. PR 15818.
+13. Improve DWARF support.
+14. Improve addr2line. PR 15994.
+15. Improve readelf. PR 15745.
+16. Improve gold.
+17. Improve nacl support.
+18. Improve aarch64 support.
+19. Improve arm support.
+20. Improve cris support.
+21. Improve hppa support.
+22. Improve m32c support.
+23. Improve m68k support.
+24. Improve mips support.
+25. Improve msp430 support.
+26. Improve nios2 support.
+27. Improve ppc support.
+28. Improve rl78 support.
+29. Improve rx support.
+30. Improve rs6000 support.
+31. Improve s390 support.
+32. Improve sparc support.
+33. Improve tile support.
+34. Improve vax support.
+
+Changes from binutils 2.23.52.0.1:
+
+1. Update from binutils 2013 0426.
+2. Add x32 support to embedded x86_64 ELF target.
+3. Fix an x86 IFUNC linker regression. PR 15371.
+4. Fix an LTO linker weak definition bug. PR 15323.
+5. Remove stale dynamic table entries for symbols optimized out by LTO.
+PR 15270.
+6. Revert the fix for PR 15149. When creating executables, BFD linker
+won't issue an error for undefined weak reference which is defined in
+7 shared library from DT_NEEDED.
+8. Ignore weak reference which is is defined in a shared library from
+DT_NEEDED. This may change the behavior of resulting binaries with
+undefined weak reference. List libraries needed on command-line as work
+around. PR 12549.
+9. Fix a MIPS ELF linker crash. PR 15382.
+10. Align LMA per VMA alignment only if needed. PR 15222.
+11. Fix a BFD decompress memory leak. PR 15356.
+12. Properly check SIB byte in x86 disassembler.
+13, Fix invalid memory access in readelf. PR 15191.
+14, Fix invalid memory access in DWARF dumper. PRs 15206/15202/15201.
+15. Improve gold.
+16. Improve aarch64 support.
+17. Improve arm support.
+18. Improve avr support.
+19. Improve h8300 support.
+20. Improve mips support.
+21. Improve nios2 support.
+22. Improve ppc support.
+23. Improve rl78 support.
+24. Improve sh support.
+25. Improve sparc support.
+26. Improve tic6x support.
+27. Improve v850 support.
+
+Changes from binutils 2.23.51.0.9:
+
+1. Update from binutils 2013 0226.
+2. Add Intel SAMP new instruction support.
+3. Allow dynamic R_386_SIZE32, R_X86_64_SIZE32 and R_X86_64_SIZE64
+relocations agaist TLS symbols.
+4. Fix BFD linker to set STB_GNU_UNIQUE only for definition. PR 15167.
+5. Fix BFD linker to set STB_GNU_UNIQUE only if symbol is defined in
+regular object. PR 15107.
+6. Don't add DT_NEEDED for references from the LTO IR input. PR 15146.
+7. When creating executables, BFD linker will issue an error for undefined
+weak reference which is defined in a shared library from DT_NEEDED.
+PR 15149.
+8. Also trace symbol from the LTO IR input. PR 15141.
+9. Support stripping LTO IR sections. PR 15033.
+10. Don't allow a nested archive pointing to itself and don't generate
+bad archive. PR 15140.
+11. Fix objcopy segfault on non-ELF input. PR 14873.
+12. Update DWARF dump support.
+13. Improve gold.
+14. Add nios2 support.
+15. Improve mach support.
+16. Improve aarch64 support.
+17. Improve arm support.
+18. Improve avr support.
+19. Improve h8300 support.
+20. Improve meta support.
+21. Improve mips support.
+22. Improve ppc support.
+23. Improve rl78 support.
+24. Improve sparc support.
+25. Improve v850 support.
+
+Changes from binutils 2.23.51.0.8:
+
+1. Update from binutils 2013 0118.
+2. Support R_386_SIZE32, R_X86_64_SIZE32 and R_X86_64_SIZE64
+relocations.
+3. Fix x86 assembler for "xtrn@got -1". PR 15019.
+4. Don't generate old dtags with --enable-new-dtags.
+5. Add Meta support.
+6. Improve gold.
+7. Improve aarch64 support.
+8. Improve arm support.
+9. Improve cr16 support.
+10. Improve mips support.
+11. Improve ppc support.
+12. Improve v850 support.
+13. Improve xgate support.
+
+Changes from binutils 2.23.51.0.7:
+
+1. Properly adjust h->plt.refcount. PR 14980.
+
+Changes from binutils 2.23.51.0.6:
+
+1. Update from binutils 2012 1218.
+2. Add missing R_*_IRELATIVE relocations. PR 14968.
+3. Remove unnecessary R_*_NONE relocations. PR 14956.
+4. Fix ar/ranlib on 32-bit filesystems. PR 14933.
+5. Fix a "Not enough room for program headers" linker bug. PR 14926.
+6. Support self-assignment in a linker script to convert symbols to
+absolute. PR 14962.
+7. Support --copy-dt-needed-entries when creating DSO. PR 14915.
+8. Improve linker plugin DSO error handling. PR 14904.
+9. Issue warning for plugin dummy. PR 12760.
+10. Add -fuse-ld=bfd|gold support to ld and gold.
+11. Fix gold configure. PR 14897.
+12. Correct gas dependency. PR 14899.
+13. Add rdos support.
+14. Improve gold.
+15. Improve nacl support.
+16. Improve aarch64 support.
+17. Improve arm support.
+18. Improve microblaze support.
+19. Improve mips support.
+20. Improve ppc support.
+21. Improve tile support.
+
+Changes from binutils 2.23.51.0.5:
+
+1. Update from binutils 2012 1123.
+2. Fix 64-bit jecxz encoding regression in x86 assembler. PR 14859.
+3. Revert an accidental linker change. PR 14862.
+4. Fix x32 TLS LD to LE optimization in gold. PR 14858.
+5. Add "-z global" option to set DF_1_GLOBAL to ld.
+6. Improve ld plugin error handling.
+7. Port ld lib32 arrangement from Debian.
+8. Properly set the output maxpagesize when rewriting program header.
+PR 14493.
+9. Add additional DF_1_XXX support to readelf.
+10. Improve nacl support with separate code segments.
+11. Improve macos support.
+12. Improve arm support.
+13. Improve microblaze support.
+14. Improve mips support.
+15. Improve ppc support.
+16. Improve sparc support.
+
+Changes from binutils 2.23.51.0.4:
+
+1. Update from binutils 2012 1110.
+2. Support new Linux NOTE sections.
+3. Add -z stacksize=SIZE option to ld to set size of stack segment.
+4. Fix a BFD IOVEC close bug. PR 14813.
+5. Fix a BFD IOVEC on archive bug. PR 14567.
+6. Fix archive support for non-ELF targets. PR 14481.
+7. Improve gold.
+8. Improve COFF support.
+9. Improve arm support.
+10. Improve microblaze support.
+11. Improve mips support.
+12. Improve ppc support.
+13. Improve rx support.
+14. Improve s390 support.
+15. Improve v850 support.
+16. Improve xgate support.
+
+Changes from binutils 2.23.51.0.3:
+
+1. Update from binutils 2012 1026.
+2. Fix an LTO linker bug. PR 14747.
+3. Add cx16 arch feature to x86 assembler.
+4. Add -march=bdver3 option to x86 assembler.
+5. Properly handle ignored REX prefix with fwait in x86 disassembler.
+6. Fix x32 register names in objdump DWARF output.
+7. Add NT_SIGINFO/NT_FILE support to readelf.
+8. Add linker --ignore-unresolved-symbol option from NetBSD.
+9. Treat .gdb_index section as debug section. PR 14662.
+10. Add --debug-dump=addr, --debug_dump=cu_index options to readelf and
+objdump.
+11. Add dwp, DWARF packaging utility.
+12. Add compressed debug section support to Windows. PR 14067.
+13. Improve gold.
+14. Improve aarch64 support.
+15. Improve arm support.
+16. Improve hppa support.
+17. Improve mips support.
+18. Improve s390 support.
+19. Improve tile support.
+20. Improve v850 support.
+
+Changes from binutils 2.23.51.0.2:
+
+1. Update from binutils 2012 0918.
+2. Properly handle versioned STB_SECONDARY symbols.
+3. Fix wrong symbol type with common symbol and weak function. PR 14591.
+4. Ignore discarded sections when converting mov to lea.
+5. Improve gold.
+6. Improve avr support.
+7. Improve aarch64 support.
+8. Improve moxie support.
+9. Improve ppc support.
+10. Improve tile support.
+
+Changes from binutils 2.23.51.0.1:
+
+1. Update from binutils 2012 0908.
+2. Fix STB_SECONDARY support:
+ a. Generate STB_SECONDARY symbols in DSO by default.
+ b. Properly handle STB_SECONDAY symbols when linking with archive.
+ c. Don't allow .weak directive to override .secondary directive.
+3. Optimize i386/x86-64 linker to convert GOT load (MOV) to LEA.
+4. Clarify x86 assembler error messages. PR 14457.
+5. Improve NOP/prefetch support in x86 disassembler.
+6. Improve Intel syntax support in x86 assembler.
+7. Add -march={btver1, btver2} options to x86 assembler.
+8. Fix binutils build with --enable-shared. PR 4970.
+9. Also provide __executable_start for PIE. PR 14525.
+10. Use xmalloc to allocate memory for argument list file. PR 14526.
+11. Add Intel Itanium Series 9500 support to assembler/diassembler.
+12. Ignore section symbols without a BFD section when outputing symbols
+and check bad section index. PR 14493.
+13. Improve archive reader. PR 14475.
+14. Support DW_OP_GNU_const_index reader.
+15. Improve handling of imput files with empty ELF group sections.
+PR 14444.
+16. Fix IFUNC support in s390 linker.
+17. Improve gold.
+18. Add aarch64 support.
+19. Improve arm support.
+20. Improve mips support.
+21. Improve mmix support.
+22. Improve moxie support.
+23. Improve ppc support.
+24. Improve s390 support.
+25. Improve tile support.
+
+Changes from binutils 2.22.52.0.4:
+
+1. Update from binutils 2012 0806.
+2. Add Intel ADX, RDSEED and PRFCHW new instruction support.
+3. Support 'rep bsf', 'rep bsr', and 'rep ret' syntax in x86 assembler.
+4. Mark 256-bit vmovntdqa as AVX2 instruction for x86 assembler.
+5. Improve x86 assembler error handling.
+6. Improve the repeat directive support in assembler. PR 14201.
+7. Improve x86-64 disassembler on superfluous prefixes.
+8. Fix x86 disassembler crash on bad XOP instructions. PR 14355.
+9. Support STB_SECONDARY:
+
+https://groups.google.com/forum/?hl=en&fromgroups#!forum/generic-abi
+
+10. Added SORT_NONE to the linker script language to disable section
+sorting and properly handle .init/.fini sections. PR 14156.
+11. Fix a weak alias linker bug. PR 14323.
+12. Fix the NULL GNU_RELRO segment linker bug. PR 14207.
+13. Fix the bad GNU_RELRO segment linker bug. PR 14215.
+14. Add linker support of __ehdr_start symbol for the ELF file header.
+15. Add IFUNC support to s390 linker.
+16. Fix ar for >4GB member. PR 14302.
+17. Fix objcopy --compress-debug-sections on empty debug section. PR
+14319.
+18. Fix readelf/objdup to display null bytes in DWARF debug info. PR
+14420.
+19. Improve gold.
+20. Improve arm support.
+21. Improve avr support.
+22. Improve cris support.
+23. Improve m68k support.
+24. Improve mips support.
+25. Improve ppc support.
+26. Improve vax support.
+27. Improve xgate support.
+
+Changes from binutils 2.22.52.0.3:
+
+1. Update from binutils 2012 0604.
+2. Check addend overflow for R_X86_64_RELATIVE64.
+3. Fix ar/nm/ranlib with --plugin.
+4. Create .eh_frame_hdr section only if needed. PR 13909.
+5. Properly create .eh_frame section for PLT. PR 14105.
+6. Fix a linker crash. PR 14170.
+7. Fix readelf to properly display addend.
+8. Don't make _DYNAMIC/_GLOBAL_OFFSET_TABLE_/_PROCEDURE_LINKAGE_TABLE_
+symbols absolute for x86 and ppc.
+9. Properly handle shared libraries with zero dynamic symbols. PRs
+7023/13962.
+10. Update readelf/assembler to support multibyte characters in symbol
+names.
+11. Add --strip-dwo/--extract-dwo options to objcopy/strip.
+12. Add R_X86_64_RELATIVE64 support to gold.
+13. Improve gold.
+14. Improve NACL support.
+15. Improve alpha support.
+16. Improve avr support.
+17. Improve m68k support.
+18. Improve mips support.
+19. Improve ppc support.
+20. Improve vax support.
+
+Changes from binutils 2.22.52.0.2:
+
+1. Update from binutils 2012 0507.
+2. Fix Linux kernel build by reverting the PR 13621 fix. PR 14052.
+3. Add support for x86_64-*-linux-gnux32 target.
+4. Improve x86 assembler.
+5. Improve DWARF support.
+6. Improve gold.
+7. Improve rx support.
+8. Improve sparc support.
+9. Add xgate support.
+
+Changes from binutils 2.22.52.0.1:
+
+1. Update from binutils 2012 0424.
+2. Support Intel HLE and RTM extension.
+3. Add NACL support.
+4. Fix -Bsymbolic with protected function pointer. PR 13880.
+5. Fix an IFUNC regression. PR 13817.
+6. Fix x86 NOP fill regression. PR 13675.
+7. Fix a linker regression. PR 13991.
+8. Fix dangling global hidden symbol in symtab. PR 13621.
+9. Fix objcopy, strip and ld for --emit-relocs. PR 13947.
+10. Improve gold.
+11. Improve mach support.
+12. Improve vms support.
+13. Improve windows support.
+14. Improve arm support.
+15. Improve avr support.
+16. Improve mips support.
+17. Improve ppc support.
+18. Improve rx support.
+19. Improve s390 support.
+20. Improve sh support.
+21. Improve sparc support.
+22. Improve tile support.
+
+Changes from binutils 2.22.51.0.1:
+
+1. Update from binutils 2012 0131.
+2. Add x32 support to gold.
+3. Support linker arch-depedent fill. PR 13616.
+4. Add i386 NACL support to x86 assembler.
+5. Add fake zero displacement for .d8 and .d32 suffixes to x86 assembler.
+6. Add vmfunc support to x86 assembler/disassembler.
+7. Support >2GB archive member. PR 13534.
+8. Support R_X86_64_PC32 relocation for PIC on x32. PR 13581.
+9. Fix LTO linker with --start-group and archive. PR 12758.
+10. Fix linker with --build-id. PR 12451.
+11. Improve linker dead code dependency removal on DSO. PR 12772.
+12. Improve demangler.
+13. Fix elf64-x86-64.c build with GCC 4.7.
+14. Avoid linker -z text crash. PR 13468.
+15. Avoid readelf crash. PR 13622.
+16. Avoid nm crash on --size-sort --no-sort. PR 13593.
+17. Fix linker COFF SECREL32 relocation support. PR 13491.
+18. Improve gold.
+19. Improve mach support.
+20. Improve arm support.
+21. Improve avr support.
+22. Improve hppa support.
+23. Improve m68k support.
+24. Improve mips support.
+25. Improve ppc support.
+26. Improve rl78 support.
+27. Improve rx support.
+
+Changes from binutils 2.21.53.0.2:
+
+1. Update from binutils 2011 1118.
+2. Fix ar --plugin on archive with mixed IR/non-IR objects. PR 13298.
+3. Preserve the maximum alignment and size for common symbols. PR 13250.
+4. Fix LTO linker with -as-needed. PR 13287.
+5. Fix --plugin support on thin archive. PR 13257.
+6. Fix LTO linker on thin archive. PR 13183.
+7. Fix --plugin slim object support on archive. PR 13278.
+8. Support LDPR_PREVAILING_DEF_IRONLY_EXP in linker plugin. PR 13229.
+9. Don't make make IR symbols dynamic. PR 13244.
+10. Fix LTO linker with --as-needed. PR 13201.
+11. Properly handle 2 IR symbols with the same comdat key. PR 13066.
+12. Keep .debug_types sections with linker garbage collection. PR 13233.
+13. Fix -ffunction-sections -Wl,--gc-sections failure with symbol
+versioning. PR 13195.
+14. Improve linker garbage collection support. PR 13177.
+15. Remove symbols hidden by version scripts with --gc-sections. PR 12975.
+16. Remove unnecessary GOT relocation created for IFUNC. PR 13178.
+17. Move IRELATIVE relocations to the end. PR 13302.
+18. Avoid readelf core dump. PR 13219.
+19. Check zero address size when dumping DWARF sections. PR 13196.
+20. Remove the group section if all members are removed. PR 13180.
+21. Support R_X86_64_64 and R_X86_64_RELATIVE64 relocations for x32.
+PR 13082.
+22. Add Adapteva Epiphany support.
+23. Add Renesas RL78 support.
+24. Improve gold.
+25. Improve mach-o support.
+26. Improve alpha support.
+27. Improve arm support.
+28. Improve hppa support.
+29. Improve mips support.
+30. Improve ppc support.
+31. Improve rx support.
+32. Improve sparc support.
+
+Changes from binutils 2.21.53.0.1:
+
+1. Update from binutils 2011 0804.
+2. Add Intel K1OM support.
+3. Allow R_X86_64_64 relocation for x32 and check x32 relocation overflow.
+PR ld/13048.
+4. Support direct call in x86-64 assembly code. PR gas/13046.
+5. Add ia32 Google Native Client support.
+6. Add .debug_macro section support.
+7. Improve gold.
+8. Improve VMS support.
+9. Improve arm support.
+10. Improve hppa support.
+11. Improve mips support.
+12. Improve mmix support.
+13. Improve ppc support.
+
+Changes from binutils 2.21.52.0.2:
+
+1. Update from binutils 2011 0716.
+2. Fix LTO linker bugs. PRs 12982/12942.
+3. Fix rorx support in x86 assembler/disassembler for AVX Programming
+Reference (June, 2011).
+4. Fix an x86-64 ELFOSABI linker regression.
+5. Update ELFOSABI_GNU support. PR 12913.
+6. Fix a linker regression with prelink support. PR 12921.
+7. Add unwind info to x86 PLT section. PR 12570.
+8. Support x32 core files.
+9. Support native x32 linker.
+10. Fix linker --gc-sections on note sections. PR 12851.
+11. Avoid linker crash on bad input. PR 12887.
+12. Add section flags in linker script.
+13. Improve elf linker -z option support.
+14. Fix nm on compressed debug sections. PR 12983.
+15. Fix an ar bug. PR 12558.
+16. Fix an ia64 linker regression. PR 12978.
+17. Improve gold.
+18. Improve VMS support.
+19. Add TILE-Gx/TILEPro support.
+20. Improve alpha support.
+21. Improve avr support.
+22. Improve mips support.
+23. Improve arm support.
+24. Improve ppc support.
+25. Improve sh support.
+26. Improve TIC6X support.
+
+Changes from binutils 2.21.52.0.1:
+
+1. Update from binutils 2011 0610.
+2. Support AVX Programming Reference (June, 2011)
+3. Allow R_X86_64_64 relocations in SEC_DEBUGGING sections when building
+x32 shared libraries. Used to build kernel x32 vDSO.
+4. Fix linker --gc-sections on note sections. PR 12851.
+5. Update readelf to handle binaries containing corrupt version
+information. PR 12855.
+6. Improve gold.
+7. Improve VMS support.
+8. Improve mips support.
+
+Changes from binutils 2.21.51.0.9:
+
+1. Update from binutils 2011 0608.
+2. Fix an x86 linker regression. PRs 12833/12837/12859.
+3. Fix an x86-64 large model TLS linker bug. PR 12809.
+4. Fix LTO bugs. PRs 12758/12760.
+5. Add a new linker switch, -plugin-save-temps.
+6. Fix an linker bug for warning on common symbol in archive.
+7. Fix warning support when building shared library. PR 12761.
+8. Reduce linker memory usage when linking many small object files.
+PR 12682.
+9. Fix a thin archive bug. PR 12710.
+10. Fix a TLS linker bug. PR 12763.
+11. Improve gold.
+12. Improve DWARF dump support.
+13. Improve XCOFF support.
+14. Improve arm support.
+15. Improve cris support.
+16. Improve ia64 ILP32 support.
+17. Improve mips support.
+18. Improve ppc support.
+19. Improve rx support.
+20. Improve s390 support.
+21. Improve tic30 support.
+22. Improve tic6x support.
+23. Improve v850 support.
+
+Changes from binutils 2.21.51.0.8:
+
+1. Update from binutils 2011 0507.
+2. Improve LTO bfd linker. PRs 12365/12696/12672
+3. Fix a linker regression with constructor attribute in C++. PR 12730.
+4. Warn relocation in readonly section when creating a shared object.
+5. Remove empty output sections. PR 12718.
+6. Remove DT_TEXTREL with local IFUNC symbols. PR 12694.
+7. Properly set ELFOSABI_LINUX for STB_GNU_UNIQUE. PR 10549.
+8. Fix objcopy on unusual input. PR 12632.
+9. Fix an ar regression. PR 12720.
+10 Avoid linker crash on bad linker input.
+11. Fix a linker script regression. PR 12726.
+12. Support new GNU DWARF extensions.
+13. Initial support for SystemTap note sections.
+14. Add --dwarf-start and --dwarf-end to readelf and objdump.
+15. Disable 3dnow and 3dnowa for bdver1 in x86 assembler.
+16. Improve gold.
+17. Improve VMS support.
+18. Improve arm support.
+19. Improve mips support.
+20. Improve ppc support.
+21. Improve s390 support.
+22. Improve tic6x support.
+
+Changes from binutils 2.21.51.0.7:
+
+1. Update from binutils 2011 0408.
+2. Fix x32 TLS linker bug.
+3. Enable .quad directive in x32 assembler.
+4. Fix an assembler regression. PRs 12569/12589.
+5. Add --size-check= assembler option to issue a warning, instead of an
+error, on bad ELF .size directive.
+6. Fix an ia32 linker bug with TLS/PIE. PR 12654.
+7. Fix Intel L1OM linker library search path.
+8. Fix a linker buffer overflow on malformed inputs. PR 12613.
+9. Check corrupted symtab in nm/readelf. PR 12639.
+10. Avoid objcopy crash on archive with unknown objects. PR 12632.
+11. Fix "ar -t". PR 12590.
+12. Fix many memory leaks.
+13. Improve DWARF support.
+14. Improve gold.
+15. Improve VMS support.
+16. Improve Windows support.
+17. Improve alpha support.
+18. Improve arm support.
+19. Improve avr support.
+20. Improve ppc support.
+21. Improve sparc support.
+22. Improve tic6x support.
+
+Changes from binutils 2.21.51.0.6:
+
+1. Update from binutils 2011 0306.
+2. Supprt x32 TLS IE->LE transition.
+3. Change x32 library directory from /lib32 to /libx32.
+4. Improve LTO linker support. Fix PRs 12439/12314/12248/12430.
+5. Improve linker plugin support.
+6. Fix an ar bug. PR 12513.
+7. Properly generate nops for ia32. PR 6957.
+8. Improve readelf DT_GNU_HASH support. PR 12523.
+9. Improve readelf on invalid input. PR 12467.
+10. Update ELF assembler to issue an error on invalid .size directive.
+PR 12519,
+11. Properly handle PT_DYNAMIC segment with zero size sections. PR 12516.
+12. Add a new linker option, --verbose=2, to report plugin symbol
+status.
+13. Properly handle entry symbols in linker LTO support. PR 12507.
+14. Improve gold.
+15. Improve arm support.
+16. Improve bfin support.
+17. Improve mips support.
+18. Improve ppc support.
+
+Changes from binutils 2.21.51.0.5:
+
+1. Update from binutils 2011 0118.
+2. Fix x32 (ILP32) support. Renamed assembler option to --x32. It
+can create working static and dynamic x32 executables.
+3. Add BMI and TBM new instruction support.
+4. Fix x86 disassembler to properly display sign-extended byte.
+5. Improve IFUNC linker support. PRs 12366/12371.
+6. Fix readelf bug on archive. PR 12408.
+7. Fix a assembler when compressing empty debug sections. PR 12409.
+8. Fix a warning symbol linker bug. PR 12339.
+9. Fix a duplicated assert message linker bug. PR 12380.
+10. Fix plugin linker build. PR 12391.
+11. Fix a plugin linker crash. PR 12364.
+12. Improve plugin linker.
+13. Improve gold.
+14. Improve arm support.
+15. Improve mips support.
+16. Improve rx support.
+
+Changes from binutils 2.21.51.0.4:
+
+1. Update from binutils 2011 0104.
+2. Add ILP32 support:
+
+http://www.kernel.org/pub/linux/devel/binutils/ilp32/abi.pdf
+
+to Linux/x86-64.
+3. Prevent the Linux x86-64 kernel build failure and remove
+__ld_compatibility support. PR 12356.
+4. Improve gold.
+5. Improve Windows support.
+6. Improve hppa support.
+7. Improve mips support.
+
+Changes from binutils 2.21.51.0.3:
+
+1. Update from binutils 2010 1217.
+2. Fix the Linux relocatable kernel build. PR 12327.
+3. Improve mips support.
+
+Changes from binutils 2.21.51.0.2:
+
+1. Update from binutils 2010 1215.
+2. Add BFD linker support for placing input .ctors/.dtors sections in
+output .init_array/.fini_array section. Add SORT_BY_INIT_PRIORITY. The
+benefits are
+ a. Avoid output .ctors/.dtors section in executables and shared
+ libraries.
+ b. Allow mixing input .ctors/.dtors sections with input
+ .init_array/.fini_array sectiobs. GCC PR 46770.
+3. Add BFD linker support for "ld -r" on mixed IR/non-IR objects. Add
+the new ELF section type SHT_GNU_OBJECT_ONLY (0x6ffffff8). See
+
+http://sourceware.org/bugzilla/show_bug.cgi?id=12291
+
+4. Update BFD linker to accept -flto and -flto-partition= for GCC LTO
+option compatibility.
+5. Fix BFD linker to avoid touching uncompressed section content when
+relocating DWARF debug sections for errror reporting.
+6. Mark .gnu.lto_* sections with SHF_EXCLUDE.
+7. Add --target option to ar.
+8. Improve gold.
+9. Improve AIX support.
+10. Improve Windows support.
+11. Improve mips support.
+
+Changes from binutils 2.21.51.0.1:
+
+1. Update from binutils 2010 1206.
+2. Fix BFD and GOLD linker for compressed debug section support.
+3. Fix BFD linker plugin support. PR ld/12246, ld/12247, ld/12248,
+ld/12277, ld/12288 and ld/12289.
+4. Update BFD linker to group .text.exit, text.startup and .text.hot
+sections.
+5. Fix linker for W_EH_PE_datarel handling. PR ld/12253.
+6. Fix array access bug in readelf/elfedit. PR binutils/11742 and
+binutils/12235.
+7. Support dumping GDB .gdb_index section.
+8. Install plugin-api.h.
+9. Improve gold.
+10. Improve Solaris support.
+11. Improve VMS support.
+12. Improve Windows support.
+13. Improve arm support.
+14. Improve bfin support.
+15. Improve mips support.
+16. Improve s390 support.
+17. Improve z80 support.
+
+Changes from binutils 2.20.51.0.12:
+
+1. Update from binutils 2010 1110.
+2. Fix ld plugin support. PRs lto/46291 and lto/46319.
+3. Fix x86 assembler to properly fold _GLOBAL_OFFSET_TABLE_ in Intel
+syntax. PR 12186.
+4. Update assembler to ensure that group signature symbols have the name
+of the group.
+5. Avoid unnecessary relaxation in assembler. PR 12049.
+6. Update linker NOLOAD processing.
+7. Update linker not to include archive members when symbols therein have
+already been defined. PR 12001.
+8. Change objdump to display compressed section names without 'z'.
+9. Improve gold.
+10. Improve Solaris support.
+11. Improve VMS support.
+12. Improve Windows support.
+13. Improve arm support.
+14. Improve cr16 support.
+15. Improve mips support.
+16. Improve ppc support.
+17. Improve tic6x support.
+
+The file list:
+
+1. binutils-2.24.51.0.3.tar.bz2. Source code.
+
+The primary sites for the beta Linux binutils are:
+
+1. http://www.kernel.org/pub/linux/devel/binutils/
+
+It is also available as hjl/linux/release/2.24.51.0.3 tag at
+
+https://sourceware.org/git/?p=binutils-gdb.git;a=summary
+
+Thanks.
+
+
+H.J. Lu
+hjl.tools@gmail.com
+01/27/2014