Merge remote-tracking branch 'local/linux/master' into linux/release/2.22.52.0.4
Conflicts:
bfd/elf32-i386.c
bfd/elf64-x86-64.c
bfd/elflink.c
binutils/objcopy.c
ld/lexsup.c
ld/scripttempl/armbpabi.sc
ld/scripttempl/elf.sc
ld/scripttempl/elf64hppa.sc
ld/scripttempl/elfxtensa.sc
ld/scripttempl/mep.sc
diff --git a/ChangeLog.patches b/ChangeLog.patches
new file mode 100644
index 0000000..f962392
--- /dev/null
+++ b/ChangeLog.patches
@@ -0,0 +1,750 @@
+bfd/
+
+2006-10-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/3351
+ * elflink.c (_bfd_elf_update_dynamic_flags): New.
+ (_bfd_elf_merge_symbol): Update both real and indirect symbol
+ dynamic flags.
+ (_bfd_elf_add_default_symbol): Make the real symbol dynamic if
+ the indirect symbol is defined in a shared library.
+ (elf_link_add_object_symbols): Likewise. If the indirect
+ symbol has been forced local, don't make the real symbol
+ dynamic.
+ (elf_link_check_versioned_symbol): Check indirect symbol.
+ (elf_link_output_extsym): Use real symbol definition when
+ reporting indirect symbol error. Check version info for
+ dynamic versioned symbol.
+
+ld/testsuite/
+
+2011-09-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/13195
+ * ld-elf/pr13195.d: New.
+ * ld-elf/pr13195.s: Likewise.
+ * ld-elf/pr13195.t: Likewise.
+
+2006-10-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/3351
+ * ld-elf/indirect.exp: New file.
+ * ld-elf/indirect1a.c: Likewise.
+ * ld-elf/indirect1b.c: Likewise.
+ * ld-elf/indirect1c.c: Likewise.
+ * ld-elf/indirect2.c: Likewise.
+ * ld-elf/indirect3.out: Likewise.
+ * ld-elf/indirect3a.c: Likewise.
+ * ld-elf/indirect3b.c: Likewise.
+ * ld-elf/indirect3c.c: Likewise.
+ * ld-elf/indirect4.out: Likewise.
+ * ld-elf/indirect4a.c: Likewise.
+ * ld-elf/indirect4b.c: Likewise.
+ * ld-elf/indirect4c.c: Likewise.
+
+diff --git a/bfd/elflink.c b/bfd/elflink.c
+index 5d181f7..da6a68c 100644
+bfd/
+
+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/elf-bfd.h b/bfd/elf-bfd.h
+index d6e2ab2..8660802 100644
+bfd/
+
+2011-01-12 Bernhard Rosenkränzer <bernhard.rosenkranzer@linaro.org>
+
+ * elf32-epiphany.c (epiphany_elf_relocate_section): Add an
+ argument for error ignored.
+ * elf32-rl78.c (rl78_elf_relocate_section): Likewise.
+ * elf32-tilepro.c (tilepro_elf_relocate_section): Likewise.
+ * elfxx-tilegx.c (tilegx_elf_relocate_section): Likewise.
+
+2010-07-01 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elf-bfd.h (RELOC_FOR_GLOBAL_SYMBOL): Silence unused warning
+ on ignored.
+
+ * elf32-tic6x.c (elf32_tic6x_relocate_section): Add an argument for
+ error ignored.
+
+2007-07-03 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/4409
+ * elf-bfd.h (RELOC_FOR_GLOBAL_SYMBOL): Add an argument for
+ error ignored.
+ * elf-m10200.c (mn10200_elf_relocate_section): Updated.
+ * elf-m10300.c (mn10300_elf_relocate_section): Likewise.
+ * elf32-arm.c (elf32_arm_relocate_section): Likewise.
+ * elf32-avr.c (elf32_avr_relocate_section): Likewise.
+ * elf32-bfin.c (bfinfdpic_relocate_section): Likewise.
+ (bfin_relocate_section): Likewise.
+ * elf32-cr16.c (elf32_cr16_relocate_section): Likewise.
+ * elf32-cr16c.c (elf32_cr16c_relocate_section): Likewise.
+ * elf32-cris.c (cris_elf_relocate_section): Likewise.
+ * elf32-crx.c (elf32_crx_relocate_section): Likewise.
+ * elf32-d10v.c (elf32_d10v_relocate_section): Likewise.
+ * elf32-fr30.c (fr30_elf_relocate_section): Likewise.
+ * elf32-frv.c (elf32_frv_relocate_section): Likewise.
+ * elf32-h8300.c (elf32_h8_relocate_section): Likewise.
+ * elf32-hppa.c (elf32_hppa_relocate_section): Likewise.
+ * elf32-i386.c (elf_i386_relocate_section): Likewise.
+ * elf32-i860.c (elf32_i860_relocate_section): Likewise.
+ * elf32-ip2k.c (ip2k_elf_relocate_section): Likewise.
+ * elf32-iq2000.c (iq2000_elf_relocate_section): Likewise.
+ * elf32-lm32.c (lm32_elf_relocate_section): Likewise.
+ * elf32-m68hc1x.c (elf32_m68hc11_relocate_section): Likewise.
+ * elf32-m68k.c (elf_m68k_relocate_section): Likewise.
+ * elf32-microblaze.c (microblaze_elf_relocate_section): Likewise.
+ * elf32-mcore.c (mcore_elf_relocate_section): Likewise.
+ * elf32-mep.c (mep_elf_relocate_section): Likewise.
+ * elf32-moxie.c (moxie_elf_relocate_section): Likewise.
+ * elf32-msp430.c (elf32_msp430_relocate_section): Likewise.
+ * elf32-mt.c (mt_elf_relocate_section): Likewise.
+ * elf32-openrisc.c (openrisc_elf_relocate_section): Likewise.
+ * elf32-ppc.c (ppc_elf_relocate_section): Likewise.
+ * elf32-rx.c (rx_elf_relocate_section): Likewise.
+ * elf32-s390.c (elf_s390_relocate_section): Likewise.
+ * elf32-v850.c (v850_elf_relocate_section): Likewise.
+ * elf32-vax.c (elf_vax_relocate_section): Likewise.
+ * elf32-xc16x.c (elf32_xc16x_relocate_section): Likewise.
+ * elf32-xstormy16.c (xstormy16_elf_relocate_section): Likewise.
+ * elf32-xtensa.c (elf_xtensa_relocate_section): Likewise.
+ * elf64-alpha.c (elf64_alpha_relocate_section): Likewise.
+ * elf64-mmix.c (mmix_elf_relocate_section): Likewise.
+ * elf64-ppc.c (ppc64_elf_relocate_section): Likewise.
+ * elf64-s390.c (elf_s390_relocate_section): Likewise.
+ * elf64-x86-64.c (elf64_x86_64_relocate_section): Likewise.
+ * elfxx-sparc.c (_bfd_sparc_elf_relocate_section): Likewise.
+
+ * elfnn-ia64.c (elfNN_ia64_relocate_section): Skip if error
+ from RELOC_FOR_GLOBAL_SYMBOL in executable is ignored.
+
+ld/
+
+2007-07-03 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/4409
+ * ldmain.c (how_to_report_unresolved_symbols): New.
+ (main): Set link_info.unresolved_syms_in_objects and
+ link_info.unresolved_syms_in_shared_libs if they aren't set
+ yet.
+
+ * ldmain.h (how_to_report_unresolved_symbols): New.
+
+ * lexsup.c (how_to_report_unresolved_symbols): Removed.
+ (parse_args): Set link_info.pie to FALSE for -shared. Don't
+ set default values for link_info.unresolved_syms_in_objects nor
+ link_info.unresolved_syms_in_shared_libs.
+
+ld/testsuite/
+
+2007-07-03 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/4409
+ * ld-ia64/error1.d: New file.
+ * ld-ia64/error1.s: Likewise.
+ * ld-ia64/error2.d: Likewise.
+ * ld-ia64/error3.d: Likewise.
+ * ld-ia64/error4.d: Likewise.
+
+diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
+index c7846e1..7d047e8 100644
+diff --git a/binutils/ChangeLog.addend b/binutils/ChangeLog.addend
+new file mode 100644
+index 0000000..e0bd096
+bfd/
+
+2007-07-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elflink.c (elf_link_add_object_symbols): Check symbol type
+ for symbol alias in a dynamic object.
+
+ld/testsuite/
+
+2007-07-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld-elf/data2.c: New.
+ * ld-elf/weakdef1.c: Likewise.
+
+ * ld-elf/shared.exp: Add tests for libdata2 and weakdef1.
+
+2008-03-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ * elf.c (assign_section_numbers): Check if number of sections
+ >= SHN_LORESERVE.
+ * elfcode.h (elf_object_p): Likewise.
+
+bfd/
+
+2011-10-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ * plugin.c (add_symbols): Call
+ bfd_plugin_get_symbols_in_object_only.
+ (bfd_plugin_get_symtab_upper_bound): Don't call
+ bfd_plugin_get_symbols_in_object_only.
+
+2011-10-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ * plugin.c (bfd_plugin_get_symbols_in_object_only): Optimized.
+
+2011-10-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ * plugin.c (bfd_plugin_get_symbols_in_object_only): Properly
+ remove the object only section file.
+
+2011-10-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/13298
+ * opncls.c (bfd_extract_object_only_section): New.
+
+ * plugin.c (add_symbols): Initialize object_only_syms and
+ object_only_nsyms.
+ (bfd_plugin_fake_text_section): New.
+ (bfd_plugin_fake_common_section): Likewise.
+ (bfd_plugin_get_symbols_in_object_only): Likewise.
+ (bfd_plugin_get_symtab_upper_bound): Call
+ bfd_plugin_get_symbols_in_object_only and add symbols from
+ object only section.
+ (bfd_plugin_canonicalize_symtab): Remove fake_section and
+ fake_common_section. Use bfd_plugin_fake_text_section and
+ bfd_plugin_fake_common_section. Set udata.p to NULL. Copy
+ symbols from object only section.
+
+ * plugin.h (plugin_data_struct): Add object_only_nsyms and
+ object_only_syms.
+
+ * bfd-in2.h: Regenerated.
+
+2011-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/12758
+ * elflink.c (elf_link_add_archive_symbols): Don't load the IR
+ archive member twice.
+
+2011-04-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * bfd.c (bfd_lto_object_type): New.
+ (bfd): Add object_only_section and lto_type.
+ (bfd_group_signature): New.
+
+ * elf.c (special_sections_g): Add .gnu_object_only.
+
+ * format.c (bfd_set_lto_type): New.
+ (bfd_check_format_matches): Use it.
+
+ * section.c (GNU_OBJECT_ONLY_SECTION_NAME): New.
+
+ * bfd-in2.h: Regenerated.
+
+binutils/
+
+2011-04-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * objcopy.c (group_signature): Removed.
+ (is_strip_section): Replace group_signature with
+ bfd_group_signature.
+ (setup_section): Likewise.
+
+ * readelf.c (get_section_type_name): Handle SHT_GNU_OBJECT_ONLY.
+
+gas/testsuite/
+
+2011-04-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gas/elf/section9.s: Add the .gnu_object_only test.
+ * gas/elf/section9.d: Updated.
+
+include/
+
+2011-04-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * bfdlink.h (bfd_link_info): Add emit_gnu_object_only and
+ emitting_gnu_object_only.
+
+include/elf/
+
+2011-04-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * common.h (SHT_GNU_OBJECT_ONLY): New.
+
+ld/
+
+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>
+
+ * lexsup.c (option_values): Add OPTION_PLUGIN_SAVE_TEMPS.
+ (ld_options): Add -plugin-save-temps.
+ (parse_args): Handle OPTION_PLUGIN_SAVE_TEMPS.
+
+ * plugin.c (plugin_save_temps): New.
+ (plugin_call_cleanup): Don't call plugin cleanup_handler if
+ plugin_save_temps is true.
+
+ * plugin.h (plugin_save_temps): New.
+
+2011-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/12760
+ * ldmain.c (warning_callback): Don't warn plugin dummy.
+
+2011-04-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * emultempl/alphaelf.em (alpha_finish): Replace finish_default
+ with gld${EMULATION_NAME}_finish.
+
+ * emultempl/armelf.em (gld${EMULATION_NAME}_finish): Renamed
+ to ...
+ (arm_finish): This. Replace finish_default with
+ gld${EMULATION_NAME}_finish.
+ (LDEMUL_FINISH): Set to arm_finish.
+
+ * emultempl/elf32.em (gld${EMULATION_NAME}_finish): New.
+ (orphan_init_done): Likewise.
+ (ld_${EMULATION_NAME}_emulation): Use gld${EMULATION_NAME}_finish.
+ (gld${EMULATION_NAME}_place_orphan): Initialize hold.
+
+ * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Renamed
+ to ...
+ (ppc_finish): This. Replace finish_default with
+ gld${EMULATION_NAME}_finish.
+ (LDEMUL_FINISH): Set to ppc_finish.
+
+ * emultempl/spuelf.em (gld${EMULATION_NAME}_finish): Renamed
+ to ...
+ (spu_finish): This. Replace finish_default with
+ gld${EMULATION_NAME}_finish.
+ (LDEMUL_FINISH): Set to spu_finish.
+
+ * ldfile.c (ldfile_try_open_bfd): Call
+ cmdline_check_object_only_section.
+
+ * ldlang.c: Include "ldwrite.h" and elf-bfd.h.
+ * ldlang.c (cmdline_object_only_file_list): New.
+ (cmdline_object_only_archive_list): Likewise.
+ (cmdline_temp_object_only_list): Likewise.
+ (cmdline_lists_init): Likewise.
+ (cmdline_list_new): Likewise.
+ (cmdline_list_append): Likewise.
+ (print_cmdline_list): Likewise.
+ (cmdline_on_object_only_archive_list_p): Likewise.
+ (cmdline_object_only_list_append): Likewise.
+ (cmdline_get_object_only_input_files): Likewise.
+ (cmdline_arg): Likewise.
+ (setup_section): Likewise.
+ (copy_section): Likewise.
+ (cmdline_fopen_temp): Likewise.
+ (cmdline_add_object_only_section): Likewise.
+ (cmdline_emit_object_only_section): Likewise.
+ (cmdline_extract_object_only_section): Likewise.
+ (cmdline_check_object_only_section): Likewise.
+ (cmdline_remove_object_only_files): Likewise.
+ (lang_init): Take a bfd_boolean argument to supprt object-only
+ output. Call cmdline_lists_init.
+ (load_symbols): Call cmdline_on_object_only_archive_list_p
+ to check if an archive member should be loaded.
+ (lang_process): Handle object-only link.
+
+ * ldlang.h (lang_init): Take a bfd_boolean argument.
+ (cmdline_enum_type): New.
+ (cmdline_header_type): Likewise.
+ (cmdline_file_type): Likewise.
+ (cmdline_bfd_type): Likewise.
+ (cmdline_union_type): Likewise.
+ (cmdline_list_type): Likewise.
+ (cmdline_emit_object_only_section): Likewise.
+ (cmdline_check_object_only_section): Likewise.
+ (cmdline_remove_object_only_files): Likewise.
+
+ * ldmain.c (main): Call xatexit with
+ cmdline_remove_object_only_files. Pass FALSE to lang_init.
+ Use ld_parse_linker_script. Set link_info.output_bfd to NULL
+ after close. Call cmdline_emit_object_only_section if needed.
+ (add_archive_element): Call cmdline_check_object_only_section.
+ (ld_parse_linker_script): New.
+
+ * ldmain.h (ld_parse_linker_script): New.
+
+ * plugin.c (plugin_opt_plugin_arg): Ignore -pass-through=.
+ (plugin_maybe_claim): Call cmdline_check_object_only_section
+ on claimed IR files.
+
+ * scripttempl/armbpabi.sc: Also discard .gnu_object_only
+ sections.
+ * scripttempl/elf.sc: Likewise.
+ * scripttempl/elf32sh-symbian.sc: Likewise.
+ * scripttempl/elf64hppa.sc: Likewise.
+ * scripttempl/elfxtensa.sc: Likewise.
+ * scripttempl/mep.sc: Likewise.
+ * scripttempl/pe.sc: Likewise.
+ * scripttempl/pep.sc: Likewise.
+
+ld/testsuite/
+
+2011-10-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/13287
+ * ld-plugin/lto.exp (lto_link_tests): Add a test for PR ld/13287.
+
+ * ld-plugin/pr13287.cc: New.
+
+2011-10-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/13229
+ PR ld/13244
+ * ld-plugin/lto.exp (lto_link_elf_tests): Add tests for PRs
+ ld/13229 and ld/13244.
+
+ * ld-plugin/pr13229.cc: New.
+ * ld-plugin/pr13229.d: Likewise.
+ * ld-plugin/pr13244.c: Likewise.
+ * ld-plugin/pr13244.d: Likewise.
+
+2011-09-23 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/13201
+ * ld-plugin/lto.exp (lto_link_tests): Add a test for PR ld/13201.
+ (lto_run_tests): Likewise.
+
+ * ld-plugin/pr13201.c: New.
+ * ld-plugin/pr13201.out: Likewise.
+
+2011-09-16 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/12975
+ * ld-plugin/lto.exp (lto_link_elf_tests): Add a test for PR
+ ld/12975.
+
+ * ld-plugin/pr12975.c: New.
+ * ld-plugin/pr12975.d: Likewise.
+ * ld-plugin/pr12975.t: Likewise.
+
+2011-09-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/13183
+ * ld-plugin/lto.exp (lto_link_tests): Add tests for PR ld/13183.
+ (lto_link_symbol_tests): Likewise.
+
+ * ld-plugin/pr13183.d: New.
+ * ld-plugin/pr13183a.c: Likewise.
+ * ld-plugin/pr13183b.c: Likewise.
+
+ * lib/ld-lib.exp (ar_simple_create): Pass -rc to ar.
+
+2011-08-09 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/13066
+ * ld-plugin/lto.exp (lto_run_tests): Add a test for PR ld/13066.
+
+ * ld-plugin/pr13066.cc: New.
+ * ld-plugin/pr13066.out: Likewise.
+
+2011-07-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/12942
+ * ld-plugin/lto.exp (lto_link_elf_tests): Add a test for PR
+ ld/12982.
+
+ * ld-plugin/pr12982.c: New.
+ * ld-plugin/pr12982.d: Likewise.
+
+2011-07-09 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/12942
+ * ld-plugin/lto.exp (lto_link_tests): Add tests for PR ld/12942.
+ (lto_run_tests): Likewise.
+ Add "PR ld/12942 (3)" test.
+
+ * ld-plugin/pr12942.out: New.
+ * ld-plugin/pr12942a.cc: Likewise.
+ * ld-plugin/pr12942a.h: Likewise.
+ * ld-plugin/pr12942b.cc: Likewise.
+ * ld-plugin/pr12942c.cc: Likewise.
+
+2011-06-29 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld-plugin/lto.exp (lto_link_elf_tests): Add 2 LTO ELF DSO
+ tests.
+
+ * ld-plugin/lto-17a.c: New.
+ * ld-plugin/lto-17a.d: Likewise.
+ * ld-plugin/lto-17b-1.d: Likewise.
+ * ld-plugin/lto-17b-2.d: Likewise.
+ * ld-plugin/lto-17b.c: Likewise.
+
+2011-06-29 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld-plugin/lto.exp (lto_link_elf_tests): Add 2 LTO ELF DSO
+ tests.
+
+ * ld-plugin/lto-17a.c: New.
+ * ld-plugin/lto-17a.d: Likewise.
+ * ld-plugin/lto-17b-1.d: Likewise.
+ * ld-plugin/lto-17b-2.d: Likewise.
+ * ld-plugin/lto-17b.c: Likewise.
+
+2011-06-29 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld-plugin/lto.exp (lto_run_elf_tests): Add "LTO TLS IE".
+
+ * ld-plugin/run-ie.c: New.
+ * ld-plugin/run-ie.out: Likewise.
+
+2011-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/12760
+ * ld-plugin/lto.exp (lto_link_tests): Add tests for PR ld/12760.
+
+ * ld-plugin/pr12760a.s: New.
+ * ld-plugin/pr12760b.c: Likewise.
+
+2011-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/12758
+ * ld-plugin/lto.exp (lto_link_tests): Add tests for PR ld/12758.
+
+ * ld-plugin/pr12758a.s: New.
+ * ld-plugin/pr12758b.c: Likewise.
+
+2011-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld-plugin/lto.exp (lto_link_symbol_tests): Replace "-e foo"
+ with "-Wl,-e,foo".
+
+2011-04-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ld-plugin/dummy.c: New.
+ * ld-plugin/dummy.s: Likewise.
+ * ld-plugin/func1p.c: Likewise.
+ * ld-plugin/func2i.c: Likewise.
+ * ld-plugin/func3h.c: Likewise.
+ * ld-plugin/lto-10.out: Likewise.
+ * ld-plugin/lto-10a.c: Likewise.
+ * ld-plugin/lto-10b.c: Likewise.
+ * ld-plugin/lto-10r.d: Likewise.
+ * ld-plugin/lto-11.out: Likewise.
+ * ld-plugin/lto-11a.c: Likewise.
+ * ld-plugin/lto-11b.c: Likewise.
+ * ld-plugin/lto-11c.c: Likewise.
+ * ld-plugin/lto-12.out: Likewise.
+ * ld-plugin/lto-12a.c: Likewise.
+ * ld-plugin/lto-12b.c: Likewise.
+ * ld-plugin/lto-12c.c: Likewise.
+ * ld-plugin/lto-13.out: Likewise.
+ * ld-plugin/lto-13a.c: Likewise.
+ * ld-plugin/lto-13b.c: Likewise.
+ * ld-plugin/lto-13c.c: Likewise.
+ * ld-plugin/lto-14.out: Likewise.
+ * ld-plugin/lto-14a.c: Likewise.
+ * ld-plugin/lto-14b.c: Likewise.
+ * ld-plugin/lto-14c.c: Likewise.
+ * ld-plugin/lto-15.out: Likewise.
+ * ld-plugin/lto-15a.c: Likewise.
+ * ld-plugin/lto-15b.c: Likewise.
+ * ld-plugin/lto-16a.c: Likewise.
+ * ld-plugin/lto-16a.d: Likewise.
+ * ld-plugin/lto-16b.c: Likewise.
+ * ld-plugin/lto-16b.d: Likewise.
+ * ld-plugin/lto-1a.c: Likewise.
+ * ld-plugin/lto-1b.c: Likewise.
+ * ld-plugin/lto-2.c: Likewise.
+ * ld-plugin/lto-3.d: Likewise.
+ * ld-plugin/lto-3.out: Likewise.
+ * ld-plugin/lto-3a.c: Likewise.
+ * ld-plugin/lto-3b.c: Likewise.
+ * ld-plugin/lto-3c.c: Likewise.
+ * ld-plugin/lto-3r.d: Likewise.
+ * 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-5.d: Likewise.
+ * ld-plugin/lto-5.out: Likewise.
+ * ld-plugin/lto-5a.c: Likewise.
+ * ld-plugin/lto-5b.c: Likewise.
+ * ld-plugin/lto-5r.d: Likewise.
+ * ld-plugin/lto-6.c: Likewise.
+ * ld-plugin/lto-7.out: Likewise.
+ * ld-plugin/lto-7a.c: Likewise.
+ * ld-plugin/lto-7b.c: Likewise.
+ * ld-plugin/lto-7c.c: Likewise.
+ * ld-plugin/lto-7d.c: Likewise.
+ * ld-plugin/lto-8.out: Likewise.
+ * ld-plugin/lto-8a.c: Likewise.
+ * ld-plugin/lto-8b.c: Likewise.
+ * ld-plugin/lto-9.cc: Likewise.
+ * ld-plugin/lto-9.d: Likewise.
+ * ld-plugin/lto.exp: Likewise.
+ * ld-plugin/pr12365a.c: Likewise.
+ * ld-plugin/pr12365b.c: Likewise.
+ * ld-plugin/pr12365c.c: Likewise.
+ * ld-plugin/pr12696-1.cc: Likewise.
+
+ * ld-plugin/plugin.exp: Add object files for symbols claimed
+ or created by testplugin.
+
+ * lib/ld-lib.exp (check_lto_available): New.
+
+diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
+index 22fcdf6..a84b030 100644
+bfd/
+
+2011-04-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR binutils/12639
+ * elfcode.h (elf_slurp_symbol_table): Check valid local symbols.
+
+binutils/
+
+2011-04-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR binutils/12639
+ * readelf.c (process_symbol_table): Detect corrupted symtab.
+
+diff --git a/bfd/elfcode.h b/bfd/elfcode.h
+index 28b6b90..c56b4f1 100644
+diff --git a/gas/ChangeLog.x32 b/gas/ChangeLog.x32
+new file mode 100644
+index 0000000..9cbb5b7
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 585a54a..3429d96 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1028,6 +1028,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. */
@@ -1553,6 +1556,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 (&std_section[0])
/* Pointer to the undefined section. */
@@ -5438,6 +5444,14 @@
both_direction = 3
};
+enum bfd_lto_object_type
+ {
+ lto_non_object,
+ lto_non_ir_object,
+ lto_ir_object,
+ lto_mixed_object
+ };
+
struct bfd
{
/* A unique identifier of the BFD */
@@ -5585,6 +5599,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;
@@ -5703,6 +5720,9 @@
/* Set if only required symbols should be added in the link hash table for
this object. Used by VMS linkers. */
unsigned int selective_search : 1;
+
+ /* LTO object type. */
+ unsigned int lto_type : 2;
};
typedef enum bfd_error
@@ -5919,6 +5939,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 640b420..9cdac38 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -43,6 +43,14 @@
. both_direction = 3
. };
.
+.enum bfd_lto_object_type
+. {
+. lto_non_object,
+. lto_non_ir_object,
+. lto_ir_object,
+. lto_mixed_object
+. };
+.
.struct bfd
.{
. {* A unique identifier of the BFD *}
@@ -190,6 +198,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;
.
@@ -308,6 +319,9 @@
. {* Set if only required symbols should be added in the link hash table for
. this object. Used by VMS linkers. *}
. unsigned int selective_search : 1;
+.
+. {* LTO object type. *}
+. unsigned int lto_type : 2;
.};
.
*/
@@ -2021,3 +2035,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 6918d5a..dee0e83 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2124,6 +2124,28 @@
(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 bfd_link_info *, struct elf_link_hash_entry **,
+ struct elf_link_hash_entry *, Elf_Internal_Sym *, asection **,
+ bfd_vma *, unsigned int *, bfd_boolean *, bfd_boolean *,
+ bfd_boolean *, bfd_boolean *, bfd_boolean *, bfd_boolean *,
+ bfd_boolean *, bfd_boolean *, bfd *, asection **,
+ bfd_boolean *, bfd_boolean *, bfd_boolean *, bfd_boolean *,
+ bfd *, asection **);
extern bfd_boolean bfd_elf_link_record_dynamic_symbol
(struct bfd_link_info *, struct elf_link_hash_entry *);
@@ -2349,7 +2371,7 @@
#define RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel, \
r_symndx, symtab_hdr, sym_hashes, \
h, sec, relocation, \
- unresolved_reloc, warned) \
+ unresolved_reloc, warned, ignored) \
do \
{ \
/* It seems this can happen with erroneous or unsupported \
@@ -2364,6 +2386,7 @@
h = (struct elf_link_hash_entry *) h->root.u.i.link; \
\
warned = FALSE; \
+ ignored = FALSE; \
unresolved_reloc = FALSE; \
relocation = 0; \
if (h->root.type == bfd_link_hash_defined \
@@ -2386,7 +2409,7 @@
; \
else if (info->unresolved_syms_in_objects == RM_IGNORE \
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) \
- ; \
+ ignored = TRUE; \
else if (!info->relocatable) \
{ \
bfd_boolean err; \
@@ -2402,6 +2425,7 @@
} \
(void) unresolved_reloc; \
(void) warned; \
+ (void) ignored; \
} \
while (0)
diff --git a/bfd/elf-m10200.c b/bfd/elf-m10200.c
index a46c86d..e48857b 100644
--- a/bfd/elf-m10200.c
+++ b/bfd/elf-m10200.c
@@ -393,12 +393,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c
index 8b5afa5..0780c9c 100644
--- a/bfd/elf-m10300.c
+++ b/bfd/elf-m10300.c
@@ -2013,7 +2013,7 @@
bfd_reloc_status_type r;
int tls_r_type;
bfd_boolean unresolved_reloc = FALSE;
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
struct elf_link_hash_entry * hh;
relocation = 0;
@@ -2036,7 +2036,7 @@
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
hh, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
h = elf_mn10300_hash_entry (hh);
diff --git a/bfd/elf.c b/bfd/elf.c
index ac7be2c..9ba3679 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2104,12 +2104,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 }
};
@@ -2164,6 +2167,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 }
};
@@ -3014,6 +3019,13 @@
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name);
}
+ if (section_number >= SHN_LORESERVE)
+ {
+ _bfd_error_handler (_("%B: too many sections: %u"),
+ abfd, section_number);
+ return FALSE;
+ }
+
_bfd_elf_strtab_finalize (elf_shstrtab (abfd));
t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
@@ -3609,6 +3621,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)
@@ -3780,6 +3818,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;
@@ -4087,6 +4127,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. */
@@ -4114,6 +4170,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_tdata (abfd)->eh_frame_hdr;
@@ -4644,6 +4754,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
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 10d5dcc..316b85c 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -10471,12 +10471,12 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
sym_type = h->type;
}
diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c
index 38e41df..84e5379 100644
--- a/bfd/elf32-avr.c
+++ b/bfd/elf32-avr.c
@@ -1225,12 +1225,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf32-bfin.c b/bfd/elf32-bfin.c
index c7f634b..3d74ad6 100644
--- a/bfd/elf32-bfin.c
+++ b/bfd/elf32-bfin.c
@@ -1436,12 +1436,12 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
@@ -2655,13 +2655,13 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
bfd_boolean unresolved_reloc;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
osec = sec;
}
diff --git a/bfd/elf32-cr16.c b/bfd/elf32-cr16.c
index 56d1c54..b4b4618 100644
--- a/bfd/elf32-cr16.c
+++ b/bfd/elf32-cr16.c
@@ -1423,12 +1423,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-cr16c.c b/bfd/elf32-cr16c.c
index ea22701..9056f36 100644
--- a/bfd/elf32-cr16c.c
+++ b/bfd/elf32-cr16c.c
@@ -715,12 +715,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-cris.c b/bfd/elf32-cris.c
index 1f7d20d..6b20a7e 100644
--- a/bfd/elf32-cris.c
+++ b/bfd/elf32-cris.c
@@ -1106,13 +1106,13 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
bfd_boolean unresolved_reloc;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
symname = h->root.root.string;
diff --git a/bfd/elf32-crx.c b/bfd/elf32-crx.c
index b4cbd77..60f62f6 100644
--- a/bfd/elf32-crx.c
+++ b/bfd/elf32-crx.c
@@ -865,12 +865,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-d10v.c b/bfd/elf32-d10v.c
index 246e5f5..debfeb6 100644
--- a/bfd/elf32-d10v.c
+++ b/bfd/elf32-d10v.c
@@ -455,12 +455,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-epiphany.c b/bfd/elf32-epiphany.c
index b427ef3..f796a67 100644
--- a/bfd/elf32-epiphany.c
+++ b/bfd/elf32-epiphany.c
@@ -515,11 +515,12 @@
{
bfd_boolean warned ATTRIBUTE_UNUSED;
bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf32-fr30.c b/bfd/elf32-fr30.c
index 89aab88..54a5bec 100644
--- a/bfd/elf32-fr30.c
+++ b/bfd/elf32-fr30.c
@@ -568,12 +568,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c
index 05e9c58..c162915 100644
--- a/bfd/elf32-frv.c
+++ b/bfd/elf32-frv.c
@@ -2801,13 +2801,13 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
bfd_boolean unresolved_reloc;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
osec = sec;
name = h->root.root.string;
}
diff --git a/bfd/elf32-h8300.c b/bfd/elf32-h8300.c
index 758dc75..203cc7a 100644
--- a/bfd/elf32-h8300.c
+++ b/bfd/elf32-h8300.c
@@ -452,12 +452,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index 8d86cb8..f4aa1ab 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -3706,13 +3706,14 @@
else
{
struct elf_link_hash_entry *eh;
- bfd_boolean unresolved_reloc;
+ bfd_boolean unresolved_reloc, ignored;
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rela,
r_symndx, symtab_hdr, sym_hashes,
eh, sym_sec, relocation,
- unresolved_reloc, warned_undef);
+ unresolved_reloc, warned_undef,
+ ignored);
if (!info->relocatable
&& relocation == 0
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 6aa386d..9efd2a6 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -813,6 +813,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. */
@@ -955,6 +958,8 @@
ret->tls_module_base = NULL;
ret->next_jump_slot_index = 0;
ret->next_irelative_index = 0;
+ ret->sdynsharablebss = NULL;
+ ret->srelsharablebss = NULL;
ret->loc_hash_table = htab_try_create (1024,
elf_i386_local_htab_hash,
@@ -1003,10 +1008,19 @@
htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
if (!info->shared)
- htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss");
+ {
+ htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss");
+ htab->sdynsharablebss
+ = bfd_get_section_by_name (dynobj, ".dynsharablebss");
+ htab->srelsharablebss
+ = bfd_get_section_by_name (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
@@ -2183,17 +2197,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);
}
@@ -2769,6 +2789,7 @@
|| s == htab->elf.iplt
|| s == htab->elf.igotplt
|| s == htab->plt_eh_frame
+ || s == htab->sdynsharablebss
|| s == htab->sdynbss)
{
/* Strip these too. */
@@ -3192,11 +3213,12 @@
else
{
bfd_boolean warned ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
@@ -4591,21 +4613,27 @@
{
Elf_Internal_Rela rel;
bfd_byte *loc;
+ 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);
- loc = htab->srelbss->contents;
- loc += htab->srelbss->reloc_count++ * sizeof (Elf32_External_Rel);
+ loc = s->contents;
+ loc += s->reloc_count++ * sizeof (Elf32_External_Rel);
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
}
@@ -4925,7 +4953,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 bfd_elf32_i386_vec
@@ -4979,6 +5008,19 @@
#undef elf_backend_post_process_headers
#define elf_backend_post_process_headers _bfd_elf_set_osabi
+#define elf_backend_section_from_bfd_section \
+ _bfd_elf_sharable_section_from_bfd_section
+#define elf_backend_symbol_processing \
+ _bfd_elf_sharable_symbol_processing
+#define elf_backend_common_section_index \
+ _bfd_elf_sharable_common_section_index
+#define elf_backend_common_section \
+ _bfd_elf_sharable_common_section
+#define elf_backend_common_definition \
+ _bfd_elf_sharable_common_definition
+#define elf_backend_merge_symbol \
+ _bfd_elf_sharable_merge_symbol
+
#include "elf32-target.h"
/* FreeBSD support. */
diff --git a/bfd/elf32-i860.c b/bfd/elf32-i860.c
index f50e51b..bba2479 100644
--- a/bfd/elf32-i860.c
+++ b/bfd/elf32-i860.c
@@ -1121,12 +1121,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-ip2k.c b/bfd/elf32-ip2k.c
index d696a27..eea8e77 100644
--- a/bfd/elf32-ip2k.c
+++ b/bfd/elf32-ip2k.c
@@ -1425,13 +1425,13 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
bfd_boolean unresolved_reloc;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf32-iq2000.c b/bfd/elf32-iq2000.c
index 079a962..80ab459 100644
--- a/bfd/elf32-iq2000.c
+++ b/bfd/elf32-iq2000.c
@@ -623,12 +623,12 @@
else
{
bfd_boolean unresolved_reloc;
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf32-lm32.c b/bfd/elf32-lm32.c
index b2211a3..a9a17db 100644
--- a/bfd/elf32-lm32.c
+++ b/bfd/elf32-lm32.c
@@ -884,12 +884,12 @@
{
/* It's a global symbol. */
bfd_boolean unresolved_reloc;
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf32-m68hc1x.c b/bfd/elf32-m68hc1x.c
index 65d17d9..35a4bbe 100644
--- a/bfd/elf32-m68hc1x.c
+++ b/bfd/elf32-m68hc1x.c
@@ -975,12 +975,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation, unresolved_reloc,
- warned);
+ warned, ignored);
is_far = (h && (h->other & STO_M68HC12_FAR));
}
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c
index 573003b..79e1659 100644
--- a/bfd/elf32-m68k.c
+++ b/bfd/elf32-m68k.c
@@ -3714,12 +3714,12 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-mcore.c b/bfd/elf32-mcore.c
index 7279697..5e8b57f 100644
--- a/bfd/elf32-mcore.c
+++ b/bfd/elf32-mcore.c
@@ -458,12 +458,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-mep.c b/bfd/elf32-mep.c
index f356fd0..2204488 100644
--- a/bfd/elf32-mep.c
+++ b/bfd/elf32-mep.c
@@ -490,12 +490,12 @@
}
else
{
- bfd_boolean warned, unresolved_reloc;
+ bfd_boolean warned, unresolved_reloc, ignored;
RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
index abe2861..1bb80b6 100644
--- a/bfd/elf32-microblaze.c
+++ b/bfd/elf32-microblaze.c
@@ -815,11 +815,12 @@
{
/* External symbol. */
bfd_boolean warned ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
sym_name = h->root.root.string;
}
diff --git a/bfd/elf32-moxie.c b/bfd/elf32-moxie.c
index c1a793e..05212d4 100644
--- a/bfd/elf32-moxie.c
+++ b/bfd/elf32-moxie.c
@@ -240,12 +240,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf32-msp430.c b/bfd/elf32-msp430.c
index c0459f4..14fd283 100644
--- a/bfd/elf32-msp430.c
+++ b/bfd/elf32-msp430.c
@@ -446,12 +446,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-mt.c b/bfd/elf32-mt.c
index c03d8f4..9155c73 100644
--- a/bfd/elf32-mt.c
+++ b/bfd/elf32-mt.c
@@ -344,12 +344,12 @@
else
{
bfd_boolean unresolved_reloc;
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf32-openrisc.c b/bfd/elf32-openrisc.c
index 2b002ab..faf9b93 100644
--- a/bfd/elf32-openrisc.c
+++ b/bfd/elf32-openrisc.c
@@ -365,12 +365,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 98f1aa8..cd52a34 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -7355,10 +7355,12 @@
}
else
{
+ bfd_boolean ignored;
+
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
sym_name = h->root.root.string;
}
diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c
index c454e5f..a4313dc 100644
--- a/bfd/elf32-rl78.c
+++ b/bfd/elf32-rl78.c
@@ -461,12 +461,13 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes, h,
sec, relocation, unresolved_reloc,
- warned);
+ warned, ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c
index d3b71c3..23729f8 100644
--- a/bfd/elf32-rx.c
+++ b/bfd/elf32-rx.c
@@ -511,12 +511,12 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes, h,
sec, relocation, unresolved_reloc,
- warned);
+ warned, ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index 8b90c8c..fc625240 100644
--- a/bfd/elf32-s390.c
+++ b/bfd/elf32-s390.c
@@ -2293,11 +2293,12 @@
else
{
bfd_boolean warned ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-tic6x.c b/bfd/elf32-tic6x.c
index 1aec028..ee55fcd 100644
--- a/bfd/elf32-tic6x.c
+++ b/bfd/elf32-tic6x.c
@@ -2319,12 +2319,12 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-tilepro.c b/bfd/elf32-tilepro.c
index 899abdd..5c1dbe3 100644
--- a/bfd/elf32-tilepro.c
+++ b/bfd/elf32-tilepro.c
@@ -2856,12 +2856,13 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
if (warned)
{
/* To avoid generating warning messages about truncated
diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c
index 11fbbb4..46e1d3a 100644
--- a/bfd/elf32-v850.c
+++ b/bfd/elf32-v850.c
@@ -2074,7 +2074,7 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
/* Note - this check is delayed until now as it is possible and
valid to have a file without any symbols but with relocs that
@@ -2091,7 +2091,7 @@
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-vax.c b/bfd/elf32-vax.c
index 5b86329..014af9e 100644
--- a/bfd/elf32-vax.c
+++ b/bfd/elf32-vax.c
@@ -1403,12 +1403,12 @@
else
{
bfd_boolean unresolved_reloc;
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
diff --git a/bfd/elf32-xc16x.c b/bfd/elf32-xc16x.c
index b7e0d41..7bb361e 100644
--- a/bfd/elf32-xc16x.c
+++ b/bfd/elf32-xc16x.c
@@ -373,12 +373,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-xstormy16.c b/bfd/elf32-xstormy16.c
index d6a48bf..0d59e8b 100644
--- a/bfd/elf32-xstormy16.c
+++ b/bfd/elf32-xstormy16.c
@@ -817,12 +817,12 @@
}
else
{
- bfd_boolean unresolved_reloc, warned;
+ bfd_boolean unresolved_reloc, warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index c6c9c12..b2641a4 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -2643,10 +2643,12 @@
}
else
{
+ bfd_boolean ignored;
+
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
if (relocation == 0
&& !unresolved_reloc
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index c8d76a0..c6c70a1 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -4295,14 +4295,14 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
struct elf_link_hash_entry *hh;
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
hh, sec, value,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
if (warned)
continue;
diff --git a/bfd/elf64-ia64-vms.c b/bfd/elf64-ia64-vms.c
index 152ce32..fb06078 100644
--- a/bfd/elf64-ia64-vms.c
+++ b/bfd/elf64-ia64-vms.c
@@ -3489,13 +3489,13 @@
else
{
bfd_boolean unresolved_reloc;
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sym_sec, value,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
if (h->root.type == bfd_link_hash_undefweak)
undef_weak_ref = TRUE;
diff --git a/bfd/elf64-mmix.c b/bfd/elf64-mmix.c
index 1eb725d..f49f66c 100644
--- a/bfd/elf64-mmix.c
+++ b/bfd/elf64-mmix.c
@@ -1467,12 +1467,13 @@
}
else
{
- bfd_boolean unresolved_reloc;
+ bfd_boolean unresolved_reloc, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, undefined_signalled);
+ unresolved_reloc, undefined_signalled,
+ ignored);
name = h->root.root.string;
}
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 5278589..e10e109 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -12318,10 +12318,12 @@
}
else
{
+ bfd_boolean ignored;
+
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h_elf, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
sym_name = h_elf->root.root.string;
sym_type = h_elf->type;
}
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index cc0e473..e475e38 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -2237,11 +2237,12 @@
else
{
bfd_boolean warned ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 5614aa2..d9cec67 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -763,6 +763,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. */
@@ -906,6 +909,8 @@
ret->tls_module_base = NULL;
ret->next_jump_slot_index = 0;
ret->next_irelative_index = 0;
+ ret->sdynsharablebss = NULL;
+ ret->srelsharablebss = NULL;
if (ABI_64_P (abfd))
{
@@ -972,10 +977,19 @@
htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
if (!info->shared)
- htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
+ {
+ htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
+ htab->sdynsharablebss
+ = bfd_get_section_by_name (dynobj, ".dynsharablebss");
+ htab->srelsharablebss
+ = bfd_get_section_by_name (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
@@ -2248,6 +2262,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. */
@@ -2255,12 +2271,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);
}
@@ -2813,6 +2833,7 @@
|| s == htab->elf.iplt
|| s == htab->elf.igotplt
|| s == htab->plt_eh_frame
+ || s == htab->sdynsharablebss
|| s == htab->sdynbss)
{
/* Strip this section if we don't need it; see the
@@ -3146,11 +3167,12 @@
else
{
bfd_boolean warned ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
}
if (sec != NULL && discarded_section (sec))
@@ -4492,13 +4514,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
@@ -4506,7 +4534,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;
@@ -4839,7 +4867,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);
}
@@ -4855,7 +4884,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. */
@@ -4873,22 +4903,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;
}
@@ -4897,7 +4931,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;
}
@@ -4934,7 +4968,8 @@
&& h->root.type == bfd_link_hash_common
&& !*newdef
&& bfd_is_com_section (*sec)
- && *oldsec != *sec)
+ && *oldsec != *sec
+ && _bfd_elf_sharable_common_section_index (*oldsec) == SHN_COMMON)
{
if (sym->st_shndx == SHN_COMMON
&& (elf_section_flags (*oldsec) & SHF_X86_64_LARGE) != 0)
@@ -4942,13 +4977,26 @@
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 = *sec = bfd_com_section_ptr;
+ {
+ *psec = *sec = bfd_com_section_ptr;
+ return TRUE;
+ }
}
- return TRUE;
+ return _bfd_elf_sharable_merge_symbol (info, sym_hash, h, sym,
+ psec, pvalue, pold_alignment,
+ skip, override,
+ type_change_ok, size_change_ok,
+ newdyn, newdef,
+ newdyncommon, newweak,
+ abfd, sec,
+ olddyn, olddef,
+ olddyncommon, oldweak,
+ oldbfd, oldsec);
}
static int
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index 2c8fe2b..ea601d9 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -633,8 +633,14 @@
if (i_ehdrp->e_shnum == SHN_UNDEF)
{
i_ehdrp->e_shnum = i_shdr.sh_size;
- if (i_ehdrp->e_shnum != i_shdr.sh_size
- || i_ehdrp->e_shnum == 0)
+ if (i_ehdrp->e_shnum >= SHN_LORESERVE)
+ {
+ _bfd_error_handler (_("%B: too many sections: %u"),
+ abfd, i_ehdrp->e_shnum);
+ abort ();
+ }
+ else if (i_ehdrp->e_shnum != i_shdr.sh_size
+ || i_ehdrp->e_shnum == 0)
goto got_wrong_format_error;
}
@@ -1178,6 +1184,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)
@@ -1222,6 +1231,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));
@@ -1280,6 +1292,18 @@
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 local symbol `%s'"),
+ abfd->filename, sym->symbol.name);
+
+ /* Force it to local symbol. */
+ isym->st_info = ELF_ST_INFO (STB_LOCAL,
+ ELF_ST_TYPE (isym->st_info));
+ }
+
switch (ELF_ST_BIND (isym->st_info))
{
case STB_LOCAL:
diff --git a/bfd/elflink.c b/bfd/elflink.c
index e715942..1e2c9bd 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -383,6 +383,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;
+ }
}
}
@@ -893,6 +914,33 @@
}
}
+/* Mark if a symbol has a definition in a dynamic object or is
+ weak in all dynamic objects. */
+
+static void
+_bfd_elf_mark_dynamic_def_weak (struct elf_link_hash_entry *h,
+ asection *sec, int bind)
+{
+ if (!h->dynamic_def)
+ {
+ if (!bfd_is_und_section (sec))
+ h->dynamic_def = 1;
+ else
+ {
+ /* Check if this symbol is weak in all dynamic objects. If it
+ is the first time we see it in a dynamic object, we mark
+ if it is weak. Otherwise, we clear it. */
+ if (!h->ref_dynamic)
+ {
+ if (bind == STB_WEAK)
+ h->dynamic_weak = 1;
+ }
+ else if (bind != STB_WEAK)
+ h->dynamic_weak = 0;
+ }
+ }
+}
+
/* This function is called when we want to define a new symbol. It
handles the various cases which arise when we find a definition in
a dynamic object, or when there is already a definition in a
@@ -921,6 +969,7 @@
{
asection *sec, *oldsec;
struct elf_link_hash_entry *h;
+ struct elf_link_hash_entry *hi;
struct elf_link_hash_entry *flip;
int bind;
bfd *oldbfd;
@@ -959,8 +1008,9 @@
if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
return TRUE;
- /* For merging, we only care about real symbols. */
-
+ /* For merging, we only care about real symbols. But we need to make
+ sure that indirect symbol dynamic flags are updated. */
+ hi = h;
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
@@ -1136,23 +1186,11 @@
/* We need to remember if a symbol has a definition in a dynamic
object or is weak in all dynamic objects. Internal and hidden
visibility will make it unavailable to dynamic objects. */
- if (newdyn && !h->dynamic_def)
+ if (newdyn)
{
- if (!bfd_is_und_section (sec))
- h->dynamic_def = 1;
- else
- {
- /* Check if this symbol is weak in all dynamic objects. If it
- is the first time we see it in a dynamic object, we mark
- if it is weak. Otherwise, we clear it. */
- if (!h->ref_dynamic)
- {
- if (bind == STB_WEAK)
- h->dynamic_weak = 1;
- }
- else if (bind != STB_WEAK)
- h->dynamic_weak = 0;
- }
+ _bfd_elf_mark_dynamic_def_weak (h, sec, bind);
+ if (h != hi)
+ _bfd_elf_mark_dynamic_def_weak (hi, sec, bind);
}
/* If the old symbol has non-default visibility, we ignore the new
@@ -1164,6 +1202,7 @@
*skip = TRUE;
/* Make sure this symbol is dynamic. */
h->ref_dynamic = 1;
+ hi->ref_dynamic = 1;
/* A protected symbol has external availability. Make sure it is
recorded as dynamic.
@@ -1724,6 +1763,7 @@
if (! dynamic)
{
if (! info->executable
+ || hi->def_dynamic
|| hi->ref_dynamic)
*dynsym = TRUE;
}
@@ -3839,6 +3879,7 @@
flagword flags;
const char *name;
struct elf_link_hash_entry *h;
+ struct elf_link_hash_entry *hi;
bfd_boolean definition;
bfd_boolean size_change_ok;
bfd_boolean type_change_ok;
@@ -4171,6 +4212,9 @@
goto error_free_vers;
h = *sym_hash;
+ /* We need to make sure that indirect symbol dynamic flags are
+ updated. */
+ hi = h;
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
@@ -4359,25 +4403,38 @@
h->ref_dynamic = 1;
}
}
- if (! info->executable
- || h->def_dynamic
- || h->ref_dynamic)
+
+ /* If the indirect symbol has been forced local, don't
+ make the real symbol dynamic. */
+ if ((h == hi || !hi->forced_local)
+ && (! info->executable
+ || h->def_dynamic
+ || h->ref_dynamic))
dynsym = TRUE;
}
else
{
if (! definition)
- h->ref_dynamic = 1;
+ {
+ h->ref_dynamic = 1;
+ hi->ref_dynamic = 1;
+ }
else
{
h->def_dynamic = 1;
h->dynamic_def = 1;
+ hi->def_dynamic = 1;
+ hi->dynamic_def = 1;
}
- if (h->def_regular
- || h->ref_regular
- || (h->u.weakdef != NULL
- && ! new_weakdef
- && h->u.weakdef->dynindx != -1))
+
+ /* If the indirect symbol has been forced local, don't
+ make the real symbol dynamic. */
+ if ((h == hi || !hi->forced_local)
+ && (h->def_regular
+ || h->ref_regular
+ || (h->u.weakdef != NULL
+ && ! new_weakdef
+ && h->u.weakdef->dynindx != -1)))
dynsym = TRUE;
}
@@ -4692,6 +4749,7 @@
asection *slook;
bfd_vma vlook;
long ilook;
+ int tlook;
size_t i, j, idx;
hlook = weaks;
@@ -4704,6 +4762,7 @@
|| hlook->root.type == bfd_link_hash_indirect);
slook = hlook->root.u.def.section;
vlook = hlook->root.u.def.value;
+ tlook = hlook->type;
ilook = -1;
i = 0;
@@ -4741,9 +4800,10 @@
{
h = sorted_sym_hash [i];
- /* Stop if value or section doesn't match. */
+ /* Stop if value, section or type doesn't match. */
if (h->root.u.def.value != vlook
- || h->root.u.def.section != slook)
+ || h->root.u.def.section != slook
+ || h->type != tlook)
break;
else if (h != hlook)
{
@@ -5085,6 +5145,9 @@
something wrong with the archive. */
if (element->archive_pass != 0)
{
+ /* Don't load the IR archive member twice. */
+ if (element->lto_type == lto_ir_object)
+ continue;
bfd_set_error (bfd_error_bad_value);
goto error_return;
}
@@ -8438,6 +8501,10 @@
if (!is_elf_hash_table (info->hash))
return FALSE;
+ /* Check indirect symbol. */
+ while (h->root.type == bfd_link_hash_indirect)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
switch (h->root.type)
{
default:
@@ -8662,6 +8729,11 @@
{
bfd *def_bfd;
const char *msg;
+ struct elf_link_hash_entry *hi = h;
+
+ /* Check indirect symbol. */
+ while (hi->root.type == bfd_link_hash_indirect)
+ hi = (struct elf_link_hash_entry *) hi->root.u.i.link;
if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
msg = _("%B: internal symbol `%s' in %B is referenced by DSO");
@@ -8670,8 +8742,8 @@
else
msg = _("%B: local symbol `%s' in %B is referenced by DSO");
def_bfd = flinfo->output_bfd;
- if (h->root.u.def.section != bfd_abs_section_ptr)
- def_bfd = h->root.u.def.section->owner;
+ if (hi->root.u.def.section != bfd_abs_section_ptr)
+ def_bfd = hi->root.u.def.section->owner;
(*_bfd_error_handler) (msg, flinfo->output_bfd, def_bfd,
h->root.root.string);
bfd_set_error (bfd_error_bad_value);
@@ -8908,6 +8980,23 @@
{
bfd_byte *esym;
+ /* Since there is no version information in the dynamic string,
+ if there is no version info in symbol version section, we will
+ have a run-time problem. */
+ if (h->verinfo.verdef == NULL)
+ {
+ char *p = strrchr (h->root.root.string, ELF_VER_CHR);
+
+ if (p && p [1] != '\0')
+ {
+ (*_bfd_error_handler)
+ (_("%B: No symbol version section for versioned symbol `%s'"),
+ flinfo->output_bfd, h->root.root.string);
+ eoinfo->failed = TRUE;
+ return FALSE;
+ }
+ }
+
sym.st_name = h->dynstr_index;
esym = flinfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym;
if (!check_dynsym (flinfo->output_bfd, &sym))
@@ -12863,3 +12952,219 @@
BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
bed->s->swap_reloca_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 bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry **sym_hash ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym ATTRIBUTE_UNUSED,
+ asection **psec,
+ bfd_vma *pvalue ATTRIBUTE_UNUSED,
+ unsigned int *pold_alignment ATTRIBUTE_UNUSED,
+ bfd_boolean *skip ATTRIBUTE_UNUSED,
+ bfd_boolean *override ATTRIBUTE_UNUSED,
+ bfd_boolean *type_change_ok ATTRIBUTE_UNUSED,
+ bfd_boolean *size_change_ok ATTRIBUTE_UNUSED,
+ bfd_boolean *newdef ATTRIBUTE_UNUSED,
+ bfd_boolean *newdyn,
+ bfd_boolean *newdyncommon ATTRIBUTE_UNUSED,
+ bfd_boolean *newweak ATTRIBUTE_UNUSED,
+ bfd *abfd,
+ asection **sec,
+ bfd_boolean *olddef ATTRIBUTE_UNUSED,
+ bfd_boolean *olddyn,
+ bfd_boolean *olddyncommon ATTRIBUTE_UNUSED,
+ bfd_boolean *oldweak ATTRIBUTE_UNUSED,
+ bfd *oldbfd,
+ asection **oldsec)
+{
+ /* 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 = *sec = 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/elfnn-ia64.c b/bfd/elfnn-ia64.c
index fdefb03..dcef107 100644
--- a/bfd/elfnn-ia64.c
+++ b/bfd/elfnn-ia64.c
@@ -1056,7 +1056,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. */
@@ -3897,17 +3898,17 @@
else
{
bfd_boolean unresolved_reloc;
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sym_sec, value,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
if (h->root.type == bfd_link_hash_undefweak)
undef_weak_ref = TRUE;
- else if (warned)
+ else if (warned || (ignored && info->executable))
continue;
}
@@ -5062,6 +5063,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/elfxx-sparc.c b/bfd/elfxx-sparc.c
index 06f02bf..a3f4331 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -2993,12 +2993,12 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
if (warned)
{
/* To avoid generating warning messages about truncated
diff --git a/bfd/elfxx-tilegx.c b/bfd/elfxx-tilegx.c
index 02f80c5..0d8de06 100644
--- a/bfd/elfxx-tilegx.c
+++ b/bfd/elfxx-tilegx.c
@@ -3122,12 +3122,13 @@
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
if (warned)
{
/* To avoid generating warning messages about truncated
diff --git a/bfd/format.c b/bfd/format.c
index 66b9051..181ac05 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -95,6 +95,33 @@
return bfd_check_format_matches (abfd, format, NULL);
}
+/* Set lto_type in ABFD. */
+
+static void
+bfd_set_lto_type (bfd *abfd)
+{
+ if (abfd->format == bfd_object
+ && abfd->lto_type == lto_non_object
+ && (abfd->flags & (DYNAMIC | EXEC_P)) == 0)
+ {
+ asection *sec;
+ enum bfd_lto_object_type type = lto_non_ir_object;
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ {
+ if (strcmp (sec->name, GNU_OBJECT_ONLY_SECTION_NAME) == 0)
+ {
+ type = lto_mixed_object;
+ abfd->object_only_section = sec;
+ break;
+ }
+ else if (type != lto_ir_object
+ && strncmp (sec->name, ".gnu.lto_", 9) == 0)
+ type = lto_ir_object;
+ }
+ abfd->lto_type = type;
+ }
+}
+
/*
FUNCTION
bfd_check_format_matches
@@ -136,7 +163,10 @@
}
if (abfd->format != bfd_unknown)
- return abfd->format == format;
+ {
+ bfd_set_lto_type (abfd);
+ return abfd->format == format;
+ }
/* Since the target type was defaulted, check them
all in the hope that one will be uniquely recognized. */
@@ -322,6 +352,9 @@
if (matching_vector)
free (matching_vector);
+
+ bfd_set_lto_type (abfd);
+
return TRUE; /* File position has moved, BTW. */
}
diff --git a/bfd/opncls.c b/bfd/opncls.c
index 7c1d2f9..75d498b 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -1543,3 +1543,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 8d2c4b2..1e6d82b 100644
--- a/bfd/plugin.c
+++ b/bfd/plugin.c
@@ -130,6 +130,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,
@@ -142,10 +275,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;
}
@@ -389,7 +525,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);
@@ -423,12 +560,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++)
{
@@ -441,10 +573,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:
@@ -452,15 +585,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 3091f97..2db087f 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 0a7908e..b48da6c 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -552,6 +552,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 (&std_section[0])
.{* Pointer to the undefined section. *}
diff --git a/binutils/ChangeLog.addend b/binutils/ChangeLog.addend
new file mode 100644
index 0000000..e0bd096
--- /dev/null
+++ b/binutils/ChangeLog.addend
@@ -0,0 +1,4 @@
+2007-06-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ * objdump.c (disassemble_bytes): Print addend as signed.
+ (dump_reloc_set): Likewise.
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 40250ad..d0d112f 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -918,30 +918,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
@@ -1009,7 +985,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
@@ -2608,7 +2584,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/readelf.c b/binutils/readelf.c
index 527edf2..1873f7a 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -1335,6 +1335,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
@@ -2803,6 +2805,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";
@@ -3052,6 +3055,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))
@@ -8910,6 +8914,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
@@ -9256,7 +9262,7 @@
i < elf_header.e_shnum;
i++, section++)
{
- unsigned int si;
+ unsigned int si, start_global;
char * strtab = NULL;
unsigned long int strtab_size = 0;
Elf_Internal_Sym * symtab;
@@ -9289,6 +9295,7 @@
if (symtab == NULL)
continue;
+ start_global = section->sh_info;
if (section->sh_link == elf_header.e_shstrndx)
{
strtab = string_table;
@@ -9313,7 +9320,11 @@
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 (si < start_global
+ && 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
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index ffee6f6..146ec91 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -73,6 +73,7 @@
static void obj_elf_subsection (int);
static void obj_elf_popsection (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);
@@ -130,6 +131,8 @@
{"tls_common", obj_elf_tls_common, 0},
+ {"sharable_common", obj_elf_sharable_common, 0},
+
/* End sentinel. */
{NULL, NULL, 0},
};
@@ -385,6 +388,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);
@@ -604,11 +640,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)
diff --git a/gas/testsuite/ChangeLog.addend b/gas/testsuite/ChangeLog.addend
new file mode 100644
index 0000000..7b10497
--- /dev/null
+++ b/gas/testsuite/ChangeLog.addend
@@ -0,0 +1,26 @@
+2011-01-01 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gas/i386/ilp32/mixed-mode-reloc64.d: Expect addend as signed.
+ * gas/i386/ilp32/reloc64.d: Likewise.
+
+2010-10-01 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gas/all/fwdexp.d: Expect addend as signed.
+
+2007-06-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gas/alpha/elf-reloc-1.d: Expect addend as signed.
+ * gas/i386/mixed-mode-reloc64.d: Likewise.
+ * gas/i386/reloc64.d: Likewise.
+ * gas/ia64/pcrel.d: Likewise.
+ * gas/mips/branch-misc-2-64.d: Likewise.
+ * gas/mips/branch-misc-2pic-64.d: Likewise.
+ * gas/mips/ldstla-n64-sym32.d: Likewise.
+ * gas/mips/mips16-hilo-n32.d: Likewise.
+ * gas/ppc/astest.d: Likewise.
+ * gas/ppc/astest2.d: Likewise.
+ * gas/ppc/astest2_64.d: Likewise.
+ * gas/ppc/astest64.d: Likewise.
+ * gas/ppc/test1elf32.d: Likewise.
+ * gas/ppc/test1elf64.d: Likewise.
+ * gas/sparc/reloc64.d: Likewise.
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/include/bfdlink.h b/include/bfdlink.h
index d900b47..9fdf48e 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -380,6 +380,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;
@@ -387,6 +393,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 5cddc0b..a0972c6 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 */
@@ -670,6 +674,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 fb94003..9edb0f7 100644
--- a/ld/emulparams/elf32_x86_64.sh
+++ b/ld/emulparams/elf32_x86_64.sh
@@ -15,6 +15,7 @@
LARGE_SECTIONS=yes
SEPARATE_GOTPLT=24
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 2b2f910..e1920ee 100644
--- a/ld/emulparams/elf_i386.sh
+++ b/ld/emulparams/elf_i386.sh
@@ -13,3 +13,4 @@
NO_SMALL_DATA=yes
SEPARATE_GOTPLT=12
IREL_IN_PLT=
+SHARABLE_SECTIONS=yes
diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
index c38e845..94ed6e8 100644
--- a/ld/emulparams/elf_x86_64.sh
+++ b/ld/emulparams/elf_x86_64.sh
@@ -15,6 +15,7 @@
LARGE_SECTIONS=yes
SEPARATE_GOTPLT=24
IREL_IN_PLT=
+SHARABLE_SECTIONS=yes
if [ "x${host}" = "x${target}" ]; then
case " $EMULATION_LIBPATH " in
diff --git a/ld/emultempl/alphaelf.em b/ld/emultempl/alphaelf.em
index 21064ad..ec0965a 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 3b881dd..a37a35d 100644
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -365,7 +365,7 @@
}
static void
-gld${EMULATION_NAME}_finish (void)
+arm_finish (void)
{
struct bfd_link_hash_entry * h;
@@ -388,7 +388,7 @@
}
}
- finish_default ();
+ gld${EMULATION_NAME}_finish ();
if (thumb_entry_symbol)
{
@@ -689,4 +689,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 2b7a352..9e4c5a6 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -68,6 +68,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
@@ -104,6 +105,7 @@
ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
+ link_info.sharable_sections = `if test "$SHARABLE_SECTIONS" = "yes" ; then echo TRUE ; else echo FALSE ; fi`;
}
EOF
@@ -1759,6 +1761,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. */
@@ -1767,7 +1771,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,
@@ -1794,6 +1798,7 @@
SEC_HAS_CONTENTS,
0, 0, 0, 0 },
};
+ static struct orphan_save hold[ARRAY_SIZE (orig_hold)];
enum orphan_save_index
{
orphan_text = 0,
@@ -1805,7 +1810,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;
@@ -1814,6 +1818,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))
@@ -1882,15 +1892,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;
}
@@ -1960,6 +1977,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
@@ -2492,7 +2530,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 d578f7f..bad3e2c 100644
--- a/ld/emultempl/ppc64elf.em
+++ b/ld/emultempl/ppc64elf.em
@@ -533,7 +533,7 @@
/* Final emulation specific call. */
static void
-gld${EMULATION_NAME}_finish (void)
+ppc_finish (void)
{
/* e_entry on PowerPC64 points to the function descriptor for
_start. If _start is missing, default to the first function
@@ -565,7 +565,7 @@
}
ppc64_elf_restore_symbols (&link_info);
- finish_default ();
+ gld${EMULATION_NAME}_finish ();
}
@@ -867,6 +867,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 2bcfcc2..35c4d41 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/ldfile.c b/ld/ldfile.c
index 41ace36..9e59927 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -319,7 +319,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 4e75624..9674f2e 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -38,6 +38,7 @@
#include "ldctor.h"
#include "ldfile.h"
#include "ldemul.h"
+#include "ldwrite.h"
#include "fnmatch.h"
#include "demangle.h"
#include "hashtab.h"
@@ -46,6 +47,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[10];
static lang_statement_list_type **stat_save_ptr = &stat_save[0];
static struct unique_sections *unique_section_list;
+static cmdline_list_type cmdline_object_only_file_list;
+static cmdline_list_type cmdline_object_only_archive_list;
+static cmdline_list_type cmdline_temp_object_only_list;
/* Forward declarations. */
static void exp_init_os (etree_type *);
@@ -89,6 +96,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;
@@ -1204,14 +1215,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);
@@ -1230,10 +1244,11 @@
simpler to re-use working machinery than using a linked list in terms
of code-complexity here in ld, besides the initialization which just
looks like other code here. */
- if (!bfd_hash_table_init_n (&lang_definedness_table,
- lang_definedness_newfunc,
- sizeof (struct lang_definedness_hash_entry),
- 3))
+ if (!object_only
+ && !bfd_hash_table_init_n (&lang_definedness_table,
+ lang_definedness_newfunc,
+ sizeof (struct lang_definedness_hash_entry),
+ 3))
einfo (_("%P%F: can not create hash table: %E\n"));
}
@@ -2768,6 +2783,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,
@@ -6583,7 +6604,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 (trace_file_tries
+ && (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)
@@ -8046,3 +8098,961 @@
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;
+ const char *ofilename = NULL;
+ asection *sec;
+
+ ibfd = bfd_openr (output_filename, output_target);
+ if (!ibfd)
+ {
+ err = bfd_errmsg (bfd_get_error ());
+ goto loser;
+ }
+
+ if (!bfd_check_format_matches (ibfd, bfd_object, &matching))
+ {
+ err = bfd_errmsg (bfd_get_error ());
+ goto loser;
+ }
+
+ obfd = cmdline_fopen_temp (output_filename, output_target, "w");
+ if (!obfd)
+ {
+ err = bfd_errmsg (bfd_get_error ());
+ goto loser;
+ }
+ ofilename = bfd_get_filename (obfd);
+
+ if (!bfd_set_format (obfd, bfd_object))
+ {
+ err = bfd_errmsg (bfd_get_error ());
+ goto loser;
+ }
+
+ /* Copy the start address, flags and architecture of input file to
+ output file. */
+ flags = bfd_get_file_flags (ibfd);
+ start = bfd_get_start_address (ibfd);
+ iarch = bfd_get_arch (ibfd);
+ imach = bfd_get_mach (ibfd);
+ if (!bfd_set_start_address (obfd, start)
+ || !bfd_set_file_flags (obfd, flags)
+ || !bfd_set_arch_mach (obfd, iarch, imach))
+ {
+ err = bfd_errmsg (bfd_get_error ());
+ goto loser;
+ }
+
+ symsize = bfd_get_symtab_upper_bound (ibfd);
+ if (symsize < 0)
+ {
+ err = bfd_errmsg (bfd_get_error ());
+ goto loser;
+ }
+
+ isympp = (asymbol **) xmalloc (symsize);
+ symcount = bfd_canonicalize_symtab (ibfd, isympp);
+ if (symcount < 0)
+ {
+ err = bfd_errmsg (bfd_get_error ());
+ goto loser;
+ }
+
+ arg.obfd = obfd;
+ arg.isympp = isympp;
+ arg.status = 0;
+
+ /* BFD mandates that all output sections be created and sizes set before
+ any output is done. Thus, we traverse all sections multiple times. */
+ bfd_map_over_sections (ibfd, setup_section, &arg);
+
+ if (arg.status)
+ {
+ err = _("error setting up sections");
+ goto loser;
+ }
+
+ /* Allow the BFD backend to copy any private data it understands
+ from the input section to the output section. */
+ if (! bfd_copy_private_header_data (ibfd, obfd))
+ {
+ err = _("error copying private header data");
+ goto loser;
+ }
+
+ /* Create the object-only section. */
+ sec = bfd_make_section_with_flags (obfd,
+ GNU_OBJECT_ONLY_SECTION_NAME,
+ (SEC_HAS_CONTENTS
+ | SEC_READONLY
+ | SEC_DATA
+ | SEC_LINKER_CREATED));
+ if (sec == NULL)
+ {
+ err = _("can't create object-only section");
+ goto loser;
+ }
+
+ if (! bfd_set_section_size (obfd, sec, size))
+ {
+ err = _("can't set object-only section size");
+ goto loser;
+ }
+
+ if (ibfd->object_only_section)
+ {
+ /* Filter out the object-only section symbol. */
+ long src_count = 0, dst_count = 0;
+ asymbol **from, **to;
+
+ osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
+ from = isympp;
+ to = osympp;
+ for (; src_count < symcount; src_count++)
+ {
+ asymbol *sym = from[src_count];
+ if (bfd_get_section (sym) != ibfd->object_only_section)
+ to[dst_count++] = sym;
+ }
+ to[dst_count] = NULL;
+ symcount = dst_count;
+ bfd_set_symtab (obfd, osympp, symcount);
+ }
+ else
+ bfd_set_symtab (obfd, isympp, symcount);
+
+ /* This has to happen after the symbol table has been set. */
+ bfd_map_over_sections (ibfd, copy_section, &arg);
+
+ if (arg.status)
+ {
+ err = _("error copying sections");
+ goto loser;
+ }
+
+ /* Copy the object-only section to the output. */
+ if (! bfd_set_section_contents (obfd, sec, contents, 0, size))
+ {
+ err = _("error adding object-only section");
+ goto loser;
+ }
+
+ /* Allow the BFD backend to copy any private data it understands
+ from the input BFD to the output BFD. This is done last to
+ permit the routine to look at the filtered symbol table, which is
+ important for the ECOFF code at least. */
+ if (! bfd_copy_private_bfd_data (ibfd, obfd))
+ {
+ err = _("error copying private BFD data");
+ goto loser;
+ }
+
+ if (!bfd_close (obfd))
+ {
+ unlink (ofilename);
+ einfo (_("%P%F: failed to finish output with object-only section\n"));
+ }
+
+ /* Must be freed after bfd_close (). */
+ free (isympp);
+ if (osympp)
+ free (osympp);
+
+ if (rename (ofilename, output_filename))
+ {
+ unlink (ofilename);
+ einfo (_("%P%F: failed to rename output with object-only section\n"));
+ }
+
+ return;
+
+loser:
+ if (isympp)
+ free (isympp);
+ if (osympp)
+ free (osympp);
+ if (obfd)
+ bfd_close (obfd);
+ if (ofilename)
+ unlink (ofilename);
+ einfo (_("%P%F: failed to add object-only section: %s\n"), err);
+}
+
+/* Emit the final output with object-only section. */
+
+void
+cmdline_emit_object_only_section (void)
+{
+ const char *saved_output_filename = output_filename;
+ int fd;
+ size_t size, off;
+ bfd_byte *contents;
+ struct stat st;
+
+ /* Get a temporary object-only file. */
+ output_filename = make_temp_file (".obj-only.o");
+
+ had_output_filename = FALSE;
+ link_info.input_bfds = NULL;
+ link_info.input_bfds_tail = &link_info.input_bfds;
+
+ lang_init (TRUE);
+
+ ld_parse_linker_script ();
+
+ /* Set up the object-only output. */
+ lang_final ();
+
+ /* Open the object-only file for output. */
+ lang_for_each_statement (ldlang_open_output);
+
+ ldemul_create_output_section_statements ();
+
+ if (!bfd_section_already_linked_table_init ())
+ einfo (_("%P%F: Failed to create hash table\n"));
+
+ /* Call cmdline_on_object_only_archive_list_p to check which member
+ should be loaded. */
+ input_flags.whole_archive = TRUE;
+
+ /* Set it to avoid adding more to cmdline lists. */
+ link_info.emitting_gnu_object_only = TRUE;
+
+ /* 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 ();
+
+ 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 7f1e743..a973fcb 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -486,7 +486,7 @@
extern int lang_statement_iteration;
extern void lang_init
- (void);
+ (bfd_boolean);
extern void lang_finish
(void);
extern lang_memory_region_type * lang_memory_region_lookup
@@ -664,4 +664,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 5e3d2fc..e14107c 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -132,6 +132,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 3bdaf4d..21020f0 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -219,6 +219,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)
@@ -288,6 +291,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);
@@ -295,7 +299,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 +315,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 (trace_file_tries)
{
@@ -445,6 +422,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. */
@@ -491,6 +470,9 @@
}
}
+ if (link_info.emit_gnu_object_only)
+ cmdline_emit_object_only_section ();
+
END_PROGRESS (program_name);
if (config.stats)
@@ -780,7 +762,9 @@
}
}
}
+ else
#endif /* ENABLE_PLUGINS */
+ cmdline_check_object_only_section (input->the_bfd, FALSE);
ldlang_add_file (input);
@@ -1153,7 +1137,7 @@
einfo ("%P: %s%s\n", _("warning: "), warning);
else if (symbol == NULL)
einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
- else
+ else if ((abfd->flags & BFD_PLUGIN) == 0)
{
struct warning_callback_info cinfo;
@@ -1460,3 +1444,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 527d3f2..3a357c2 100644
--- a/ld/ldmain.h
+++ b/ld/ldmain.h
@@ -43,4 +43,6 @@
extern void add_wrap (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 b5e3468..392eb11 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -168,6 +168,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 },
@@ -958,6 +961,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;
@@ -1079,12 +1085,7 @@
if (config.has_shared)
{
link_info.shared = TRUE;
- /* When creating a shared library, the default
- behaviour is to ignore any unresolved references. */
- if (link_info.unresolved_syms_in_objects == RM_NOT_YET_SET)
- link_info.unresolved_syms_in_objects = RM_IGNORE;
- if (link_info.unresolved_syms_in_shared_libs == RM_NOT_YET_SET)
- link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
+ link_info.pie = FALSE;
}
else
einfo (_("%P%F: -shared not supported\n"));
@@ -1439,14 +1440,6 @@
free (default_dirlist);
}
- if (link_info.unresolved_syms_in_objects == RM_NOT_YET_SET)
- /* FIXME: Should we allow emulations a chance to set this ? */
- link_info.unresolved_syms_in_objects = how_to_report_unresolved_symbols;
-
- if (link_info.unresolved_syms_in_shared_libs == RM_NOT_YET_SET)
- /* FIXME: Should we allow emulations a chance to set this ? */
- link_info.unresolved_syms_in_shared_libs = how_to_report_unresolved_symbols;
-
if (link_info.relocatable)
{
if (command_line.check_section_addresses < 0)
@@ -1455,6 +1448,40 @@
einfo (_("%P%F: -r and -shared may not be used together\n"));
}
+ if (link_info.shared)
+ {
+ char *dynamic = getenv ("LD_DYNAMIC_LIST");
+ if (dynamic)
+ {
+ bfd_boolean first = TRUE;
+
+ do
+ {
+ bfd_boolean set;
+
+ dynamic = strtok (dynamic, ":");
+ if (dynamic == NULL)
+ break;
+ set = strcasecmp (dynamic, "cpp_new") == 0;
+ if (set)
+ lang_append_dynamic_list_cpp_new ();
+ if (set && first)
+ {
+ if (command_line.dynamic_list != dynamic_list_data)
+ command_line.dynamic_list = dynamic_list;
+ if (command_line.symbolic == symbolic)
+ command_line.symbolic = symbolic_unset;
+ first = FALSE;
+ }
+ else
+ einfo (_("%P%F: unknown LD_DYNAMIC_LIST option `%s'\n"),
+ dynamic);
+ dynamic = NULL;
+ }
+ while (1);
+ }
+ }
+
/* We may have -Bsymbolic, -Bsymbolic-functions, --dynamic-list-data,
--dynamic-list-cpp-new, --dynamic-list-cpp-typeinfo and
--dynamic-list FILE. -Bsymbolic and -Bsymbolic-functions are
@@ -1503,6 +1530,27 @@
if (! link_info.shared || link_info.pie)
link_info.executable = TRUE;
+ /* When creating a shared library, the default behaviour is to
+ ignore any unresolved references. */
+
+ if (link_info.unresolved_syms_in_objects == RM_NOT_YET_SET)
+ {
+ if (link_info.shared && !link_info.pie)
+ link_info.unresolved_syms_in_objects = RM_IGNORE;
+ else
+ link_info.unresolved_syms_in_objects
+ = how_to_report_unresolved_symbols;
+ }
+
+ if (link_info.unresolved_syms_in_shared_libs == RM_NOT_YET_SET)
+ {
+ if (link_info.shared && !link_info.pie)
+ link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
+ else
+ link_info.unresolved_syms_in_shared_libs
+ = how_to_report_unresolved_symbols;
+ }
+
/* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols). I
don't see how else this can be handled, since in this case we
must preserve all externally visible symbols. */
diff --git a/ld/plugin.c b/ld/plugin.c
index 2515888..4445ab2 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. */
@@ -210,6 +213,17 @@
if (!last_plugin)
return set_plugin_error (_("<no plugin>"));
+ /* Ignore -pass-through= from GCC driver. */
+ if (*arg == '-')
+ {
+ const char *p;
+ for (p = arg + 1; p; p++)
+ if (*p != '-')
+ break;
+ if (strncmp (p, "pass-through=", 13) == 0)
+ return 0;
+ }
+
newarg = xmalloc (sizeof *newarg);
newarg->arg = arg;
newarg->next = NULL;
@@ -866,6 +880,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
@@ -919,13 +936,16 @@
{
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)
- set_plugin_error (curplug->name);
+ 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)
+ set_plugin_error (curplug->name);
+ }
dlclose (curplug->dlhandle);
}
curplug = curplug->next;
diff --git a/ld/plugin.h b/ld/plugin.h
index dc32295..e3e6ee3 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 ea01ce2..43a7018 100644
--- a/ld/scripttempl/armbpabi.sc
+++ b/ld/scripttempl/armbpabi.sc
@@ -30,7 +30,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 37a3124..c9b3e80 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -158,7 +158,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} :
{
@@ -299,6 +299,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})"
@@ -393,6 +427,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 c8d9360..9fe9477 100644
--- a/ld/scripttempl/elf32sh-symbian.sc
+++ b/ld/scripttempl/elf32sh-symbian.sc
@@ -83,7 +83,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 136156d..1bd82dc 100644
--- a/ld/scripttempl/elf64hppa.sc
+++ b/ld/scripttempl/elf64hppa.sc
@@ -127,7 +127,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 f9e5745..532348c 100644
--- a/ld/scripttempl/elfxtensa.sc
+++ b/ld/scripttempl/elfxtensa.sc
@@ -140,7 +140,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 23b6c54..d7ddae6 100644
--- a/ld/scripttempl/mep.sc
+++ b/ld/scripttempl/mep.sc
@@ -114,7 +114,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 3a27952..b44fe8b 100644
--- a/ld/scripttempl/pe.sc
+++ b/ld/scripttempl/pe.sc
@@ -148,6 +148,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 b2113fe..fcc3c83 100644
--- a/ld/scripttempl/pep.sc
+++ b/ld/scripttempl/pep.sc
@@ -154,6 +154,7 @@
*(.drectve)
${RELOCATING+ *(.note.GNU-stack)}
${RELOCATING+ *(.gnu.lto_*)}
+ ${RELOCATING+ *(.gnu_object_only)}
}
.idata ${RELOCATING+BLOCK(__section_alignment__)} :
diff --git a/ld/testsuite/ld-elf/data2.c b/ld/testsuite/ld-elf/data2.c
new file mode 100644
index 0000000..c137b7c
--- /dev/null
+++ b/ld/testsuite/ld-elf/data2.c
@@ -0,0 +1,9 @@
+int foo = 0;
+extern int foo_alias __attribute__ ((weak, alias ("foo")));
+
+void
+bar (void)
+{
+ foo = -1;
+}
+
diff --git a/ld/testsuite/ld-elf/indirect.exp b/ld/testsuite/ld-elf/indirect.exp
new file mode 100644
index 0000000..603179a
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect.exp
@@ -0,0 +1,126 @@
+# Expect script for various indirect symbol tests.
+# Copyright 2006 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 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.
+#
+
+#
+# Written by H.J. Lu (hongjiu.lu@intel.com)
+#
+
+# Exclude non-ELF targets.
+
+if ![is_elf_format] {
+ return
+}
+
+# Check if compiler works
+if { [which $CC] == 0 } {
+ return
+}
+
+proc check_link_message { cmd string testname } {
+ send_log "$cmd\n"
+ verbose "$cmd"
+ catch "exec $cmd" exec_output
+ send_log "$exec_output\n"
+ verbose "$exec_output"
+
+ foreach str $string {
+ if [string match "*$str*" $exec_output] {
+ pass "$testname: $str"
+ } else {
+ fail "$testname: $str"
+ }
+ }
+}
+
+if { ![ld_compile $CC $srcdir/$subdir/indirect1a.c tmpdir/indirect1a.o]
+ || ![ld_compile $CC $srcdir/$subdir/indirect1b.c tmpdir/indirect1b.o]
+ || ![ld_compile "$CC -fPIC" $srcdir/$subdir/indirect2.c tmpdir/indirect2.o]
+ || ![ld_compile $CC $srcdir/$subdir/indirect3a.c tmpdir/indirect3a.o]
+ || ![ld_compile $CC $srcdir/$subdir/indirect3b.c tmpdir/indirect3b.o]
+ || ![ld_compile $CC $srcdir/$subdir/indirect4a.c tmpdir/indirect4a.o]
+ || ![ld_compile $CC $srcdir/$subdir/indirect4b.c tmpdir/indirect4b.o] } {
+ unresolved "Indirect symbol tests"
+ return
+}
+
+set build_tests {
+ {"Build libindirect1c.so"
+ "-shared" "-fPIC"
+ {indirect1c.c} {} "libindirect1c.so"}
+ {"Build libindirect3c.so"
+ "-shared" "-fPIC"
+ {indirect3c.c} {} "libindirect3c.so"}
+ {"Build libindirect4c.so"
+ "-shared" "-fPIC"
+ {indirect4c.c} {} "libindirect4c.so"}
+}
+
+run_cc_link_tests $build_tests
+
+global ld
+
+set string ": final link failed: Bad value"
+set string1 ": local symbol \`foo\' in tmpdir/indirect1b.o is referenced by DSO"
+
+set testname "Indirect symbol 1a"
+set cmd "$ld -e start -o tmpdir/indirect1 tmpdir/indirect1a.o tmpdir/indirect1b.o tmpdir/libindirect1c.so"
+check_link_message "$cmd" [list $string1 $string] "$testname"
+
+set testname "Indirect symbol 1b"
+set cmd "$ld -e start -o tmpdir/indirect1 tmpdir/indirect1a.o tmpdir/libindirect1c.so tmpdir/indirect1b.o"
+check_link_message "$cmd" [list $string1 $string] "$testname"
+
+set string ": final link failed: Nonrepresentable section on output"
+set string2 ": No symbol version section for versioned symbol \`foo@FOO\'"
+set testname "Indirect symbol 2"
+set cmd "$ld -shared -o tmpdir/indirect2.so tmpdir/indirect2.o"
+check_link_message "$cmd" [list $string2 $string] "$testname"
+
+# The following tests require running the executable generated by ld.
+if ![isnative] {
+ return
+}
+
+set run_tests {
+ {"Run with libindirect3c.so 1"
+ "tmpdir/indirect3a.o tmpdir/indirect3b.o tmpdir/libindirect3c.so" ""
+ {dummy.c} "indirect3a" "indirect3.out"}
+ {"Run with libindirect3c.so 2"
+ "tmpdir/indirect3a.o tmpdir/libindirect3c.so tmpdir/indirect3b.o" ""
+ {dummy.c} "indirect3b" "indirect3.out"}
+ {"Run with libindirect3c.so 3"
+ "tmpdir/indirect3b.o tmpdir/libindirect3c.so tmpdir/indirect3a.o" ""
+ {dummy.c} "indirect3c" "indirect3.out"}
+ {"Run with libindirect3c.so 4"
+ "tmpdir/libindirect3c.so tmpdir/indirect3b.o tmpdir/indirect3a.o" ""
+ {dummy.c} "indirect3d" "indirect3.out"}
+ {"Run with libindirect4c.so 1"
+ "tmpdir/indirect4a.o tmpdir/indirect4b.o tmpdir/libindirect4c.so" ""
+ {dummy.c} "indirect4a" "indirect4.out"}
+ {"Run with libindirect4c.so 2"
+ "tmpdir/indirect4a.o tmpdir/libindirect4c.so tmpdir/indirect4b.o" ""
+ {dummy.c} "indirect4b" "indirect4.out"}
+ {"Run with libindirect4c.so 3"
+ "tmpdir/indirect4b.o tmpdir/libindirect4c.so tmpdir/indirect4a.o" ""
+ {dummy.c} "indirect4c" "indirect4.out"}
+ {"Run with libindirect4c.so 4"
+ "tmpdir/libindirect4c.so tmpdir/indirect4b.o tmpdir/indirect4a.o" ""
+ {dummy.c} "indirect4d" "indirect4.out"}
+}
+
+run_ld_link_exec_tests [] $run_tests
diff --git a/ld/testsuite/ld-elf/indirect1a.c b/ld/testsuite/ld-elf/indirect1a.c
new file mode 100644
index 0000000..6931542
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect1a.c
@@ -0,0 +1,8 @@
+extern void bar (void);
+
+int
+start (void)
+{
+ bar ();
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/indirect1b.c b/ld/testsuite/ld-elf/indirect1b.c
new file mode 100644
index 0000000..51740f9
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect1b.c
@@ -0,0 +1,6 @@
+void
+foo (void)
+{
+}
+
+asm (".symver foo,foo@FOO");
diff --git a/ld/testsuite/ld-elf/indirect1c.c b/ld/testsuite/ld-elf/indirect1c.c
new file mode 100644
index 0000000..eae278d
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect1c.c
@@ -0,0 +1,7 @@
+extern void foo (void);
+
+void
+bar (void)
+{
+ foo ();
+}
diff --git a/ld/testsuite/ld-elf/indirect2.c b/ld/testsuite/ld-elf/indirect2.c
new file mode 100644
index 0000000..6df29be
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect2.c
@@ -0,0 +1,9 @@
+extern void foo (void);
+
+asm (".symver foo,foo@@@FOO");
+
+void
+bar (void)
+{
+ foo ();
+}
diff --git a/ld/testsuite/ld-elf/indirect3.out b/ld/testsuite/ld-elf/indirect3.out
new file mode 100644
index 0000000..482e981
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect3.out
@@ -0,0 +1,2 @@
+MAIN
+DSO
diff --git a/ld/testsuite/ld-elf/indirect3a.c b/ld/testsuite/ld-elf/indirect3a.c
new file mode 100644
index 0000000..0f6ddc8
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect3a.c
@@ -0,0 +1,10 @@
+extern void bar (void);
+extern void foo (void);
+
+int
+main (void)
+{
+ foo ();
+ bar ();
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/indirect3b.c b/ld/testsuite/ld-elf/indirect3b.c
new file mode 100644
index 0000000..dbb37c3
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect3b.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+void
+foo (void)
+{
+ printf ("MAIN\n");
+}
+
+asm (".symver foo,foo@FOO");
diff --git a/ld/testsuite/ld-elf/indirect3c.c b/ld/testsuite/ld-elf/indirect3c.c
new file mode 100644
index 0000000..b52cb95
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect3c.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+extern void foo (void);
+
+void
+foo (void)
+{
+ printf ("DSO\n");
+}
+
+void
+bar (void)
+{
+ foo ();
+}
diff --git a/ld/testsuite/ld-elf/indirect4.out b/ld/testsuite/ld-elf/indirect4.out
new file mode 100644
index 0000000..3b34ee4
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect4.out
@@ -0,0 +1,2 @@
+MAIN2
+MAIN2
diff --git a/ld/testsuite/ld-elf/indirect4a.c b/ld/testsuite/ld-elf/indirect4a.c
new file mode 100644
index 0000000..0f6ddc8
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect4a.c
@@ -0,0 +1,10 @@
+extern void bar (void);
+extern void foo (void);
+
+int
+main (void)
+{
+ foo ();
+ bar ();
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/indirect4b.c b/ld/testsuite/ld-elf/indirect4b.c
new file mode 100644
index 0000000..b8db9d0
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect4b.c
@@ -0,0 +1,17 @@
+#include <stdio.h>
+
+void
+foo2 (void)
+{
+ printf ("MAIN2\n");
+}
+
+asm (".symver foo2,foo@@FOO2");
+
+void
+foo1 (void)
+{
+ printf ("MAIN1\n");
+}
+
+asm (".symver foo1,foo@FOO1");
diff --git a/ld/testsuite/ld-elf/indirect4c.c b/ld/testsuite/ld-elf/indirect4c.c
new file mode 100644
index 0000000..b52cb95
--- /dev/null
+++ b/ld/testsuite/ld-elf/indirect4c.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+extern void foo (void);
+
+void
+foo (void)
+{
+ printf ("DSO\n");
+}
+
+void
+bar (void)
+{
+ foo ();
+}
diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
index f39bf0f..aaaa85b 100644
--- a/ld/testsuite/ld-elf/shared.exp
+++ b/ld/testsuite/ld-elf/shared.exp
@@ -127,6 +127,9 @@
{"Build libdata1.so"
"-shared" "-fPIC"
{data1.c} {} "libdata1.so"}
+ {"Build libdata2.so"
+ "-shared" "-fPIC"
+ {data2.c} {} "libdata2.so"}
{"Build libcomm1.o"
"-r -nostdlib" ""
{comm1.c} {} "libcomm1.o"}
@@ -281,6 +284,9 @@
{"Run with libdata1.so"
"tmpdir/libdata1.so" ""
{dynbss1.c} "dynbss1" "pass.out"}
+ {"Run with libdata2.so"
+ "tmpdir/libdata2.so" ""
+ {weakdef1.c} "weakdef1" "pass.out"}
{"Run with libfunc1.so comm1.o"
"tmpdir/libfunc1.so tmpdir/comm1.o" ""
{dummy.c} "comm1" "pass.out"}
diff --git a/ld/testsuite/ld-elf/weakdef1.c b/ld/testsuite/ld-elf/weakdef1.c
new file mode 100644
index 0000000..82642bb
--- /dev/null
+++ b/ld/testsuite/ld-elf/weakdef1.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int foo_alias;
+extern void bar (void);
+
+int
+main (void)
+{
+ bar ();
+ if (foo_alias != -1)
+ abort ();
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-ia64/error1.d b/ld/testsuite/ld-ia64/error1.d
new file mode 100644
index 0000000..82142b6
--- /dev/null
+++ b/ld/testsuite/ld-ia64/error1.d
@@ -0,0 +1,7 @@
+#source: error1.s
+#ld: -unresolved-symbols=ignore-all
+#readelf: -s
+
+#...
+[ ]+[0-9]+:[ ]+[0]+[ ]+0[ ]+NOTYPE[ ]+GLOBAL DEFAULT[ ]+UND[ ]+foo
+#pass
diff --git a/ld/testsuite/ld-ia64/error1.s b/ld/testsuite/ld-ia64/error1.s
new file mode 100644
index 0000000..fd48eae
--- /dev/null
+++ b/ld/testsuite/ld-ia64/error1.s
@@ -0,0 +1,30 @@
+ .explicit
+ .pred.safe_across_calls p1-p5,p16-p63
+ .text
+ .align 16
+ .global _start#
+ .proc _start#
+_start:
+ .prologue 12, 32
+ .mii
+ .save ar.pfs, r33
+ alloc r33 = ar.pfs, 0, 3, 0, 0
+ .save rp, r32
+ mov r32 = b0
+ mov r34 = r1
+ .body
+ ;;
+ .bbb
+ nop 0
+ nop 0
+ br.call.sptk.many b0 = foo#
+ ;;
+ .mmi
+ nop 0
+ mov r1 = r34
+ mov b0 = r32
+ .mib
+ nop 0
+ mov ar.pfs = r33
+ br.ret.sptk.many b0
+ .endp _start#
diff --git a/ld/testsuite/ld-ia64/error2.d b/ld/testsuite/ld-ia64/error2.d
new file mode 100644
index 0000000..764ba66
--- /dev/null
+++ b/ld/testsuite/ld-ia64/error2.d
@@ -0,0 +1,7 @@
+#source: error1.s
+#ld: -pie -unresolved-symbols=ignore-all
+#readelf: -s
+
+#...
+[ ]+[0-9]+:[ ]+[0]+[ ]+0[ ]+NOTYPE[ ]+GLOBAL DEFAULT[ ]+UND[ ]+foo
+#pass
diff --git a/ld/testsuite/ld-ia64/error3.d b/ld/testsuite/ld-ia64/error3.d
new file mode 100644
index 0000000..e14d451
--- /dev/null
+++ b/ld/testsuite/ld-ia64/error3.d
@@ -0,0 +1,7 @@
+#source: error1.s
+#ld: -pie -shared
+#readelf: -s
+
+#...
+[ ]+[0-9]+:[ ]+[0]+[ ]+0[ ]+NOTYPE[ ]+GLOBAL DEFAULT[ ]+UND[ ]+foo
+#pass
diff --git a/ld/testsuite/ld-ia64/error4.d b/ld/testsuite/ld-ia64/error4.d
new file mode 100644
index 0000000..881e671
--- /dev/null
+++ b/ld/testsuite/ld-ia64/error4.d
@@ -0,0 +1,3 @@
+#source: error1.s
+#ld: -shared -pie
+#error: .*undefined reference to `foo'
diff --git a/ld/testsuite/ld-plugin/dummy.c b/ld/testsuite/ld-plugin/dummy.c
new file mode 100644
index 0000000..5c03287
--- /dev/null
+++ b/ld/testsuite/ld-plugin/dummy.c
@@ -0,0 +1 @@
+/* An empty file. */
diff --git a/ld/testsuite/ld-plugin/dummy.s b/ld/testsuite/ld-plugin/dummy.s
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ld/testsuite/ld-plugin/dummy.s
@@ -0,0 +1 @@
+
diff --git a/ld/testsuite/ld-plugin/func1p.c b/ld/testsuite/ld-plugin/func1p.c
new file mode 100644
index 0000000..917dcbb
--- /dev/null
+++ b/ld/testsuite/ld-plugin/func1p.c
@@ -0,0 +1,8 @@
+extern int retval;
+
+int
+__attribute__ ((visibility ("protected")))
+func1 (void)
+{
+ return retval;
+}
diff --git a/ld/testsuite/ld-plugin/func2i.c b/ld/testsuite/ld-plugin/func2i.c
new file mode 100644
index 0000000..00d7cdd
--- /dev/null
+++ b/ld/testsuite/ld-plugin/func2i.c
@@ -0,0 +1,8 @@
+extern int retval;
+
+int
+__attribute__ ((visibility ("internal")))
+func2 (void)
+{
+ return retval;
+}
diff --git a/ld/testsuite/ld-plugin/func3h.c b/ld/testsuite/ld-plugin/func3h.c
new file mode 100644
index 0000000..525de63
--- /dev/null
+++ b/ld/testsuite/ld-plugin/func3h.c
@@ -0,0 +1,8 @@
+extern int retval;
+
+int
+__attribute__ ((visibility ("hidden")))
+func3 (void)
+{
+ return retval;
+}
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-11.out b/ld/testsuite/ld-plugin/lto-11.out
new file mode 100644
index 0000000..899682a
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-11.out
@@ -0,0 +1,2 @@
+Hello from foo!
+Hello from bar!
diff --git a/ld/testsuite/ld-plugin/lto-11a.c b/ld/testsuite/ld-plugin/lto-11a.c
new file mode 100644
index 0000000..5193972
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-11a.c
@@ -0,0 +1,9 @@
+extern void foo(void);
+extern void bar(void);
+
+int main(void)
+{
+ foo();
+ bar();
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-11b.c b/ld/testsuite/ld-plugin/lto-11b.c
new file mode 100644
index 0000000..62d61ec
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-11b.c
@@ -0,0 +1,6 @@
+extern int printf(const char *, ...);
+
+void foo(void)
+{
+ printf("Hello from %s!\n", __FUNCTION__);
+}
diff --git a/ld/testsuite/ld-plugin/lto-11c.c b/ld/testsuite/ld-plugin/lto-11c.c
new file mode 100644
index 0000000..8cd40b9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-11c.c
@@ -0,0 +1,6 @@
+extern int printf(const char *, ...);
+
+void bar(void)
+{
+ printf("Hello from %s!\n", __FUNCTION__);
+}
diff --git a/ld/testsuite/ld-plugin/lto-12.out b/ld/testsuite/ld-plugin/lto-12.out
new file mode 100644
index 0000000..d86bac9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-12.out
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-plugin/lto-12a.c b/ld/testsuite/ld-plugin/lto-12a.c
new file mode 100644
index 0000000..30ff3d9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-12a.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int value;
+
+int
+main (int argc, char **argv)
+{
+ int n = 10 * (argc + 1);
+ char *p = malloc (n);
+ __builtin_memcpy (p, argv[0], n);
+ if (value != -1)
+ abort ();
+ printf ("OK\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-12b.c b/ld/testsuite/ld-plugin/lto-12b.c
new file mode 100644
index 0000000..c2b00e4
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-12b.c
@@ -0,0 +1 @@
+int value = -1;
diff --git a/ld/testsuite/ld-plugin/lto-12c.c b/ld/testsuite/ld-plugin/lto-12c.c
new file mode 100644
index 0000000..ecd1bd4
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-12c.c
@@ -0,0 +1,15 @@
+#include <string.h>
+
+extern int value;
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+ char *d = (char *) dest;
+ const char *s = (const char *) src;
+
+ while (n--)
+ *d++ = *s++;
+
+ value = 1;
+ return dest;
+}
diff --git a/ld/testsuite/ld-plugin/lto-13.out b/ld/testsuite/ld-plugin/lto-13.out
new file mode 100644
index 0000000..3bd1f0e
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-13.out
@@ -0,0 +1,2 @@
+foo
+bar
diff --git a/ld/testsuite/ld-plugin/lto-13a.c b/ld/testsuite/ld-plugin/lto-13a.c
new file mode 100644
index 0000000..5193972
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-13a.c
@@ -0,0 +1,9 @@
+extern void foo(void);
+extern void bar(void);
+
+int main(void)
+{
+ foo();
+ bar();
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-13b.c b/ld/testsuite/ld-plugin/lto-13b.c
new file mode 100644
index 0000000..7c87a5e
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-13b.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+bar (void)
+{
+ printf ("bar\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-13c.c b/ld/testsuite/ld-plugin/lto-13c.c
new file mode 100644
index 0000000..4859019
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-13c.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+foo (void)
+{
+ printf ("foo\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-14.out b/ld/testsuite/ld-plugin/lto-14.out
new file mode 100644
index 0000000..7ef22e9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-14.out
@@ -0,0 +1 @@
+PASS
diff --git a/ld/testsuite/ld-plugin/lto-14a.c b/ld/testsuite/ld-plugin/lto-14a.c
new file mode 100644
index 0000000..d61437b
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-14a.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+extern void foo(void);
+extern int i;
+
+int main()
+{
+ foo();
+ if (i == 0x1234)
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-14b.c b/ld/testsuite/ld-plugin/lto-14b.c
new file mode 100644
index 0000000..5d3eb75
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-14b.c
@@ -0,0 +1,7 @@
+extern int bar(void);
+extern int i;
+
+void foo(void)
+{
+ i = bar();
+}
diff --git a/ld/testsuite/ld-plugin/lto-14c.c b/ld/testsuite/ld-plugin/lto-14c.c
new file mode 100644
index 0000000..a01e0f9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-14c.c
@@ -0,0 +1,6 @@
+int i;
+
+int bar(void)
+{
+ return 0x1234;
+}
diff --git a/ld/testsuite/ld-plugin/lto-15.out b/ld/testsuite/ld-plugin/lto-15.out
new file mode 100644
index 0000000..7ef22e9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-15.out
@@ -0,0 +1 @@
+PASS
diff --git a/ld/testsuite/ld-plugin/lto-15a.c b/ld/testsuite/ld-plugin/lto-15a.c
new file mode 100644
index 0000000..c4ce5e9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-15a.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ printf ("PASS\n");
+ return (int) ((unsigned long long) argc / argv[0][0]);
+}
diff --git a/ld/testsuite/ld-plugin/lto-15b.c b/ld/testsuite/ld-plugin/lto-15b.c
new file mode 100644
index 0000000..0ae748d
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-15b.c
@@ -0,0 +1,7 @@
+extern void abort (void);
+unsigned long long
+__udivdi3(unsigned long long n, unsigned long long d)
+{
+ abort ();
+ return n + d;
+}
diff --git a/ld/testsuite/ld-plugin/lto-16a.c b/ld/testsuite/ld-plugin/lto-16a.c
new file mode 100644
index 0000000..aa1cbe2
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-16a.c
@@ -0,0 +1 @@
+void foo (void) { }
diff --git a/ld/testsuite/ld-plugin/lto-16a.d b/ld/testsuite/ld-plugin/lto-16a.d
new file mode 100644
index 0000000..76ff1f6
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-16a.d
@@ -0,0 +1,3 @@
+#...
+[0-9a-f]+ T foo
+#...
diff --git a/ld/testsuite/ld-plugin/lto-16b.c b/ld/testsuite/ld-plugin/lto-16b.c
new file mode 100644
index 0000000..31781e8
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-16b.c
@@ -0,0 +1,4 @@
+void
+bar ()
+{
+}
diff --git a/ld/testsuite/ld-plugin/lto-16b.d b/ld/testsuite/ld-plugin/lto-16b.d
new file mode 100644
index 0000000..5c0e148
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-16b.d
@@ -0,0 +1,3 @@
+#...
+[0-9a-f]+ T bar
+#...
diff --git a/ld/testsuite/ld-plugin/lto-17a.c b/ld/testsuite/ld-plugin/lto-17a.c
new file mode 100644
index 0000000..7de81b3
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-17a.c
@@ -0,0 +1,4 @@
+void
+bar (void)
+{
+}
diff --git a/ld/testsuite/ld-plugin/lto-17a.d b/ld/testsuite/ld-plugin/lto-17a.d
new file mode 100644
index 0000000..5c0e148
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-17a.d
@@ -0,0 +1,3 @@
+#...
+[0-9a-f]+ T bar
+#...
diff --git a/ld/testsuite/ld-plugin/lto-17b-1.d b/ld/testsuite/ld-plugin/lto-17b-1.d
new file mode 100644
index 0000000..c8f4339
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-17b-1.d
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f]+ . bar
+#...
diff --git a/ld/testsuite/ld-plugin/lto-17b-2.d b/ld/testsuite/ld-plugin/lto-17b-2.d
new file mode 100644
index 0000000..76ff1f6
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-17b-2.d
@@ -0,0 +1,3 @@
+#...
+[0-9a-f]+ T foo
+#...
diff --git a/ld/testsuite/ld-plugin/lto-17b.c b/ld/testsuite/ld-plugin/lto-17b.c
new file mode 100644
index 0000000..f129c90
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-17b.c
@@ -0,0 +1,6 @@
+extern void bar(void) __attribute__((__visibility__("hidden")));
+
+void foo (void)
+{
+ bar ();
+}
diff --git a/ld/testsuite/ld-plugin/lto-1a.c b/ld/testsuite/ld-plugin/lto-1a.c
new file mode 100644
index 0000000..b775d0a
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-1a.c
@@ -0,0 +1,4 @@
+unsigned long long bar (unsigned long long y)
+{
+ return 30 / y;
+}
diff --git a/ld/testsuite/ld-plugin/lto-1b.c b/ld/testsuite/ld-plugin/lto-1b.c
new file mode 100644
index 0000000..8a961ef
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-1b.c
@@ -0,0 +1,8 @@
+extern unsigned long long bar (unsigned long long);
+
+int
+main (int argc, char **argv)
+{
+ unsigned long long d = bar ((unsigned long long) (argc + 1));
+ return d;
+}
diff --git a/ld/testsuite/ld-plugin/lto-2.c b/ld/testsuite/ld-plugin/lto-2.c
new file mode 100644
index 0000000..f0eacf4
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-2.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+int
+main (int argc, char **argv)
+{
+ int d = atoi (argv[1]);
+ printf ("%f\n", sin (d));
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-3.d b/ld/testsuite/ld-plugin/lto-3.d
new file mode 100644
index 0000000..c3a9a16
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3.d
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f]+ T foo
+#...
diff --git a/ld/testsuite/ld-plugin/lto-3.out b/ld/testsuite/ld-plugin/lto-3.out
new file mode 100644
index 0000000..a69f8f3
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3.out
@@ -0,0 +1,2 @@
+hello foo
+hello bar
diff --git a/ld/testsuite/ld-plugin/lto-3a.c b/ld/testsuite/ld-plugin/lto-3a.c
new file mode 100644
index 0000000..5193972
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3a.c
@@ -0,0 +1,9 @@
+extern void foo(void);
+extern void bar(void);
+
+int main(void)
+{
+ foo();
+ bar();
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-3b.c b/ld/testsuite/ld-plugin/lto-3b.c
new file mode 100644
index 0000000..c24f6d4
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3b.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void foo(void)
+{
+ printf ("hello foo\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-3c.c b/ld/testsuite/ld-plugin/lto-3c.c
new file mode 100644
index 0000000..95b3bc0
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3c.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void bar(void)
+{
+ printf ("hello bar\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-3r.d b/ld/testsuite/ld-plugin/lto-3r.d
new file mode 100644
index 0000000..1d1befe
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3r.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-3b.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-5.d b/ld/testsuite/ld-plugin/lto-5.d
new file mode 100644
index 0000000..c3a9a16
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-5.d
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f]+ T foo
+#...
diff --git a/ld/testsuite/ld-plugin/lto-5.out b/ld/testsuite/ld-plugin/lto-5.out
new file mode 100644
index 0000000..dfbb215
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-5.out
@@ -0,0 +1 @@
+hello foo
diff --git a/ld/testsuite/ld-plugin/lto-5a.c b/ld/testsuite/ld-plugin/lto-5a.c
new file mode 100644
index 0000000..2d07cf5
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-5a.c
@@ -0,0 +1,7 @@
+extern void foo(void);
+
+int main(void)
+{
+ foo();
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-5b.c b/ld/testsuite/ld-plugin/lto-5b.c
new file mode 100644
index 0000000..c24f6d4
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-5b.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void foo(void)
+{
+ printf ("hello foo\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-5r.d b/ld/testsuite/ld-plugin/lto-5r.d
new file mode 100644
index 0000000..43e9a5c
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-5r.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-5a.o tmpdir/lto-5b.o
+#source: dummy.s
+#nm: -p
+
+#...
+[0-9a-f]+ C __gnu_lto_v.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-6.c b/ld/testsuite/ld-plugin/lto-6.c
new file mode 100644
index 0000000..749e4e0
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-6.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+extern char _etext[];
+
+int main(void)
+{
+ printf ("%p: %d\n", _etext, _etext[0]);
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-7.out b/ld/testsuite/ld-plugin/lto-7.out
new file mode 100644
index 0000000..d86bac9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-7.out
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-plugin/lto-7a.c b/ld/testsuite/ld-plugin/lto-7a.c
new file mode 100644
index 0000000..d277a43
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-7a.c
@@ -0,0 +1,14 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+int foo = -1;
+
+extern void bar ();
+
+int
+main (int argc, char **argv)
+{
+ bar ();
+ printf ("OK\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-7b.c b/ld/testsuite/ld-plugin/lto-7b.c
new file mode 100644
index 0000000..1798130
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-7b.c
@@ -0,0 +1,8 @@
+extern int foo;
+
+static void
+__attribute__ ((unused, constructor))
+set_foo (void)
+{
+ foo = 30;
+}
diff --git a/ld/testsuite/ld-plugin/lto-7c.c b/ld/testsuite/ld-plugin/lto-7c.c
new file mode 100644
index 0000000..5236f57
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-7c.c
@@ -0,0 +1,9 @@
+extern int foo;
+extern int foo2;
+
+static void
+__attribute__ ((unused, constructor))
+set_foo (void)
+{
+ foo = foo2;
+}
diff --git a/ld/testsuite/ld-plugin/lto-7d.c b/ld/testsuite/ld-plugin/lto-7d.c
new file mode 100644
index 0000000..7fc1ff1
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-7d.c
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+
+extern int foo;
+int foo2 = 2;
+
+void
+bar (void)
+{
+ if (foo != 30)
+ abort ();
+}
diff --git a/ld/testsuite/ld-plugin/lto-8.out b/ld/testsuite/ld-plugin/lto-8.out
new file mode 100644
index 0000000..35c5d69
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-8.out
@@ -0,0 +1 @@
+baz: 42
diff --git a/ld/testsuite/ld-plugin/lto-8a.c b/ld/testsuite/ld-plugin/lto-8a.c
new file mode 100644
index 0000000..6901fb3
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-8a.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+void baz(int i)
+{
+ printf ("baz: %d\n", i);
+}
+
+int main(void)
+{
+ foo(42);
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-8b.c b/ld/testsuite/ld-plugin/lto-8b.c
new file mode 100644
index 0000000..3b6db5f
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-8b.c
@@ -0,0 +1,14 @@
+extern int bar(void) __attribute__((__visibility__("hidden"), __const__));
+extern void baz(int);
+
+void foo(char c)
+{
+ int i;
+
+ if (bar())
+ i = c;
+ else
+ i = c;
+
+ baz(i);
+}
diff --git a/ld/testsuite/ld-plugin/lto-9.cc b/ld/testsuite/ld-plugin/lto-9.cc
new file mode 100644
index 0000000..2a4dcde
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-9.cc
@@ -0,0 +1,9 @@
+struct Foooo {
+ virtual ~Foooo () { }
+};
+
+int main(void)
+{
+ Foooo t;
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-9.d b/ld/testsuite/ld-plugin/lto-9.d
new file mode 100644
index 0000000..4b5bcf8
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-9.d
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f]+ . .*Foooo::Foooo.*
+#...
diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
new file mode 100644
index 0000000..92932f3
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto.exp
@@ -0,0 +1,342 @@
+# Expect script for ld-plugin LTO tests
+# Copyright 2011
+# 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.
+
+# These tests require plugin and LTO.
+if { ![check_plugin_api_available]
+ || ![check_lto_available] } {
+ return
+}
+
+# Simple LTO tests and generate input files for complex LTO tests.
+set lto_link_tests {
+ {"LTO 1"
+ "-O2 -flto -fuse-linker-plugin" "-flto -fuse-linker-plugin"
+ {lto-1a.c lto-1b.c} {} "lto-1.exe"}
+ {"Build libdummy.a 2"
+ "" "-O2 -flto -fuse-linker-plugin"
+ {lto-2.c} {} "libdummy.a"}
+ {"LTO 2"
+ "-static -O2 -flto -fuse-linker-plugin tmpdir/lto-2.o -lm" ""
+ {dummy.c} {} "lto-2.exe"}
+ {"Build libdummy.a 3a"
+ "" "-flto"
+ {lto-3a.c} {} "libdummy.a"}
+ {"Build libdummy.a 3c"
+ "" "-O2"
+ {lto-3c.c} {} "libdummy.a"}
+ {"Build liblto-3.a"
+ "" "-flto"
+ {lto-3b.c} {} "liblto-3.a"}
+ {"Build libdummy.a 4a"
+ "" "-flto"
+ {lto-4a.c} {} "libdummy.a"}
+ {"Build libdummy.a 4b"
+ "" "-O2"
+ {lto-4b.c} {} "libdummy.a"}
+ {"Build libdummy.a 4c"
+ "" "-O2"
+ {lto-4c.c} {} "libdummy.a"}
+ {"Build libdummy.a 5a"
+ "" "-flto"
+ {lto-5a.c} {} "libdummy.a"}
+ {"Build libdummy.a 5b"
+ "" "-flto"
+ {lto-5b.c} {} "libdummy.a"}
+ {"LTO 6"
+ "-O2 -flto -fuse-linker-plugin" ""
+ {lto-6.c} {} "lto-6.exe" "c"}
+ {"Build libdummy.a PR ld/12365"
+ "" "-flto -O2"
+ {pr12365a.c pr12365b.c pr12365c.c} {} "libdummy.a"}
+ {"Build libdummy.a 9"
+ "" "-O2 -flto"
+ {lto-9.cc} {} "libdummy.a"}
+ {"Build libdummy.a 10a"
+ "" "-O2"
+ {lto-10a.c} {} "libdummy.a"}
+ {"Build libdummy.a 10b"
+ "" "-O2 -flto"
+ {lto-10b.c} {} "libdummy.a"}
+ {"Build libdummy.a 11a"
+ "" "-O -flto"
+ {lto-11a.c} {} "libdummy.a"}
+ {"Build libdummy.a 11b"
+ "" "-O -flto"
+ {lto-11b.c} {} "libdummy.a"}
+ {"Build libdummy.a 11c"
+ "" "-O"
+ {lto-11c.c} {} "libdummy.a"}
+ {"Build liblto-12.a"
+ "" "-O2 -flto"
+ {lto-12c.c} {} "liblto-12.a"}
+ {"Build libdummy.a 12"
+ "" "-O2 -flto"
+ {lto-12a.c lto-12b.c} {} "libdummy.a"}
+ {"Build libdummy.a 13"
+ "" "-O2 -flto"
+ {lto-13a.c lto-13b.c} {} "libdummy.a"}
+ {"Build liblto-13.a"
+ "" "-O2"
+ {lto-13c.c} {} "liblto-13.a"}
+ {"Build libdummy.a 14a"
+ "" "-flto"
+ {lto-14a.c lto-14b.c} {} "libdummy.a"}
+ {"Build liblto-14.a"
+ "" "-flto"
+ {lto-14c.c} {} "liblto-14.a"}
+ {"Build libdummy.a 15a"
+ "" "-flto"
+ {lto-15a.c} {} "libdummy.a"}
+ {"Build liblto-15.a"
+ "" "-flto"
+ {lto-15b.c} {} "liblto-15.a"}
+ {"PR ld/12696"
+ "-O2 -flto -fuse-linker-plugin -r -nostdlib" "-O2 -flto"
+ {pr12696-1.cc} {} "pr12696-1r.o" "c"}
+ {"Build libdummy.a PR ld/12758"
+ "" ""
+ {pr12758a.s} {} "libdummy.a"}
+ {"Build libpr12758.a"
+ "" "-flto -O2"
+ {pr12758b.c} {} "libpr12758.a"}
+ {"PR ld/12758"
+ "-O2 -Wl,-e,foo -nostdlib -flto -fuse-linker-plugin tmpdir/pr12758a.o -Wl,--start-group tmpdir/libpr12758.a -Wl,--end-group" ""
+ {dummy.c} {} "pr12758.exe"}
+ {"Build libdummy.a PR ld/12760"
+ "" ""
+ {pr12760a.c} {} "libdummy.a"}
+ {"Build libpr12760.a"
+ "" "-flto -O2"
+ {pr12760b.c} {} "libpr12760.a"}
+ {"PR ld/12760"
+ "-O2 -Wl,-e,foo -nostdlib -flto -fuse-linker-plugin tmpdir/pr12760a.o -Wl,--start-group tmpdir/libpr12760.a -Wl,--end-group" ""
+ {dummy.c} {} "pr12760.exe"}
+ {"Build libdummy.a PR ld/12942 (1)"
+ "" "-flto -O2"
+ {pr12942a.cc pr12942c.cc} {} "libdummy.a" "c++"}
+ {"Build libdummy.a PR ld/12942 (2)"
+ "" "-O0"
+ {pr12942b.cc} {} "libdummy.a" "c++"}
+ {"Build libpr13183.a"
+ "-T" "-flto -O2"
+ {pr13183a.c} {} "libpr13183.a"}
+ {"Build libdummy.a PR ld/13183"
+ "" "-flto -O2"
+ {pr13183b.c} {} "libdummy.a"}
+ {"Build libdummy.a PR ld/13201"
+ "" "-flto -O2"
+ {pr13201.c} {} "libdummy.a"}
+ {"PR ld/13287"
+ "-flto -fuse-linker-plugin -Wl,--as-needed" "-flto"
+ {pr13287.cc} {} "pr13287.exe" "c++"}
+}
+
+# Generate input files for complex LTO tests for ELF.
+set lto_link_elf_tests {
+ {"Build libdummy.a 7"
+ "" "-flto -O2"
+ {lto-7a.c lto-7b.c lto-7c.c} {} "libdummy.a"}
+ {"Build liblto-7.so"
+ "-shared" "-O2 -fpic"
+ {lto-7d.c} {} "liblto-7.so" "c"}
+ {"Build libdummy.a 8a"
+ "" "-O2"
+ {lto-8a.c} {} "libdummy.a"}
+ {"Build libdummy.a 8b"
+ "" "-flto -O2"
+ {lto-8b.c} {} "libdummy.a"}
+ {"Build liblto-17a.so"
+ "-shared -O2 -fpic -flto -fuse-linker-plugin" "-O2 -fpic -flto"
+ {lto-17a.c} {{"nm" {} "lto-17a.d"}} "liblto-17a.so" "c"}
+ {"Build liblto-17b.so 1"
+ "-shared -O2 -fpic -flto -fuse-linker-plugin tmpdir/lto-17a.o" "-O2 -fpic -flto"
+ {lto-17b.c} {{"nm" {} "lto-17b-1.d"}} "liblto-17b.so"}
+ {"Build liblto-17b.so 2"
+ "-shared -O2 -fpic -flto -fuse-linker-plugin tmpdir/lto-17a.o" "-O2 -fpic -flto"
+ {lto-17b.c} {{"nm" {} "lto-17b-2.d"}} "liblto-17b.so"}
+ {"PR ld/12982"
+ "-O2 -flto -fuse-linker-plugin" "-O2 -flto"
+ {pr12982.c} {{"readelf" {-l --wide} "pr12982.d"}} "pr12982.exe"}
+ {"PR ld/12975"
+ "-shared -O2 -fPIC -flto -fuse-linker-plugin -nostdlib -Wl,-version-script,pr12975.t" "-O2 -flto"
+ {pr12975.c} {{"readelf" {-s --wide} "pr12975.d"}} "pr12975.so" "c"}
+ {"PR ld/13229"
+ "-shared -O2 -fPIC -flto -fuse-linker-plugin -nostdlib" "-O2 -fno-early-inlining -flto"
+ {pr13229.cc} {{"readelf" {-s --wide} "pr13229.d"}} "pr13229.so" "c++"}
+ {"PR ld/13244"
+ "-shared -O2 -fPIC -flto -fuse-linker-plugin -nostdlib" "-O2 -fno-early-inlining -flto"
+ {pr13244.c} {{"readelf" {-s --wide} "pr13244.d"}} "pr13244.so" "c"}
+}
+
+# Check final symbols in executables.
+set lto_link_symbol_tests {
+ {"LTO 3 symbol"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o tmpdir/liblto-3.a" ""
+ {dummy.c} {{"nm" {} "lto-3.d"}} "lto-3.exe" "c"}
+ {"LTO 5 symbol"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-5.o" ""
+ {dummy.c} {{"nm" {} "lto-5.d"}} "lto-5.exe" "c"}
+ {"LTO 9 symbol"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-9.o" ""
+ {dummy.c} {{"nm" {-C} "lto-9.d"}} "lto-9.exe" "c++"}
+ {"LTO 16a symbol"
+ "-O2 -Wl,-e,foo -nostdlib -flto -fuse-linker-plugin" "-flto"
+ {lto-16a.c} {{"nm" {} "lto-16a.d"}} "lto-16.exe" "c"}
+ {"LTO 16b symbol"
+ "-O2 -Wl,-e,foo -u bar -nostdlib -flto -fuse-linker-plugin" "-flto"
+ {lto-16a.c lto-16b.c} {{"nm" {} "lto-16b.d"}} "lto-16b.exe" "c"}
+ {"PR ld/13183"
+ "-O2 -flto -fuse-linker-plugin tmpdir/pr13183b.o tmpdir/libpr13183.a" ""
+ {dummy.c} {{"nm" {} "pr13183.d"}} "pr13183.exe" "c"}
+}
+
+# LTO run-time tests.
+set lto_run_tests {
+ {"LTO 3a"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o tmpdir/liblto-3.a" ""
+ {dummy.c} "lto-3b.exe" "lto-3.out" "" "c"}
+ {"LTO 3b"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o tmpdir/lto-3.o" ""
+ {dummy.c} "lto-3c.exe" "lto-3.out" "" "c"}
+ {"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"}
+ {"LTO 4a"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-a.o" ""
+ {dummy.c} "lto-4a.exe" "lto-4.out" "" "c"}
+ {"LTO 4c"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-c.o" ""
+ {dummy.c} "lto-4c.exe" "lto-4.out" "" "c"}
+ {"LTO 4d"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-d.o" ""
+ {dummy.c} "lto-4d.exe" "lto-4.out" "" "c"}
+ {"LTO 5"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-5.o" ""
+ {dummy.c} "lto-5.exe" "lto-5.out" "" "c"}
+ {"LTO 10"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-10.o" ""
+ {dummy.c} "lto-10.exe" "lto-10.out" "" "c"}
+ {"LTO 11"
+ "-O -flto -fuse-linker-plugin tmpdir/liblto-11.a" ""
+ {dummy.c} "lto-11.exe" "lto-11.out" "" "c"}
+ {"LTO 12a"
+ "-O -flto -fuse-linker-plugin tmpdir/lto-12a.o tmpdir/liblto-12.a tmpdir/lto-12b.o" ""
+ {dummy.c} "lto-12a.exe" "lto-12.out" "" "c"}
+ {"LTO 12b"
+ "-O -flto -fuse-linker-plugin tmpdir/lto-12a.o tmpdir/lto-12b.o tmpdir/liblto-12.a" ""
+ {dummy.c} "lto-12b.exe" "lto-12.out" "" "c"}
+ {"LTO 13"
+ "-O -flto -fuse-linker-plugin tmpdir/lto-13a.o tmpdir/liblto-13.a tmpdir/lto-13b.o" ""
+ {dummy.c} "lto-13.exe" "lto-13.out" "" "c"}
+ {"LTO 14"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-14a.o -Wl,--whole-archive tmpdir/liblto-14.a -Wl,--no-whole-archive tmpdir/lto-14b.o" ""
+ {dummy.c} "lto-14.exe" "lto-14.out" "" "c"}
+ {"LTO 15"
+ "-O2 -flto -fuse-linker-plugin -Wl,--start-group tmpdir/lto-15a.o tmpdir/liblto-15.a -Wl,--end-group" ""
+ {dummy.c} "lto-15.exe" "lto-15.out" "" "c"}
+ {"PR ld/12942 (1)"
+ "-O2 -flto -fuse-linker-plugin tmpdir/pr12942a.o tmpdir/pr12942b.o" ""
+ {dummy.c} "pr12942a.exe" "pr12942.out" "" "c++"}
+ {"PR ld/12942 (2)"
+ "-O2 -flto -fuse-linker-plugin tmpdir/pr12942a.o tmpdir/pr12942c.o" ""
+ {dummy.c} "pr12942c.exe" "pr12942.out" "" "c++"}
+ {"PR ld/13066"
+ "-O2 -flto -fuse-linker-plugin" ""
+ {pr13066.cc} "pr13066.exe" "pr13066.out" "" "c++"}
+ {"PR ld/13201"
+ "-O2 -flto -fuse-linker-plugin -Wl,--as-needed tmpdir/pr13201.o -lm" ""
+ {dummy.c} "pr13201.exe" "pr13201.out" "" "c"}
+}
+
+# LTO run-time tests for ELF
+set lto_run_elf_tests {
+ {"LTO 7"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-7b.o tmpdir/lto-7c.o tmpdir/lto-7a.o tmpdir/liblto-7.so" ""
+ {dummy.c} "lto-7.exe" "lto-7.out" "" "c"}
+ {"LTO 8"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-8b.o tmpdir/lto-8a.o" ""
+ {dummy.c} "lto-8.exe" "lto-8.out" "" "c"}
+ {"LTO TLS IE"
+ "-O2 -flto -fuse-linker-plugin" ""
+ {run-ie.c} "run-ie.exe" "run-ie.out" "" "c"}
+}
+
+run_cc_link_tests $lto_link_tests
+
+if { [is_elf_format] } {
+ run_cc_link_tests $lto_link_elf_tests
+}
+
+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
+ return
+}
+
+set testname "Build liblto-11.a"
+remote_file host delete "tmpdir/liblto-11.a"
+set catch_output [run_host_cmd "$ar" "rc tmpdir/liblto-11.a tmpdir/lto-11a.o tmpdir/lto-11b.o tmpdir/lto-11c.o"]
+if {![string match "" $catch_output]} {
+ unresolved $testname
+ return
+}
+
+# Check expected LTO linker errors.
+set testname "PR ld/12365"
+set exec_output [run_host_cmd "$CC" "$gcc_gas_flag $gcc_ld_flag -O2 -flto -fuse-linker-plugin tmpdir/pr12365a.o tmpdir/pr12365b.o tmpdir/pr12365c.o"]
+if { [ regexp "`my_bcopy' referenced in .* defined in discarded section" $exec_output ] } {
+ pass $testname
+} {
+ fail $testname
+}
+set testname "PR ld/12942 (3)"
+set exec_output [run_host_cmd "$CXX" "$gcc_gas_flag $gcc_ld_flag -O2 -flto -fuse-linker-plugin tmpdir/pr12942b.o tmpdir/pr12942a.o"]
+if { [ regexp "pr12942a.h:7: undefined reference to `link_error\\(\\)'" $exec_output ] } {
+ pass $testname
+} {
+ fail $testname
+}
+
+# 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"
+
+run_cc_link_tests $lto_link_symbol_tests
+
+run_ld_link_exec_tests [] $lto_run_tests
+
+if { [is_elf_format] } {
+ run_ld_link_exec_tests [] $lto_run_elf_tests
+}
diff --git a/ld/testsuite/ld-plugin/plugin.exp b/ld/testsuite/ld-plugin/plugin.exp
index d28505d..803ccee 100644
--- a/ld/testsuite/ld-plugin/plugin.exp
+++ b/ld/testsuite/ld-plugin/plugin.exp
@@ -157,7 +157,11 @@
-plugin-opt sym:${_}func3::0:3:0 \
-plugin-opt dumpresolutions \
-plugin-opt add:tmpdir/func.o \
- $testobjfiles $libs --verbose=2" "" "" {{ld plugin-12.d}} "main.x" ] \
+ -plugin-opt add:tmpdir/func1p.o \
+ -plugin-opt add:tmpdir/func2i.o \
+ -plugin-opt add:tmpdir/func3h.o \
+ $testobjfiles $libs --verbose=2" "" "" {{ld plugin-12.d} \
+ {readelf -s plugin-vis-1.d}} "main.x" ] \
]
if { !$can_compile || $failed_compile } {
@@ -174,7 +178,10 @@
run_ld_link_tests $plugin_tests
-if { [is_elf_format] } {
+if { [is_elf_format] \
+ && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func1p.c tmpdir/func1p.o] \
+ && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func2i.c tmpdir/func2i.o] \
+ && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func3h.c tmpdir/func3h.o] } {
run_ld_link_tests $plugin_extra_elf_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..3e86e06
--- /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/pr12696-1.cc b/ld/testsuite/ld-plugin/pr12696-1.cc
new file mode 100644
index 0000000..084c07f
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12696-1.cc
@@ -0,0 +1,7 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options {{-ftoplevel-reorder -flto -flto-partition=none} {-ftoplevel-reorder -flto -flto-partition=1to1}} } */
+/* { dg-extra-ld-options {-r -nostdlib} } */
+
+struct Foo { virtual ~Foo(); };
+struct Bar:public Foo { Bar() { } };
+void Func() { new Bar(); }
diff --git a/ld/testsuite/ld-plugin/pr12758a.s b/ld/testsuite/ld-plugin/pr12758a.s
new file mode 100644
index 0000000..04409d0
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12758a.s
@@ -0,0 +1,4 @@
+ .text
+ .globl foo
+foo:
+ .dc.a memcmp
diff --git a/ld/testsuite/ld-plugin/pr12758b.c b/ld/testsuite/ld-plugin/pr12758b.c
new file mode 100644
index 0000000..5bcf116
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12758b.c
@@ -0,0 +1,12 @@
+#include <string.h>
+
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+ const unsigned char *su1, *su2;
+ int res = 0;
+
+ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
diff --git a/ld/testsuite/ld-plugin/pr12760a.c b/ld/testsuite/ld-plugin/pr12760a.c
new file mode 100644
index 0000000..6169c26
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12760a.c
@@ -0,0 +1,7 @@
+extern void bar ();
+
+void
+foo ()
+{
+ bar ();
+}
diff --git a/ld/testsuite/ld-plugin/pr12760b.c b/ld/testsuite/ld-plugin/pr12760b.c
new file mode 100644
index 0000000..29a9fd8
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12760b.c
@@ -0,0 +1,7 @@
+#define linker_warning(x, msg) \
+ static const char __warn_##x[] \
+ __attribute__((used, section(".gnu.warning." #x))) \
+ = msg
+
+void bar (void) {}
+linker_warning(bar, "Bad bar");
diff --git a/ld/testsuite/ld-plugin/pr12942.out b/ld/testsuite/ld-plugin/pr12942.out
new file mode 100644
index 0000000..d86bac9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12942.out
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-plugin/pr12942a.cc b/ld/testsuite/ld-plugin/pr12942a.cc
new file mode 100644
index 0000000..1a18404
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12942a.cc
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include "pr12942a.h"
+
+extern "C" void abort ();
+
+test_t b(void);
+
+int
+main(void)
+{
+ if (test != b ())
+ abort ();
+
+ printf ("OK\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/pr12942a.h b/ld/testsuite/ld-plugin/pr12942a.h
new file mode 100644
index 0000000..760929b
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12942a.h
@@ -0,0 +1,12 @@
+extern void link_error ();
+
+inline int test (void)
+{
+ int exp = -1;
+ if ((exp < 2 ? 2U : (unsigned int) exp) != 2)
+ link_error ();
+
+ return 0;
+}
+
+typedef int (*test_t) (void);
diff --git a/ld/testsuite/ld-plugin/pr12942b.cc b/ld/testsuite/ld-plugin/pr12942b.cc
new file mode 100644
index 0000000..387954e
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12942b.cc
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include "pr12942a.h"
+
+test_t b(void)
+{
+ return test;
+}
diff --git a/ld/testsuite/ld-plugin/pr12942c.cc b/ld/testsuite/ld-plugin/pr12942c.cc
new file mode 100644
index 0000000..9b07231
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12942c.cc
@@ -0,0 +1 @@
+#include "pr12942b.cc"
diff --git a/ld/testsuite/ld-plugin/pr12975.c b/ld/testsuite/ld-plugin/pr12975.c
new file mode 100644
index 0000000..909af97
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12975.c
@@ -0,0 +1,7 @@
+int foo() { return 42; }
+
+int bar() { return 0; }
+
+#pragma GCC visibility push(hidden)
+int baz() { return 1; }
+#pragma GCC visibility pop
diff --git a/ld/testsuite/ld-plugin/pr12975.d b/ld/testsuite/ld-plugin/pr12975.d
new file mode 100644
index 0000000..7fcff80
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12975.d
@@ -0,0 +1,4 @@
+#failif
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +LOCAL +DEFAULT +[1-9]+ bar
+#...
diff --git a/ld/testsuite/ld-plugin/pr12975.t b/ld/testsuite/ld-plugin/pr12975.t
new file mode 100644
index 0000000..902c1f7
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12975.t
@@ -0,0 +1,6 @@
+{
+global:
+ foo;
+local:
+ *;
+};
diff --git a/ld/testsuite/ld-plugin/pr12982.c b/ld/testsuite/ld-plugin/pr12982.c
new file mode 100644
index 0000000..398ec67
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12982.c
@@ -0,0 +1,5 @@
+int
+main (void)
+{
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/pr12982.d b/ld/testsuite/ld-plugin/pr12982.d
new file mode 100644
index 0000000..f536d5b
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12982.d
@@ -0,0 +1,3 @@
+#...
+[ \t]+GNU_STACK[ \t]+0x[0-9a-f]+ +0x[0-9a-f]+ +0x[0-9a-f]+ +0x[0-9a-f]+ +0x[0-9a-f]+ +RW +0x[0-9a-f]+
+#pass
diff --git a/ld/testsuite/ld-plugin/pr13066.cc b/ld/testsuite/ld-plugin/pr13066.cc
new file mode 100644
index 0000000..b2c73f2
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13066.cc
@@ -0,0 +1,85 @@
+#include <stdio.h>
+
+template <typename V> struct S
+{
+ V *f, *l;
+ __attribute__ ((noinline)) S (void) { f = 0, l = 0; }
+ void foo (V *x)
+ {
+ if (x->p != 0)
+ x->p->n = x->n;
+ else
+ f = x->n;
+ if (x->n != 0)
+ x->n->p = x->p;
+ else
+ l = x->p;
+ }
+ __attribute__ ((noinline)) void bar (V *x)
+ {
+ x->n = 0;
+ x->p = l;
+ if (l != 0)
+ l->n = x;
+ else
+ f = x;
+ l = x;
+ }
+};
+
+struct H;
+
+struct A
+{
+ S <H> k;
+};
+
+struct H
+{
+ A *a;
+ H *p, *n;
+ __attribute__ ((noinline)) H (void) { p = 0, n = 0, a = 0; }
+ __attribute__ ((noinline)) H (A *b) : a (b)
+ {
+ p = 0;
+ n = 0;
+ if (a != 0)
+ a->k.bar (this);
+ }
+ __attribute__ ((noinline)) H (const H &h) : a (h.a)
+ {
+ p = 0;
+ n = 0;
+ if (a != 0)
+ a->k.bar (this);
+ }
+ ~H (void) { if (a != 0) a->k.foo (this); }
+ H &operator= (const H &o)
+ {
+ if (a != 0 || &o == this)
+ __builtin_abort ();
+ a = o.a;
+ if (a != 0)
+ a->k.bar (this);
+ return *this;
+ }
+};
+
+__attribute__ ((noinline))
+H baz (void)
+{
+ return H (new A);
+}
+
+H g;
+
+int
+main (void)
+{
+ g = baz ();
+ if (g.a->k.f != &g)
+ __builtin_abort ();
+ printf ("OK\n");
+ return 0;
+}
+
diff --git a/ld/testsuite/ld-plugin/pr13066.out b/ld/testsuite/ld-plugin/pr13066.out
new file mode 100644
index 0000000..d86bac9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13066.out
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-plugin/pr13183.d b/ld/testsuite/ld-plugin/pr13183.d
new file mode 100644
index 0000000..a390282
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13183.d
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f]+ . foo
+#...
diff --git a/ld/testsuite/ld-plugin/pr13183a.c b/ld/testsuite/ld-plugin/pr13183a.c
new file mode 100644
index 0000000..c83d856
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13183a.c
@@ -0,0 +1,4 @@
+int foo(void)
+{
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/pr13183b.c b/ld/testsuite/ld-plugin/pr13183b.c
new file mode 100644
index 0000000..93d57b5
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13183b.c
@@ -0,0 +1,6 @@
+extern int foo(void);
+
+int main(void)
+{
+ return foo();
+}
diff --git a/ld/testsuite/ld-plugin/pr13201.c b/ld/testsuite/ld-plugin/pr13201.c
new file mode 100644
index 0000000..8cfc50c
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13201.c
@@ -0,0 +1,16 @@
+#include <math.h>
+#include <stdio.h>
+
+int
+main(int argc, char **argv)
+{
+ double x;
+ if (argc > 1)
+ x = atof (argv[1]);
+ else
+ x = 3;
+ x = sin (x);
+ if (x > 0)
+ printf("OK\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/pr13201.out b/ld/testsuite/ld-plugin/pr13201.out
new file mode 100644
index 0000000..d86bac9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13201.out
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-plugin/pr13229.cc b/ld/testsuite/ld-plugin/pr13229.cc
new file mode 100644
index 0000000..f584982
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13229.cc
@@ -0,0 +1,15 @@
+int call_something (int);
+inline void optimize_me_out (void)
+{
+ call_something(0);
+}
+__attribute__ ((visibility("hidden")))
+int optimize_me_out2 (int param)
+{
+ if ((void *)optimize_me_out != (void *)call_something)
+ return call_something(0);
+}
+void test2 (void)
+{
+ optimize_me_out();
+}
diff --git a/ld/testsuite/ld-plugin/pr13229.d b/ld/testsuite/ld-plugin/pr13229.d
new file mode 100644
index 0000000..017a716
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13229.d
@@ -0,0 +1,4 @@
+#failif
+#...
+.*optimize_me_out.*
+#...
diff --git a/ld/testsuite/ld-plugin/pr13244.c b/ld/testsuite/ld-plugin/pr13244.c
new file mode 100644
index 0000000..0d6d14a
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13244.c
@@ -0,0 +1,13 @@
+extern __attribute__ ((visibility("hidden"))) int fooblah;
+
+static
+do_nothing (int param)
+{
+ if (param)
+ fooblah = 1;
+}
+
+bar ()
+{
+ do_nothing (0);
+}
diff --git a/ld/testsuite/ld-plugin/pr13244.d b/ld/testsuite/ld-plugin/pr13244.d
new file mode 100644
index 0000000..59bbe4d
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13244.d
@@ -0,0 +1,4 @@
+#failif
+#...
+.*fooblah.*
+#...
diff --git a/ld/testsuite/ld-plugin/pr13287.cc b/ld/testsuite/ld-plugin/pr13287.cc
new file mode 100644
index 0000000..67e8506
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr13287.cc
@@ -0,0 +1 @@
+int main() {return 0; }
diff --git a/ld/testsuite/ld-plugin/run-ie.c b/ld/testsuite/ld-plugin/run-ie.c
new file mode 100644
index 0000000..32afa0a
--- /dev/null
+++ b/ld/testsuite/ld-plugin/run-ie.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+
+extern void abort (void);
+
+__thread int tls_ie __attribute__((tls_model("initial-exec"))) = 4;
+
+int get_ie (void)
+{
+ return tls_ie;
+}
+
+int *get_iep (void)
+{
+ return &tls_ie;
+}
+
+int main (void)
+{
+ int val;
+
+ val = get_ie ();
+ if (val != 4)
+ abort ();
+
+ val = *get_iep ();
+ if (val != 4)
+ abort ();
+
+ printf ("IE: %d\n", val);
+
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/run-ie.out b/ld/testsuite/ld-plugin/run-ie.out
new file mode 100644
index 0000000..7edca6d
--- /dev/null
+++ b/ld/testsuite/ld-plugin/run-ie.out
@@ -0,0 +1 @@
+IE: 4
diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp
index a481ce7..5f21757 100644
--- a/ld/testsuite/lib/ld-lib.exp
+++ b/ld/testsuite/lib/ld-lib.exp
@@ -934,7 +934,7 @@
proc ar_simple_create { ar aropts target objects } {
remote_file host delete $target
- set exec_output [run_host_cmd "$ar" "$aropts rc $target $objects"]
+ set exec_output [run_host_cmd "$ar" "$aropts -rc $target $objects"]
set exec_output [prune_warnings $exec_output]
if [string match "" $exec_output] then {
@@ -1562,6 +1562,34 @@
return $plugin_api_available_saved
}
+# Returns true if the target compiler supports LTO
+proc check_lto_available { } {
+ global lto_available_saved
+ global CC
+ if {![info exists lto_available_saved]} {
+ # Check if gcc supports -flto -fuse-linker-plugin
+ if { [which $CC] == 0 } {
+ set lto_available_saved 0
+ return 0
+ }
+ set basename "lto"
+ set src ${basename}[pid].c
+ set output ${basename}[pid].s
+ set f [open $src "w"]
+ puts $f ""
+ close $f
+ set status [remote_exec host $CC "-S -flto -fuse-linker-plugin $src -o $output"]
+ if { [lindex $status 0] == 0 } {
+ set lto_available_saved 1
+ } else {
+ set lto_available_saved 0
+ }
+ file delete $src
+ file delete $output
+ }
+ return $lto_available_saved
+}
+
# Check if the assembler supports CFI statements.
proc check_as_cfi { } {
diff --git a/release.binutils-2.22.52.0.3 b/release.binutils-2.22.52.0.3
new file mode 100644
index 0000000..219ad2f
--- /dev/null
+++ b/release.binutils-2.22.52.0.3
@@ -0,0 +1,520 @@
+This is the beta release of binutils 2.22.52.0.3 for Linux, which is
+based on binutils 2012 0507 in CVS 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.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.22.52.0.3 to
+hjl.tools@gmail.com
+
+and
+
+http://www.sourceware.org/bugzilla/
+
+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.22.52.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 on linux/release/2.22.52.0.3 branch at
+
+http://git.kernel.org/?p=linux/kernel/git/hjl/binutils.git;a=summary
+
+Thanks.
+
+
+H.J. Lu
+hjl.tools@gmail.com
+05/07/2012